Razumijevanje FreePBX-a i njegova integracija sa Bitrix24 i više

Bitrix24 je ogroman kombinat koji kombinuje CRM, radni tok, računovodstvo i mnoge druge stvari koje menadžeri zaista vole, a IT osoblje ne voli. Portal koristi veliki broj malih i srednjih kompanija, uključujući male klinike, proizvođače, pa čak i kozmetičke salone. Glavna funkcija koju menadžeri “vole” je integracija telefonije i CRM-a, kada se svaki poziv odmah snimi u CRM, kreiraju se klijentske kartice, pri dolasku se prikazuju informacije o klijentu i odmah se vidi ko je, šta je. može prodati i koliko duguje. Ali telefonija sa Bitrix24 i njena integracija sa CRM košta novac, ponekad mnogo. U članku ću vam ispričati iskustvo integracije s otvorenim alatima i popularnom IP PBX-om freepbx, a također razmotriti logiku rada različitih dijelova

Radim kao autsorser u kompaniji koja prodaje i konfiguriše, integriše IP telefoniju. Kada su me pitali da li možemo da ponudimo nešto ovoj i ovoj kompaniji za integraciju Bitrix24 sa centralama koje kupci imaju, kao i sa virtuelnim centralama na raznim VDS kompanijama, otišao sam na Google. I naravno dao mi je link članak u habr, gdje postoji opis, i github, i čini se da sve radi. Ali kada smo pokušali koristiti ovo rješenje, pokazalo se da Bitrix24 više nije isti kao prije i da je potrebno mnogo toga prepraviti. Osim toga, FreePBX nije gola zvjezdica za vas, ovdje morate razmisliti o tome kako kombinirati jednostavnost korištenja i hardcore dialplan u konfiguracijskim datotekama.

Proučavamo logiku rada

Dakle, za početak, kako bi sve to trebalo funkcionirati. Kada se na PBX primi poziv izvana (SIP INVITE događaj od provajdera), počinje obrada dialplan (dial plan, dialplan) - pravila šta i kojim redosledom se radi sa pozivom. Od prvog paketa možete dobiti puno informacija koje se onda mogu koristiti u pravilima. Odličan alat za proučavanje unutrašnjosti SIP-a je analizator sngrep (link) koji se jednostavno instalira u popularnim distribucijama putem apt install/yum install i slično, ali se može izgraditi i iz izvora. Pogledajmo evidenciju poziva u sngrepu

Razumijevanje FreePBX-a i njegova integracija sa Bitrix24 i više

U pojednostavljenom obliku, dialplan se bavi samo prvim paketom, ponekad i tokom razgovora, prenose se pozivi, pritiskanje tastera (DTMF), razne zanimljive stvari poput FollowMe, RingGroup, IVR i drugih.

Šta se nalazi unutar Invite Pack-a

Razumijevanje FreePBX-a i njegova integracija sa Bitrix24 i više

Zapravo, većina jednostavnih planova biranja radi sa prva dva polja, a cijela logika se vrti oko DID-a i CallerID-a. DID - gdje zovemo, CallerID - ko zove.

Ali ipak imamo kompaniju a ne jedan telefon - što znači da centrala najvjerovatnije ima grupe poziva (istovremeno/uzastopno zvono više uređaja) na gradskim brojevima (Ring Group), IVR (Zdravo, zvali ste... Pritisnite jedan za ...), Telefonske sekretarice (Fraze), Vremenski uslovi, Prosljeđivanje na druge brojeve ili na ćeliju (FollowMe, Forward). To znači da je vrlo teško nedvosmisleno odrediti ko će zapravo primiti poziv, a s kim će razgovarati kada poziv stigne. Evo primjera početka tipičnog poziva u PBX-u naših klijenata

Razumijevanje FreePBX-a i njegova integracija sa Bitrix24 i više

Nakon što poziv uspješno uđe u PBX, on putuje kroz plan biranja u različitim "kontekstima". Kontekst sa stanovišta Asterisk-a je numerisani skup naredbi, od kojih svaka sadrži filter prema biranom broju (zove se exten, za eksterni poziv u početnoj fazi exten=DID). Komande u liniji plana biranja mogu biti bilo koje - interne funkcije (na primjer, pozvati internog pretplatnika - Dial(), spusti telefon - Hangup()), uslovni operatori (IF, ELSE, ExecIF i slično), prelazi na druga pravila ovog konteksta (Goto, GotoIF), prelazak na druge kontekste u obliku poziva funkcije (Gosub, Macro). Posebna direktiva include имя_контекста, koji dodaje komande iz drugog konteksta na kraj trenutnog konteksta. Naredbe uključene putem uključivanja uvijek se izvršavaju после komande trenutnog konteksta.

Cijela logika FreePBX-a je izgrađena na uključivanju različitih konteksta jedan u drugi putem uključivanja i poziva preko Gosub, Macro i Handler rukovatelja. Razmotrite kontekst dolaznih FreePBX poziva

Razumijevanje FreePBX-a i njegova integracija sa Bitrix24 i više

Poziv prolazi redom kroz sve kontekste od vrha do dna, u svakom kontekstu mogu postojati pozivi u druge kontekste kao što su makroi (Macro), funkcije (Gosub) ili samo prijelazi (Goto), tako da pravo stablo onoga što se zove može samo biti praćeni u evidenciji.

Tipični dijagram podešavanja za tipičnu PBX je prikazan ispod. Prilikom poziva, DID se traži u dolaznim rutama, provjeravaju se privremeni uslovi za njega, ako je sve u redu, pokreće se glasovni meni. Iz njega, pritiskom na dugme 1 ili timeoutom, izađite u grupu operatera biranja. Nakon završetka poziva, poziva se makro hangupcall, nakon čega se ništa ne može učiniti u dijalplanu, osim specijalnih rukovatelja (hangup handler).

Razumijevanje FreePBX-a i njegova integracija sa Bitrix24 i više

Gdje u ovom algoritmu poziva trebamo dostaviti informacije o početku poziva CRM-u, gdje započeti snimanje, gdje završiti snimanje i poslati ga zajedno sa informacijama o pozivu CRM-u?

Integracija sa eksternim sistemima

Šta je PBX i CRM integracija? To su postavke i programi koji pretvaraju podatke i događaje između ove dvije platforme i šalju ih jedni drugima. Najčešći način komunikacije nezavisnih sistema je preko API-ja, a najpopularniji način pristupa API-jima je HTTP REST. Ali ne za zvjezdicu.

Unutar Asterisk je:

  • AGI - sinhroni poziv vanjskim programima/komponentama, koristi se uglavnom u dijalplanu, postoje biblioteke poput phpagi, PAGI

  • AMI - tekstualni TCP socket koji radi na principu pretplate na događaje i unosa tekstualnih naredbi, iznutra liči na SMTP, može pratiti događaje i upravljati pozivima, postoji biblioteka PAMI - najpopularniji za stvaranje veze sa Asterisk-om

Primjer AMI izlaza

Događaj: Novi kanal
Privilegija: zvati, sve
Kanal: PJSIP/VMS_pjsip-0000078b
Stanje kanala: 4
ChannelStateDesc: Prsten
CallerIDNum: 111222
CallerIDName: 111222
ConnectedLineNum:
ime povezane linije:
Jezik: en
šifra računa:
Kontekst: from-pstn
Proširenje: s
Prioritet: 1
Jedinstveni: 1599589046.5244
Linkedid: 1599589046.5244

  • ARI je mješavina oba, sve putem REST-a, WebSocket-a, u JSON formatu - ali sa svježim bibliotekama i omotima, ne baš dobro, slučajno pronađeno (phparia, phpari) koji je ušao u njihov razvoj prije otprilike 3 godine.

Primjer ARI izlaza kada se započne poziv

{ "varijable":"CallMeCallerIDName", "value":"111222", "type":"ChannelVarset", "timestamp":"2020-09-09T09:38:36.269+0000", "channel":{ "id »:»1599644315.5334″, «ime»:»PJSIP/VMSpjsip-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":"en" }, "asteriskid":"48:5b:aa:aa:aa:aa", "application":"hello-world" }

Pogodnost ili neugodnost, mogućnost ili nemogućnost rada sa određenim API-jem određuju se zadacima koje je potrebno riješiti. Zadaci za integraciju sa CRM-om su sljedeći:

  • Pratite početak poziva, gdje je prenesen, izvucite CallerID, DID, vrijeme početka i završetka, možda podatke iz imenika (za traženje veze između telefona i CRM korisnika)

  • Započnite i završite snimanje razgovora, sačuvajte ga u željenom formatu, na kraju snimanja obavijestite gdje se nalazi fajl

  • Pokrenite poziv na eksternom događaju (iz programa), pozovite interni broj, eksterni broj i povežite ih

  • Neobvezno: integrirati sa CRM-om, grupama birača i FollowME za automatski prijenos poziva u nedostatku mjesta (prema CRM-u)

Svi ovi zadaci se mogu riješiti putem AMI-ja ili ARI-ja, ali ARI pruža mnogo manje informacija, nema mnogo događaja, mnoge varijable koje AMI još uvijek ima (na primjer, makro pozivi, postavljanje varijabli unutar makroa, uključujući snimanje poziva) se ne prate. Stoga, za ispravno i precizno praćenje, izaberimo AMI za sada (ali ne u potpunosti). Uz to (pa gdje bi bez ovoga, mi smo lijeni ljudi) - u originalnom djelu (članak u habr) koristite PAMI. *Zatim morate pokušati prepisati na ARI, ali nije činjenica da će to uspjeti.

Ponovno izmišljanje integracije

Kako bi naš FreePBX mogao na jednostavne načine izvještavati AMI o početku poziva, vremenu završetka, brojevima, nazivima snimljenih fajlova, najlakše je izračunati trajanje poziva koristeći isti trik kao i originalni autori - unesite svoje varijable i analizirajte izlaz za njihovo prisustvo. PAMI predlaže da se to radi jednostavno kroz funkciju filtera.

Evo primjera postavljanja vlastite varijable za vrijeme početka poziva (s je poseban broj u planu biranja koji se izvodi PRIJE pokretanja DID pretrage)

[ext-did-custom]

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

Primjer AMI događaja za ovu liniju

Događaj: Novi kanal

Privilegija: zvati, sve

Kanal: PJSIP/VMS_pjsip-0000078b

Stanje kanala: 4

ChannelStateDesc: Prsten

CallerIDNum: 111222

CallerIDName: 111222

ConnectedLineNum:

ime povezane linije:

Jezik: en

šifra računa:

Kontekst: from-pstn

Proširenje: s

Prioritet: 1

Jedinstveni: 1599589046.5244

Linkedid: 1599589046.5244

Aplikacija: Postavite AppData:

CallStart=1599571046

Zato što FreePBX prepisuje datoteke extention.conf i extention_Additional.conf, mi ćemo koristiti datoteku proširenje_običaj.conf

Puni kod extention_custom.conf

[globals]	
;; Проверьте пути и права на папки - юзер asterisk должен иметь права на запись
;; Сюда будет писаться разговоры
WAV=/var/www/html/callme/records/wav 
MP3=/var/www/html/callme/records/mp3

;; По этим путям будет воспроизводится и скачиваться запись
URLRECORDS=https://www.host.ru/callmeplus/records/mp3

;; Адрес для калбека при исходящем вызове
URLPHP=https://www.host.ru/callmeplus

;; Да пишем разговоры
RECORDING=1

;; Это макрос для записи разговоров в нашу папку. 
;; Можно использовать и системную запись, но пока пусть будет эта - 
;; она работает
[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()


;; Это основной контекст для начала разговора
[ext-did-custom]

;; Это хулиганство, делать это так и здесь, но работает - добавляем к номеру '8'
exten =>  s,1,Set(CALLERID(num)=8${CALLERID(num)})

;; Тут всякие переменные для скрипта
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)})

;; Самое главное! Обработчик окончания разговора. 
;; Обычные пути обработки конца через (exten=>h,1,чтототут) в FreePBX не работают - Macro(hangupcall,) все портит. 
;; Поэтому вешаем Hangup_Handler на окончание звонка
exten => s,n,Set(CHANNEL(hangup_handler_push)=sub-call-from-cid-ended,s,1(${CALLERID(num)},${EXTEN}))

;; Обработчик окончания входящего вызова
[sub-call-from-cid-ended]

;; Сообщаем о значениях при конце звонка
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)})
exten => s,n,Return


;; Обработчик исходящих вызовов - все аналогичено
[outbound-allroutes-custom]

;; Запись
exten => _.,1,Gosub(recording,~~s~~,1(${CALLERID(number)},${EXTEN}))
;; Переменные
exten => _.,n,Set(__CallIntNum=${CALLERID(num)})
exten => _.,n,Set(CallExtNum=${EXTEN})
exten => _.,n,Set(CallStart=${STRFTIME(epoch,,%s)})
exten => _.,n,Set(CallmeCALLID=${SIPCALLID})

;; Вешаем Hangup_Handler на окончание звонка
exten => _.,n,Set(CHANNEL(hangup_handler_push)=sub-call-internal-ended,s,1(${CALLERID(num)},${EXTEN}))

;; Обработчик окончания исходящего вызова
[sub-call-internal-ended]

;; переменные
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)})

;; Вызов скрипта, который сообщит о звонке в CRM - это исходящий, 
;; так что по факту окончания
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

Osobina i razlika u odnosu na originalni dijagram autora originalnog članka -

  • Dialplan u .conf formatu, kako to FreePBX želi (da, može .ael, ali ne sve verzije i nije uvijek zgodno)

  • Umjesto obrade kraja preko exten=>h, obrada je uvedena preko hangup_handlera, jer je FreePBX dialplan radio samo s njim

  • Fiksni niz poziva skripte, dodani citati i eksterni pozivni broj ExtNum

  • Obrada je premještena u _prilagođene kontekste i omogućava vam da ne dodirujete ili uređujete FreePBX konfiguracije - dolazni putem [ext-did-custom], odlazeći kroz [outbound-allroutes-custom]

  • Nema vezivanja za brojeve - fajl je univerzalan i samo treba da se konfiguriše za putanju i vezu sa serverom

Da biste započeli, također morate pokrenuti skripte u AMI-u putem login-a i lozinke - za to FreePBX također ima _custom fajl

manager_custom.conf fajl

;;  это логин
[callmeplus]
;; это пароль
secret = trampampamturlala
deny = 0.0.0.0/0.0.0.0

;; я работаю с локальной машиной - но если надо, можно и другие прописать
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

Oba ova fajla moraju biti smeštena u /etc/asterisk, a zatim ponovo pročitajte konfiguracije (ili ponovo pokrenite zvezdicu)

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

Sada pređimo na PHP

Inicijalizacija skripti i kreiranje servisa

Budući da shema za rad s Bitrix 24, uslugom za AMI, nije sasvim jednostavna i transparentna, o njoj se mora razgovarati zasebno. Asterisk, kada je AMI aktiviran, jednostavno otvori port i to je to. Kada se klijent pridruži, traži autorizaciju, tada se klijent pretplaćuje na potrebne događaje. Događaji dolaze u običnom tekstu, koji PAMI pretvara u strukturirane objekte i pruža mogućnost postavljanja funkcije filtriranja samo za događaje od interesa, polja, brojeve itd.

Čim dođe poziv, NewExten događaj se pokreće počevši od roditeljskog [from-pstn] konteksta, tada svi događaji idu redoslijedom redova u kontekstima. Kada se primi informacija od varijabli CallMeCallerIDName i CallStart navedenih u _custom dialplanu,

  1. Funkcija traženja korisničkog ID-a koji odgovara broju lokala na koji je upućen poziv. Šta ako je to dial-up grupa? Pitanje je političko, da li treba kreirati poziv svima odjednom (kada svi zovu odjednom) ili kreirati kako zovu kada zovu redom? Većina klijenata ima strategiju Fisrt Available, tako da s tim nema problema, samo jedan poziv. Ali problem treba riješiti.

  2. Funkcija registracije poziva u Bitrix24, koja vraća CallID, koji je onda potreban za prijavu parametara poziva i vezu do snimka. Zahtijeva ili broj lokala ili UserID

Razumijevanje FreePBX-a i njegova integracija sa Bitrix24 i više

Nakon završetka poziva poziva se funkcija preuzimanja zapisa, koja istovremeno javlja status završetka poziva (Zauzeto, Nema odgovora, Uspjeh), a također preuzima link do mp3 datoteke sa zapisom (ako postoji).

Budući da modul CallMeIn.php treba da radi kontinuirano, za njega je kreirana SystemD datoteka za pokretanje callme.service, koji se mora staviti u /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

#тут надо смотреть,какие права на папки
#User=www-data  #Ubuntu - debian
#User=nginx #Centos

[Install]
WantedBy=multi-user.target

inicijalizacija i pokretanje skripte se dešava preko systemctl ili servisa

# systemctl enable callme
# systemctl start callme

Usluga će se ponovo pokrenuti po potrebi (u slučaju pada). Usluga praćenja inboxa ne zahtijeva instaliranje web servera, potreban je samo php (koji se definitivno nalazi na FeePBX serveru). Ali u nedostatku pristupa evidenciji poziva preko web servera (također sa https), neće biti moguće preslušati zapise poziva.

Hajde sada da pričamo o odlaznim pozivima. CallMeOut.php skripta ima dvije funkcije:

  • Pokretanje poziva kada se primi zahtjev za php skriptom (uključujući korištenje dugmeta "Pozovi" u samom Bitrix-u). Ne radi bez web servera, zahtjev se prima putem HTTP POST-a, zahtjev sadrži token

  • Poruka o pozivu, njegovim parametrima i zapisima u Bitrix-u. Aktivira Asterisk u dijalplanu [sub-call-internal-ended] kada se poziv završi

Razumijevanje FreePBX-a i njegova integracija sa Bitrix24 i više

Web server je potreban samo za dvije stvari - preuzimanje Bitrix zapisa (preko HTTPS-a) i pozivanje skripte CallMeOut.php. Možete koristiti ugrađeni FreePBX server, fajlovi za koji su /var/www/html, možete instalirati drugi server ili odrediti drugu putanju.

Web server

Ostavimo podešavanje web servera za samostalno proučavanje (tyts, tyts, tyts). Ako nemate domenu, možete isprobati FreeDomain( https://www.freenom.com/ru/index.html), koji će vam dati besplatno ime za vaš bijeli IP (ne zaboravite prosljediti portove 80, 443 kroz ruter ako je eksterna adresa samo na njemu). Ako ste upravo kreirali DNS domen, onda morate čekati (od 15 minuta do 48 sati) dok se svi serveri ne učitaju. Prema iskustvu rada sa domaćim provajderima - od 1 sata do jednog dana.

Automatizacija instalacije

Instalater je razvijen na githubu kako bi instalaciju bio još lakši. Ali na papiru je bilo glatko - dok mi to sve ručno instaliramo, pošto je nakon petljanja u svemu ovome postalo kristalno jasno šta se s kim druži, ko gde ide i kako to ispraviti. Još nema instalatera

doker

Ako želite brzo isprobati rješenje - postoji opcija sa Dockerom - brzo kreirajte kontejner, dajte mu portove van, ubacite fajlove postavki i pokušajte (ovo je opcija sa kontejnerom LetsEncrypt, ako već imate certifikat, vi samo treba preusmjeriti obrnuti proxy na FreePBX web server (dali smo mu drugi port je 88), LetsEncrypt u docker-u na osnovu ovog člana

Morate pokrenuti datoteku u preuzetom folderu projekta (nakon git klona), ali prvo uđite u konfiguracije asterisk (fascikla asterisk) i tamo upišite putanje do zapisa i URL vaše stranice

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 # для настройки
      - 5060:5060/udp
      - 5160:5160/udp
      - 127.0.0.1:5038:5038 # для 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:

Ova datoteka docker-compose.yaml se pokreće putem

docker-compose up -d

Ako se nginx ne pokrene, onda nešto nije u redu sa konfiguracijom u folderu nginx/ssl_docker.conf

Druge integracije

A zašto ne bismo u isto vrijeme ubacili CRM u skripte, pomislili smo. Proučili smo nekoliko drugih CRM API-ja, posebno besplatni ugrađeni PBX - ShugarCRM i Vtiger, i da! da, princip je isti. Ali ovo je druga priča, koju ćemo kasnije zasebno učitati na github.

reference

Disclaimer: Svaka sličnost sa stvarnošću je fiktivna i to nisam bio ja.

izvor: www.habr.com

Dodajte komentar