— je velikanska platforma, ki združuje CRM, upravljanje dokumentov, evidenco in še mnoge druge stvari, ki so zelo privlačne za menedžerje in manj za IT osebje. Portal uporabljajo številna mala in srednje velika podjetja, vključno z manjšimi klinikami, proizvajalci in celo frizerskimi saloni. Glavna funkcija, ki jo menedžerji najbolj 'ljubijo', je integracija telefonije in CRM, kjer se vsak klic takoj zabeleži v CRM, ustvarijo se kartice strank, ob vhodnem klicu pa se prikažejo informacije o stranki in takoj je jasno, kdo je, kaj mu lahko prodamo in koliko dolguje. Vendar pa integracija telefonije iz Bitrix24 in njena povezava s CRM stanejo denar, včasih kar precejšnjo vsoto. V članku bom delil izkušnje integracije z odprtimi orodji in priljubljeno IP PBX. , ter preučil logiko delovanja različnih delov.
Delam na zunanjih projektih v podjetju, ki se ukvarja s prodajo in nastavitvijo IP telefonije. Ko so me vprašali, ali lahko tistem in onem podjetju ponudimo nekaj za integracijo Bitrix24 s PBX-om, ki ga imajo stranke, ter z virtualnimi PBX-ji na različnih VDS podjetja, sem se obrnil na Googla. Seveda mi je prikazal povezavo do , kjer so opisani postopki, github, in vse naj bi delovalo. Vendar pa je med poskusom uporabe te rešitve prišlo do zavedanja, da Bitrix24 ni več tak, kot je bil prej, in da je potrebno veliko stvari ponovno prilagoditi. Poleg tega FreePBX ni običajni Asterisk, tukaj je potrebno razmišljati, kako uskladiti enostavnost uporabe in zapleteno strukturo dialplanov v konfiguracijskih datotekah.
Preučuję logiko delovanja
Torej, za začetek, kako naj bi vse to delovalo. Ob prejemu klica od zunaj na PBX (dogodek SIP INVITE od ponudnika) se začne obdelava diagrama klicev (dialplan) — pravil, kaj in v kakšnem vrstnem redu naj se naredi s klicem. Iz prvega paketa lahko pridobimo veliko informacij, ki jih lahko kasneje uporabimo v pravilih. Odlično orodje za preučevanje notranjih delov SIP je analizator sngrep () ki ga enostavno namestimo v priljubljenih distribucijah z apt install/yum install in podobnim, mogoče pa ga je sestaviti tudi iz virov. Oglejmo si log klica v sngrep.

Poenostavljeno, dialplan se ukvarja le s prvim paketom, včasih pa se v procesu klica dogajajo tudi prenos klicev, pritiski na gumbe (DTMF), različne zanimivosti, kot so FollowMe, RingGroup, IVR in podobno.
Kaj je dentro Invite paketa

Večina preprostih dialplanov deluje z prvima dvema poljema in vsa logika se vrti okoli DID in CallerID. DID je tisti, na katerega kličemo, CallerID pa je tisti, ki kliče.
Ampak mi imamo podjetje in ne le en telefon — to pomeni, da ima PBX verjetno skupine klicev (hkratni/podstantni klici več naprav) na mestnih številkah (Ring Group), IVR (Pozdravljeni, poklicali ste… pritisnite en za…), Avtomatske odgovorilnike (Phrases), Časovne pogoje (Time Conditions), Preusmeritve na druge številke ali mobilne (FollowMe, Forward). To pomeni, da je zelo težko nedvoumno določiti, kdo bo dejansko prejel klic in s kom se bo pogovarjal ob prejemu klica. Tukaj je primer začetka standardnega klica v PBX naših strank.

Po uspešnem vstopu klica v PBX se ta potuje po dialplanu v različnih "kontextih". Kontext iz vidika Asteriska je numerirana množica ukazov, od katerih vsak vsebuje filter za vneseno številko (imenuje se exten, za zunanji klic na začetni stopnji je exten=DID). Ukazi v vrstici dialplana so lahko karkoli — notranje funkcije (na primer poklicati notranjega uporabnika — Dial(), obesiti slušalko — Hangup()), pogojni operatorji (IF, ELSE, ExecIF in podobno), prehodi k drugim pravilom tega konteksta (Goto, GotoIF), prehodi v druge kontekste v obliki klicev funkcij (Gosub, Macro). Posebno ureditev predstavlja direktiva include ime_konteksta, ki doda ukaze drugega konteksta na konec trenutnega konteksta. Ukazi, vključeni preko include, se vedno izvajajo po ukazov trenutnega konteksta.
Vsa logika dela FreePBX je zgrajena na vključevanju različnih kontekstov drug v drugega preko include in klicev preko Gosub, Macro in obdelovalcev Handler. Raziščimo kontekst dohodnih klicev FreePBX.

Klic prehaja skozi vse kontekste od zgoraj navzdol po vrsti, v vsakem kontekstu so lahko klici drugih kontekstov kot makroji (Macro), funkcij (Gosub) ali preprosto prehodi (Goto), zato je dejansko drevo tega, kar se kliče, mogoče slediti samo v dnevnikih.
Standardna shema konfiguracije tipične kancelarijske PBX systema je prikazana ispod. Kada stigne poziv, na ulaznim rutama se traži DID, proveravaju se vremenski uslovi, a ako je sve u redu — pokreće se glasovni meni. Iz njega, pritiskom na dugme 1 ili nakon isteka vremena, dolazi se do grupe operatera. Nakon završetka poziva poziva se makro hangupcall, nakon čega se već ništa ne može izvršiti u dijal-planu, osim posebnih obrada (hangup handler).

Gde u ovom algoritmu poziva treba da dostavimo informacije o početku poziva u CRM, gde da započnemo snimanje, gde da završimo snimanje i da ga pošaljemo zajedno sa informacijama o pozivu na CRM?
Integracija sa eksternim sistemima
Šta je integracija PBX i CRM? To su podešavanja i programi koji konvertuju podatke i događaje između ove dve platforme i šalju ih jedni drugima. Najčešći način interakcije nezavisnih sistema je API, a najpopularniji način pristupa API-ju je HTTP REST. Ali ne i za asterisk.
Unutar Asteriska postoje:
AGI — sinhroni poziv eksternih programa/komponenti, koristi se uglavnom u dijal-planu, postoje biblioteke poput ,
AMI — tekstualni TCP soket, koji funkcioniše po principu pretplate na događaje i unosa tekstualnih komandi, podseća na SMTP iznutra, može pratiti događaje i upravljati pozivima, postoji biblioteka — najpopularnija za uspostavljanje veze sa Asterisk-om
Primer izlaza AMI
Događaj: Newchannel
Ovlašćenje: call,all
Kanal: PJSIP/VMS_pjsip-0000078b
Država kanala: 4
Opis stanja kanala: Ring
CallerIDNum: 111222
CallerIDName: 111222
ConnectedLineNum:
ConnectedLineName:
Jezik: en
AccountCode:
Kontekst: from-pstn
Exten: s
Prioritet: 1
Jedinstveni ID: 1599589046.5244
Povezani ID: 1599589046.5244
ARI — mešavina jednog i drugog, sve kroz REST, WebSocket, u JSON formatu — ali sa novim bibliotekama i omotima nije baš sjajno, našli su se (, ) koji su se razvijali pre 3 godine.
Primer izlaza ARI prilikom iniciranja poziva
{ "variable":"CallMeCallerIDName", "value":"111222", "type":"ChannelVarset", "timestamp":"2020-09-09T09:38:36.269+0000", "channel":{ "id":"1599644315.5334", "name":"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":"ru" }, "asteriskid":"48:5b:aa:aa:aa:aa", "application":"hello-world" }
Udobnost ali neudobnost, možnost ali nemogočnost dela z določenim API-jem sta odvisni od nalog, ki jih je treba rešiti. Naloge za integracijo s CRM so naslednje:
Spremljati začetek klica, kam je bil preusmerjen, pridobiti CallerID, DID, čase začetka in konca, lahko tudi podatke iz imenika (za iskanje povezave med telefonom in uporabnikom CRM)
Začeti in končati snemanje klica, shraniti v ustreznem formatu, sporočiti po končanju snemanja, kje leži datoteka
Inicializirati klic po zunanjem dogodku (iz programa), poklicati notranjo številko, zunanjo in ju povezati
Valgfrit: integrirati s CRM-jem, skupinami za klicanje in FollowME za samodejno preusmerjanje klicev v primeru odsotnosti (na podlagi informacij CRM)
Vse te naloge lahko rešimo preko AMI ali ARI, vendar ARI nudi veliko manj informacij, mnogi dogodki niso sledeni, mnoge spremenljivke, ki jih AMI vseeno vsebuje (na primer klici makrov, dodeljevanje spremenljivk znotraj makrov, vključno s snemanjem klicev). Zato bomo za pravilno in natančno sledenje zaenkrat izbrali AMI (a ne dokončno). Poleg tega (no, kako pa brez tega, smo ljudje leni) — v izvorni nalogi () uporabljajo PAMI. *Pozneje je treba poskusiti prepisati na ARI, vendar ni nujno, da bo uspelo.
Izmišljamo integracijo znova
Da lahko naš FreePBX preprosto obvešča AMI o začetku klica, času konca, številkah, imenih posnetih datotek, je najbolje uporabiti enak trik, kot so ga imeli izvirni avtorji — vnos svojih spremenljivk in analiza izhoda na njihovo prisotnost. PAMI to omogoča preprosto preko funkcije filter.
Tukaj je primer dodelitve svoje spremenljivke za čas začetka klica (s je posebna številka v dialplan-u, ki se izvaja PRED začetkom iskanja po DID)
[ext-did-custom]
exten => s,1,Set(CallStart=${STRFTIME(epoch,,%s)})Primer AMI dogodka po tej vrstici
Događaj: Newchannel
Ovlašćenje: call,all
Kanal: PJSIP/VMS_pjsip-0000078b
Država kanala: 4
Opis stanja kanala: Ring
CallerIDNum: 111222
CallerIDName: 111222
ConnectedLineNum:
ConnectedLineName:
Jezik: en
AccountCode:
Kontekst: from-pstn
Exten: s
Prioritet: 1
Jedinstveni ID: 1599589046.5244
Povezani ID: 1599589046.5244
Aplikacija: Set AppData:
CallStart=1599571046
Ker FreePBX prepisuje datoteke extention.conf in extention_additional.conf, bomo uporabili datoteko extention_custom.conf
Polna koda 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,ReturnPosebnost i razlika od originalnog dijal plana autora izvorne članka —
Dijal plan u .conf formatu, kako to želi FreePBX (da, može i .ael, ali ne u svim verzijama i ne uvijek je to praktično)
Umjesto obrade završetka kroz exten=>h, uvedena je obrada putem hangup_handler, jer je FreePBX dijal plan radio samo s njim
Ispravljena je linija poziva skripte, dodane su navodnice i vanjski broj poziva ExtNum
Obradbe su premještene u _custom kontekste i omogućuju nečakiranje i nepromjenu FreePBX konfiguracija — dolazne kroz [ext-did-custom], odlazne kroz [outbound-allroutes-custom]
Nema vezivanja za brojeve — datoteka je univerzalna i zahtijeva samo podešavanje puta i poveznice na poslužitelj
Za početak rada potrebno je još pustiti skripte u AMI pomoću korisničkog imena i lozinke — za to FreePBX također ima _custom datoteku
Datoteka manager_custom.conf
;; to je korisničko ime
[callmeplus]
;; to je lozinka
secret = trampampamturlala
deny = 0.0.0.0/0.0.0.0
;; radim s lokalnim strojem - ali ako treba, može se navesti i druge
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,originateOve obje datoteke treba staviti u /etc/asterisk, zatim ponovo učitati konfiguracije (ili ponovo pokrenuti Asterisk)
# astrisk -rv
Connected to Asterisk 16.6.2 currently running on freepbx (pid = 31629)
#freepbx*CLI> dialplan reload
Dialplan reloaded.
#freepbx*CLI> exitSada prelazimo na PHP
Inicijalizacija skripti i kreiranje servisa
Budući da je shema rada s Bitrix 24, servisom za AMI, prilično složena i neprozirna, na njoj se treba posebno zadržati. Asterisk, kada se aktivira AMI, jednostavno otvara port i to je to. Kada se klijent pridruži, traži autorizaciju, zatim se klijent pretplaćuje na potrebne događaje. Događaji dolaze u običnom tekstu, koji PAMI pretvara u strukturirane objekte i omogućava postavljanje funkcije filtriranja samo za interesantne događaje, polja, brojeve itd.
S čim dolazi poziv, nastaje događaj NewExten počevši od roditeljskog konteksta [from-pstn], zatim idu svi događaji po redoslijedu linija u kontekstima. Kada se dobije informacija iz zadanih u dijal planu _custom varijablama CallMeCallerIDName i CallStart, poziva se
Funckcja zapytania UserID, odpowiadająca wewnętrznemu numerowi, do którego dzwoniono. A jeśli to grupa połączeń? To pytanie polityczne – należy utworzyć połączenie do wszystkich jednocześnie (gdy dzwonią wszyscy jednocześnie), czy też tworzyć je w miarę dzwonienia podczas dzwonienia po kolei? U większości klientów stosuje się strategię First Available, więc nie ma z tym problemów, dzwoni tylko jedna osoba. Ale problem należy rozwiązać.
Funkcja rejestracji połączenia w Bitrix24, która zwraca CallID, potrzebny później do zgłaszania parametrów połączenia oraz linku do nagrania. Wymaga wewnętrznego numeru lub UserID.

Po zakończeniu połączenia wywoływana jest funkcja ładowania zapisu, która jednocześnie informuje o statusie zakończenia połączenia (Zajęty, Brak odpowiedzi, Sukces), a także ładuje link do pliku mp3 z nagraniem (jeśli jest).
Ponieważ moduł CallMeIn.php musi działać nieprzerwanie, stworzono dla niego plik startowy SystemD. callme.service, który należy umieścić w /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
# tutaj należy sprawdzić, jakie są prawa do folderów
#User=www-data #Ubuntu - debian
#User=nginx #Centos
[Install]
WantedBy=multi-user.targetInicjalizacja i uruchomienie skryptu odbywa się za pośrednictwem systemctl lub service.
# systemctl enable callme
# systemctl start callmeSerwis będzie automatycznie uruchamiał się ponownie w razie potrzeby (przy awariach). Serwis monitorujący przychodzące połączenia nie wymaga instalacji serwera WWW, potrzebny jest tylko PHP (który z pewnością jest na serwerze FeePBX). Jednak w przypadku braku dostępu do nagrań połączeń przez serwer WWW (jeszcze z HTTPS) nie będzie możliwości odsłuchiwania nagrań rozmów.
Teraz porozmawiajmy o połączeniach wychodzących. Skrypt CallMeOut.php ma dwie funkcje:
Inicjacja połączenia przy otrzymaniu żądania do skryptu PHP (w tym przycisk „Zadzwoń” w samym Bitrixie). Bez serwera WWW nie działa, żądanie przychodzi przez HTTP POST, a w żądaniu zawarty jest token.
Informacja o dzwonieniu, jego parametrach i nagraniach w Bitrixie. Ma miejsce z inicjatywy Asterisk w planie dzwanienia [sub-call-internal-ended] po zakończeniu połączenia.

Serwer WWW potrzebny jest tylko do dwóch rzeczy – ładowania plików nagrań przez Bitrix (przez HTTPS) oraz wywoływania skryptu CallMeOut.php. Można używać wbudowanego serwera FreePBX, pliki dla którego znajdują się w /var/www/html, można zainstalować inny serwer lub określić inną ścieżkę.
Serwer WWW
Pustimo konfiguracijo spletnega strežnika za samostojno raziskovanje (, , ). Če nimate domene, lahko preizkusite FreeDomain ( ), ki vam bodo brezplačno dali ime za vaš javni IP (ne pozabite preusmeriti vrat 80, 443 skozi usmerjevalnik, če je zunanji naslov samo na njem). Če ste pravkar ustvarili DNS domeno, boste morali počakati (od 15 minut do 48 ur), da se vsi strežniki naložijo. Na podlagi izkušenj z domačimi ponudniki – od 1 ure do enega dneva.
Samodejna namestitev
Na githubu se je začela razvijati namestitvena programska oprema, tako da bo namestitev še enostavnejša. Toda gladko je bilo na papirju — zaenkrat vse to nameščamo ročno, a po muckanju z vsemi temi stvarmi je postalo kristalno jasno, kdo je s kom prijatelj, kdo kam hodi in kako to debuggirati. Namestitvene programske opreme zaenkrat ni (
Docker
Če želite hitro preizkusiti rešitev — obstaja možnost z Dockerjem — hitro ustvarite vsebnik, mu omogočite zunanja vrata, dodajte konfiguracijske datoteke in preizkusite (to je možnost z LetsEncrypt vsebnikom, če ima že certifikat, potrebno je le preusmeriti obratni proxy na spletni strežnik FreePBX (dali smo mu drugo vrata — 88), LetsEncrypt v Dockerju po motivih
Datoteko je treba zagnati v preneseni mapi projekta (po git clone), a prej je treba spremeniti nastavitve Asteriska (mapa asterisk) in tam vnesti poti do zapisov in URL vašega spletnega mesta.
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 # za nastavitev
- 5060:5060\/udp
- 5160:5160\/udp
- 127.0.0.1:5038:5038 # za 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:
Ta datoteka docker-compose.yaml se zažene prek
docker-compose up -d
Če nginx ni zagnal, potem je nekaj narobe s konfiguracijo v mapi nginx\/ssl_docker.conf.
Druge integracije
Zakaj ne bi dodali več CRM v skripte, smo pomislili. Raziskovali smo več API-jev drugih CRM, še posebej brezplačne, vgrajene v nekatere PBX — ShugarCRM in Vtiger, in ja! lahko, načelo je isto. A to je že druga zgodba, ki jo bomo kasneje nalagali na github ločeno.
Povezave
Sam koda na githubu —
Izvirni članek za inspiracijo
Disklejmer: vse morebitne podobnosti z resničnostjo so naključne in to nisem bil jaz,
Izvor: habr.com
