Zabýváme se FreePBX a integrujeme jej s Bitrix24 a nejen to

Bitrix24 — je to obrovský nástroj, který kombinuje CRM, správu dokumentů a účetnictví, a další různé funkce, které se velmi líbí manažerům, ale IT personálům už tolik ne. Portál využívá velké množství malých a středních firem, včetně malých klinik, výrobců a dokonce i kosmetických salonů. Hlavní funkcí, kterou manažeři "milují", je integrace telefonie a CRM, kdy každý telefonní hovor je okamžitě zaznamenán v CRM, vytvářejí se karty zákazníků a při příchozím hovoru se zobrazují informace o zákazníkovi, takže je jasné, kdo je, co mu lze prodat a kolik dluží. Ale telefonie od Bitrix24 a její integrace s CRM něco stojí, někdy nemalé částky. V tomto článku se podělím o zkušenosti s integrací pomocí otevřených nástrojů a populární IP PBX. FreePBX, a také prozkoumám logiku fungování různých částí.

Pracuji na outsourcingu ve firmě, která se zabývá prodejem, nastavením a integrací IP telefonie. Když se mě ptali, zda můžeme té a té firmě nabídnout něco pro integraci Bitrix24 s PBX, které mají u svých klientů, stejně jako s virtuálními PBX na různých VDS firem, šel jsem na Google. A samozřejmě mi vrátil odkaz na článek na Habr, kde jsou popisy, a github, a vypadá to, že vše funguje. Ale když jsem se pokusil tohle řešení použít, ukázalo se, že Bitrix24 již není tím, co býval, a je třeba mnohé předělat. Kromě toho, FreePBX není holý Asterisk, je třeba přemýšlet, jak sladit pohodlí použití s hardcore dial plánem v konfiguračních souborech.

Zkoumáme logiku fungování

Takže nejprve, jak to všechno má fungovat. Při příchozím hovoru z vnějšího zdroje do PBX (událost SIP INVITE od poskytovatele) začíná zpracování dial plánu (dialplan) — pravidel, co a v jakém pořadí s hovorem udělat. Z prvního paketu lze získat spoustu informací, které lze poté použít v pravidlech. Skvělým nástrojem pro zkoumání vnitřností SIP je analyzátor sngrep (odkaz) který se jednoduše instaluje v populárních distribucích přes apt install/yum install a podobně, ale lze ho také sestavit ze zdrojových kódů. Podíváme se na log hovoru v sngrep.

Zabýváme se FreePBX a integrujeme jej s Bitrix24 a nejen to

Zjednodušeně se dialplán zabývá pouze prvním balíčkem, někdy také během hovoru dochází k převodu hovorů, stisků tlačítek (DTMF), různým zajímavostem jako FollowMe, RingGroup, IVR a dalším.

Co je uvnitř balíčku Invite

Zabýváme se FreePBX a integrujeme jej s Bitrix24 a nejen to

Ve skutečnosti většina jednoduchých dialplánů pracuje s prvními dvěma poli a veškerá logika se točí kolem DID a CallerID. DID — kam voláme, CallerID — kdo volá.

Ale máme firmu, ne jen jeden telefon — a to znamená, že v PBX pravděpodobně existují skupiny hovorů (současný/sekvenční hovor několika přístrojů) na městských číslech (Ring Group), IVR (Dobrý den, voláte… Stiskněte jedničku pro…), Hlasové pošty (Phrases), Časové podmínky (Time Conditions), Přesměrování na jiné čísla nebo na mobil (FollowMe, Forward). To znamená, že jednoznačně určit, komu skutečně hovor přijde a s kým bude rozhovor, je velmi obtížné. Zde je příklad začátku průchodu typického hovoru v PBX našich klientů.

Zabýváme se FreePBX a integrujeme jej s Bitrix24 a nejen to

Po úspěšném přijetí hovoru do PBX probíhá jeho cesta dialplánem v různých "kontextech". Kontext z pohledu Asteriska je číselný soubor příkazů, z nichž každý obsahuje filtr podle zadaného čísla (ten se nazývá exten, pro vnější hovor na začátku exten=DID). Příkazy v řádku dialplánu mohou být cokoliv — vnitřní funkce (například zavolat vnitřnímu účastníkovi — Dial(), ukončit hovor — Hangup()), podmínkoví operátory (IF, ELSE, ExecIF a podobně), přechody na jiná pravidla tohoto kontextu (Goto, GotoIF), přechod do jiných kontextů ve formě volání funkcí (Gosub, Macro). Samostatně stojí direktiva include jméno_kontextu, , která přidává příkazy jiného kontextu na konec aktuálního kontextu. Příkazy zahrnuté přes include se vždy vykonávají po příkazech aktuálního kontextu.

Celá logika práce FreePBX je postavena na vzájemném zahrnování různých kontextů přes include a volání přes Gosub, Macro a zpracovatele Handler. Podívejme se na kontext příchozích hovorů FreePBX.

Zabýváme se FreePBX a integrujeme jej s Bitrix24 a nejen to

Hovor prochází všemi kontexty shora dolů postupně, v každém kontextu mohou být volání jiných kontextů jako makra (Macro), funkcí(Gosub) nebo prostě přechody (Goto), a proto skutečné stromové rozložení toho, co je voláno, lze sledovat pouze v logách.

Typická schéma nastavení typické kancelářské PBX je znázorněna níže. Při příjmu hovorů se hledá DID, na jehož základě se kontrolují časové podmínky; pokud je vše v pořádku, spustí se hlasové menu. Z něj je prostřednictvím tlačítka 1 nebo po uplynutí časového limitu přesměrování na skupinu operátorů. Po skončení hovoru se vyvolá makro hangupcall, po kterém již nebude možné v dialplánu provést žádné akce kromě speciálních zpracovatelů (hangup handler).

Zabýváme se FreePBX a integrujeme jej s Bitrix24 a nejen to

Kde v tomto algoritmu hovoru bychom měli posílat informace o začátku hovoru do CRM, kde začít nahrávání, kde končit nahrávání a zasílat to spolu s informacemi o hovoru do CRM?

Integrace s externími systémy

Co je integrace PBX a CRM? Jsou to nastavení a programy, které převádějí data a události mezi těmito dvěma platformami a navzájem si je přenášejí. Nejobvyklejším způsobem interakce nezávislých systémů je API a nejoblíbenějším způsobem přístupu k API je HTTP REST. Ale to neplatí pro Asterisk.

Uvnitř Asterisku jsou:

  • AGI — synchronní volání externích programů/komponentů, používá se hlavně v dialplánu, jsou dostupné knihovny jako phpagi, PAGI

  • AMI — textový TCP socket, který funguje na principu subscribe na události a vstupu textových příkazů, připomíná SMTP zevnitř, dokáže sledovat události a řídit hovory, existuje knihovna PAMI — nejoblíbenější pro vytváření spojení s Asteriskem

Příklad výstupu AMI

Událost: Newchannel
Oprávnění: call, all
Kanál: PJSIP/VMS_pjsip-0000078b
StavKanálu: 4
PopisStavuKanálu: Ring
ČísloVolajícího: 111222
JménoVolajícího: 111222
ČísloPřipojenéLinky:
JménoPřipojenéLinky:
Jazyk: en
KódÚčtu:
Kontext: from-pstn
Exten: s
Priorita: 1
Jedinečnéid: 1599589046.5244
Propojenéid: 1599589046.5244

  • ARI — směs toho a onoho, vše přes REST, WebSocket, ve formátu JSON — ale s novými knihovnami a obaly to moc slavné není, našly se (phparia, phpari) které stagnovaly ve svém vývoji už asi 3 roky.

Příklad výstupu ARI při iniciaci hovoru

{ "variable": "CallMeCallerIDName", "value": "111222", "type": "ChannelVarset", "timestamp": "2020-09-09T09:38:36.269+0000", "channel": { "id": "1599644315.5334", "name": "PJSIP/VMS pjsip-000007b6", "state": "Ring", "caller": { "name": "111222", "number": "111222" }, "connected": { "name": "", "number": "" }, "accountcode": "", "dialplan": { "context": "from-pstn", "exten": "s", "priority": 2, "appname": "Stasis", "appdata": "hello-world" }, "creationtime": "2020-09-09T09:38:35.926+0000", "language": "ru" }, "asteriskid": "48:5b:aa:aa:aa:aa", "application": "hello-world" }id»:»48:5b:aa:aa:aa:aa», «application»:»hello-world» }

Pohodlí nebo nepohodlí, možnost nebo nemožnost práce s konkrétním API se určuje podle úkolů, které je třeba vyřešit. Úkoly pro integraci s CRM jsou následující:

  • Sledovat začátek volání, kam bylo přesměrováno, vyhledat CallerID, DID, časy začátku a konce, případně data z adresáře (k nalezení vztahu mezi telefonem a uživatelem CRM)

  • Zahájit a ukončit nahrávání hovoru, uložit ve správném formátu, po ukončení nahrávání sdělit, kde se soubor nachází

  • Iniciovat hovor na základě externí události (z programu), zavolat na interní číslo, externí a spojit je

  • Volitelně: integrovat s CRM, skupinami volání a FollowME pro automatické přesměrování hovorů v případě nepřítomnosti (na základě informací z CRM)

Všechny tyto úkoly lze řešit prostřednictvím AMI nebo ARI, ale ARI poskytuje mnohem méně informací, chybí mnohé události, nejsou sledovány mnohé proměnné, které v AMI přece jen jsou (například volání makro příkazů, zadávání proměnných uvnitř makro příkazů, včetně nahrávání hovorů). Proto pro správné a přesné sledování zvolíme zatím AMI (ale ne definitivně). Kromě toho (kam by byl svět bez toho, jsme líní lidé) — v původní práci (článek na habru) používají PAMI. *Poté je třeba zkusit přepsat na ARI, ale není jisté, že to půjde.

Vymýšlíme integraci znovu

Aby náš FreePBX mohl jednoduchými způsoby hlásit do AMI začátek hovoru, dobu ukončení, telefonní čísla, jména nahraných souborů a vypočítat délku hovoru, je nejjednodušší využít stejný trik jako původní autoři — zavést si vlastní proměnné a zpracovat výstup na jejich přítomnost. PAMI to umožňuje jednoduše prostřednictvím funkce filtr.

Zde je příklad, jak zadat svou proměnnou pro čas začátku hovoru (s — to je speciální číslo v dialplánu, které se provádí PŘED začátkem vyhledávání podle DID)

[ext-did-custom]

exten => s,1,Set(CallStart=${STRFTIME(epoch,,%s)})

Příklad AMI události na tomto řádku

Událost: Newchannel

Oprávnění: call, all

Kanál: PJSIP/VMS_pjsip-0000078b

StavKanálu: 4

PopisStavuKanálu: Ring

ČísloVolajícího: 111222

JménoVolajícího: 111222

ČísloPřipojenéLinky:

JménoPřipojenéLinky:

Jazyk: en

KódÚčtu:

Kontext: from-pstn

Exten: s

Priorita: 1

Jedinečnéid: 1599589046.5244

Propojenéid: 1599589046.5244

Aplikace: Set AppData:

CallStart=1599571046

Jelikož FreePBX přepisuje soubory extention.conf a extention_additional.conf, budeme používat soubor extention_custom.conf

Kompletní kód extention_custom.conf

[globals]	
;; Zkontrolujte cesty a práva ke složkám - uživatel asterisk musí mít práva pro zápis
;; Zde budou zapisovány rozhovory
WAV=\/var\/www\/html\/callme\/records\/wav 
MP3=\/var\/www\/html\/callme\/records\/mp3

;; Pomocí těchto cest budou přehrávány a stahovány záznamy
URLRECORDS=https:\/\/www.host.ru\/callmeplus\/records\/mp3

;; Adresa pro callback při odchozím hovoru
URLPHP=https:\/\/www.host.ru\/callmeplus

;; Ano, zapisujeme rozhovory
RECORDING=1

;; Toto je makro pro zaznamenávání hovorů do naší složky. 
;; Můžete použít i systémové nahrávání, ale zatím to dejme takto - 
;; funguje to
[recording]
exten => ~~s~~,1,Set(LOCAL(calling)=${ARG1})
exten => ~~s~~,2,Set(LOCAL(called)=${ARG2})
exten => ~~s~~,3,GotoIf($["${RECORDING}" = "1"]?4:14)
exten => ~~s~~,4,Set(fname=${UNIQUEID}-${STRFTIME(${EPOCH},,%Y-%m-%d-%H_%M)}-${calling}-${called})
exten => ~~s~~,5,Set(datedir=${STRFTIME(${EPOCH},,%Y\/%m\/%d)})
exten => ~~s~~,6,System(mkdir -p ${MP3}\/${datedir})
exten => ~~s~~,7,System(mkdir -p ${WAV}\/${datedir})
exten => ~~s~~,8,Set(monopt=nice -n 19 \/usr\/bin\/lame -b 32  --silent "${WAV}\/${datedir}\/${fname}.wav"  "${MP3}\/${datedir}\/${fname}.mp3" && rm -f "${WAV}\/${fname}.wav" && chmod o+r "${MP3}\/${datedir}\/${fname}.mp3")
exten => ~~s~~,9,Set(FullFname=${URLRECORDS}\/${datedir}\/${fname}.mp3)
exten => ~~s~~,10,Set(CDR(filename)=${fname}.mp3)
exten => ~~s~~,11,Set(CDR(recordingfile)=${fname}.wav)
exten => ~~s~~,12,Set(CDR(realdst)=${called})
exten => ~~s~~,13,MixMonitor(${WAV}\/${datedir}\/${fname}.wav,b,${monopt})
exten => ~~s~~,14,NoOp(Finish if_recording_1)
exten => ~~s~~,15,Return()


;; Toto je hlavní kontext pro začátek hovoru
[ext-did-custom]

;; Je to šílenství, dělat to takhle, ale funguje - přidáváme k číslu '8'
exten =>  s,1,Set(CALLERID(num)=8${CALLERID(num)})

;; Tady jsou různé proměnné pro skript
exten =>  s,n,Gosub(recording,~~s~~,1(${CALLERID(number)},${EXTEN}))
exten =>  s,n,ExecIF(${CallMeCallerIDName}?Set(CALLERID(name)=${CallMeCallerIDName}):NoOp())
exten =>  s,n,Set(CallStart=${STRFTIME(epoch,,%s)})
exten =>  s,n,Set(CallMeDISPOSITION=${CDR(disposition)})

;; To nejdůležitější! Zpracovatel konce hovoru. 
;; Běžné cesty zpracování konce přes (exten=>h,1,něco) v FreePBX nefungují - Macro(hangupcall,) to všechno kazí. 
;; Proto zavěšujeme Hangup_Handler na konec hovoru
exten => s,n,Set(CHANNEL(hangup_handler_push)=sub-call-from-cid-ended,s,1(${CALLERID(num)},${EXTEN}))

;; Zpracovatel konce příchozího hovoru
[sub-call-from-cid-ended]

;; Mlčení hodnot při konci hovoru
exten => s,1,Set(CDR_PROP(disable)=true)
exten => s,n,Set(CallStop=${STRFTIME(epoch,,%s)})
exten => s,n,Set(CallMeDURATION=${MATH(${CallStop}-${CallStart},int)})

;; Stav hovoru - Odpověděl, neodpověděl...
exten => s,n,Set(CallMeDISPOSITION=${CDR(disposition)})
exten => s,n,Return


;; Zpracovatel odchozích hovorů - všechno analogické
[outbound-allroutes-custom]

;; Záznam
exten => _.,1,Gosub(recording,~~s~~,1(${CALLERID(number)},${EXTEN}))
;; Proměnné
exten => _.,n,Set(__CallIntNum=${CALLERID(num)})
exten => _.,n,Set(CallExtNum=${EXTEN})
exten => _.,n,Set(CallStart=${STRFTIME(epoch,,%s)})
exten => _.,n,Set(CallmeCALLID=${SIPCALLID})

;; Zavěšujeme Hangup_Handler na konec hovoru
exten => _.,n,Set(CHANNEL(hangup_handler_push)=sub-call-internal-ended,s,1(${CALLERID(num)},${EXTEN}))

;; Zpracovatel konce odchozího hovoru
[sub-call-internal-ended]

;; proměnné
exten => s,1,Set(CDR_PROP(disable)=true)
exten => s,n,Set(CallStop=${STRFTIME(epoch,,%s)})
exten => s,n,Set(CallMeDURATION=${MATH(${CallStop}-${CallStart},int)})
exten => s,n,Set(CallMeDISPOSITION=${CDR(disposition)})

;; Volání skriptu, který oznámí hovor v CRM - to je odchozí, 
;; takže po skončení
exten => s,n,System(curl -s ${URLPHP}\/CallMeOut.php --data action=sendcall2b24 --data ExtNum=${CallExtNum} --data call_id=${SIPCALLID} --data-urlencode FullFname='${FullFname}' --data CallIntNum=${CallIntNum} --data CallDuration=${CallMeDURATION} --data-urlencode CallDisposition='${CallMeDISPOSITION}')
exten => s,n,Return

Hlavní rys a odlišení od původní dialplánu autorů původního článku —

  • Dialplán ve formátu .conf, jak to vyžaduje FreePBX (ano, umí .ael, ale ne všechny verze a ne vždy je to pohodlné)

  • Místo zpracování konce přes exten=>h byla zavedena zpracování přes hangup_handler, protože dialplán FreePBX fungoval pouze s tímto

  • Opravený řádek volání skriptu, přidána uvozovka a externí číslo volání ExtNum

  • Zpracování bylo přesunuto do _custom kontextů, což umožňuje nezásahovat a neměnit konfigurace FreePBX — příchozí přes [ext-did-custom], odchozí přes [outbound-allroutes-custom]

  • Žádná vazba na čísla — soubor je univerzální a vyžaduje nastavování pouze cesty a odkazu na server

Pro zahájení práce je třeba také věnovat skripty do AMI podle přihlašovacího jména a hesla — pro to má FreePBX také _custom soubor

Soubor manager_custom.conf

;; to je uživatelské jméno
[callmeplus]
;; to je heslo
secret = trampampamturlala
deny = 0.0.0.0/0.0.0.0

;; pracuji s lokálním počítačem - ale pokud je potřeba, lze uvést i jiné
permit = 127.0.0.1/255.255.255.255
read = system,call,log,verbose,agent,user,config,dtmf,reporting,cdr,dialplan
write = system,call,agent,log,verbose,user,config,command,reporting,originate

Tyto oba soubory je třeba umístit do /etc/asterisk, poté přečíst konfigurace (nebo restartovat asterisk)

# astrisk -rv
  Connected to Asterisk 16.6.2 currently running on freepbx (pid = 31629)
#freepbx*CLI> dialplan reload
     Dialplan reloaded.
#freepbx*CLI> exit

Teď přejdeme k PHP

Inicializace skriptů a vytvoření služby

Jelikož schéma práce s Bitrix24, službou pro AMI, není zcela jasné a průhledné, je třeba se na něm zastavit zvlášť. Asterisk při aktivaci AMI pouze otevře port a to je vše. Při připojení klienta si vyžádá autorizaci, poté se klient přihlásí k potřebným událostem. Události přicházejí v prostém textu, který PAMI převádí na strukturované objekty a nabízí možnost nastavit funkci filtrování pouze podle zajímavých událostí, polí, čísel atd.

Jakmile hovor přijde, vznikne událost NewExten začínající s rodičovským kontextem [from-pstn], poté následují všechny události podle pořadí řádků v kontextech. Při získávání informací z definovaných v dialplánu _custom proměnných CallMeCallerIDName a CallStart je volána

  1. Funkce dotazu UserID, odpovídající internímu číslu, na které volání dorazilo. A pokud jde o skupinové volání? To je politická otázka, je třeba vytvořit hovor všem najednou (když volají všichni najednou) nebo vytvářet podle potřeby při postupném volání? Většina klientů má strategii First Available, takže s tím nejsou problémy, volá jen jeden. Ale otázku je třeba vyřešit.

  2. Funkce registrace hovoru v Bitrix24, která vrací CallID, nutný později pro oznámení o parametrech hovoru a odkazu na záznam. Vyžaduje buď vnitřní číslo, nebo UserID.

Zabýváme se FreePBX a integrujeme jej s Bitrix24 a nejen to

Po skončení hovoru je volána funkce načtení záznamu, která současně oznamuje stav ukončení hovoru (Zaneprázdněno, Není odpověď, Úspěch) a také načítá odkaz na mp3 soubor se záznamem (pokud je k dispozici).

Jelikož modul CallMeIn.php musí běžet nepřetržitě, byl pro něj vytvořen spouštěcí soubor SystemD. callme.service, který je třeba umístit do /etc/systemd/system/callme.service.

[Unit]
Description=CallMe

[Service]
WorkingDirectory=/var/www/html/callmeplus
ExecStart=/usr/bin/php /var/www/html/callmeplus/CallMeIn.php 2>&1 >>/var/log/callmeplus.log
ExecStop=/bin/kill -WINCH ${MAINPID}
KillSignal=SIGKILL

Restart=on-failure
RestartSec=10s

# zde je třeba zkontrolovat, jaká práva na složky
#User=www-data  #Ubuntu - debian
#User=nginx #Centos

[Install]
WantedBy=multi-user.target

Inicializace a spuštění skriptu probíhá přes systemctl nebo service.

# systemctl enable callme
# systemctl start callme

Služba se bude sama restartovat podle potřeby (při pádech). Služba sledování příchozích nevyžaduje instalaci webového serveru, potřebný je jen PHP (který je jistě na serveru FreePBX). Ale při absenci přístupu ke záznamům hovorů přes webový server (ještě s https) nebude možné poslouchat záznamy hovorů.

Teď se podívejme na odchozí hovory. Skript CallMeOut.php má dvě funkce:

  • Iniciace hovoru při přijetí žádosti na php skript (včetně tlačítka „Zavolat“ v samotném Bitrixu). Bez webového serveru nefunguje, žádost přichází přes HTTP POST, v žádosti je token.

  • Oznámení o hovoru, jeho parametrech a záznamech v Bitrixu. Probíhá na podnět Asterisku v dialplánu [sub-call-internal-ended] po skončení hovoru.

Zabýváme se FreePBX a integrujeme jej s Bitrix24 a nejen to

Webový server je potřeba pouze pro dvě věci — nahrání souborů záznamů Bitrixem (přes HTTPS) a volání skriptu CallMeOut.php. Můžete použít zabudovaný server FreePBX, soubory pro který leží /var/www/html, můžete nainstalovat jiný server nebo napsat jinou cestu.

Webový server

Nastavení webového serveru ponecháme na samostatné studium (klikněte, klikněte, klikněte). Pokud nemáte doménu, můžete vyzkoušet FreeDomain ( https://www.freenom.com/ru/index.html), která vám zdarma poskytne název pro vaši bílou IP (nezapomeňte přesměrovat porty 80, 443 přes router, pokud je externí adresa jen na něm). Pokud jste právě vytvořili DNS doménu, musíte počkat (od 15 minut do 48 hodin), než se všechny servery načtou. Zkušenosti s domácími poskytovateli ukazují, že to může trvat od 1 hodiny do 24 hodin.

Automatizace instalace

Na GitHubu byla zahájena vývoj instalátoru, aby bylo možné instalaci provádět ještě snadněji. Ale hladké to bylo na papíře — zatím instalujeme všechno ručně, naštěstí po prozkoumání této problematiky je jasné, kdo s kým kam chodí a jak to debuggovat. Instalátor zatím není (

Docker

Pokud chcete řešení rychle vyzkoušet — existuje možnost s Dockerem — rychle vytvořit kontejner, poskytnout mu porty ven, přidat konfigurační soubory a vyzkoušet (to je varianta s kontejnerem LetsEncrypt, pokud certifikát již existuje, stačí přesměrovat reverzní proxy na webový server FreePBX (tomu jsme dali jiný port — 88), LetsEncrypt v Dockeru podle doporučení. tohoto článku

Soubor je potřeba spustit ve stažené složce projektu (po git clone), ale předtím se podívat do konfigurací Asterisku (složka asterisk) a zapsat tam cesty k záznamům a URL vašeho webu.

version: '3.3'
services:
  nginx:
    image: nginx:1.15-alpine
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - .\/nginx\/ssl_docker.conf:\/etc\/nginx\/conf.d\/ssl_docker.conf
  certbot:
    image: certbot\/certbot
  freepbx:
    image: flaviostutz\/freepbx
    ports:
      - 88:80 # pro nastavení
      - 5060:5060\/udp
      - 5160:5160\/udp
      - 127.0.0.1:5038:5038 # pro CallMeOut.php
#      - 3306:3306
      - 18000-18100:18000-18100\/udp
    restart: always
    environment:
      - ADMIN_PASSWORD=admin123
    volumes:
      - backup:\/backup
      - recordings:\/var\/spool\/asterisk\/monitor
      - .\/callme:\/var\/www\/html\/callme
      - .\/systemd\/callme.service:\/etc\/systemd\/system\/callme.conf
      - .\/asterisk\/manager_custom.conf:\/etc\/asterisk\/manager_custom.conf
      - .\/asterisk\/extensions_custom.conf:\/etc\/asterisk\/extensions_custom.conf
#      - .\/conf\/startup.sh:\/startup.sh

volumes:
  backup:
  recordings:

Tento soubor docker-compose.yaml se spouští přes

docker-compose up -d

Pokud nginx neběží, znamená to, že něco není v pořádku s konfigurací ve složce nginx\/ssl_docker.conf.

Další integrace

A proč by se zároveň nezapojilo několik CRM do skriptů, říkali jsme si. Prozkoumali jsme několik API jiných CRM, zejména bezplatnou zabudovanou do některých Asterisk — ShugarCRM a Vtiger, a ano! jde to, princip je stejný. Ale to už je jiný příběh, který později nahrajeme na GitHub samostatně.

Odkazy

Diskleimer: jakékoli shody s realitou jsou fiktivní a nebyl to já,

Zdroj: habr.com

Koupit spolehlivý hosting pro webové stránky s ochranou proti DDoS, VPS VDS servery 🔥 Koupit spolehlivý hosting pro webové stránky s ochranou proti DDoS, VPS VDS servery | ProHoster