Разбіраемся з FreePBX і інтэгруемся яго з Битрикс24 і не толькі

Бітрыкс24 - гэта велізарны камбайн, які сумяшчае і CRM, і дакументазварот, і ўлік і яшчэ шмат розных рэчаў, якія вельмі падабаюцца мэнэджарам і не вельмі падабаюцца IT персаналу. Партал выкарыстоўваюць вельмі шмат невялікіх і сярэдніх кампаній, у тым ліку невялікія клінікі, вытворцы і нават салоны прыгажосці. Асноўнай функцыяй, якую "любяць" менеджэры з'яўляецца інтэграцыя тэлефаніі і CRM, калі любы званок адразу фіксуецца ў CRM, ствараюцца карткі кліента, пры ўваходным адлюстроўваецца інфармацыя аб кліенце і адразу відаць хто ён такі, што яму можна прадаць і колькі ён павінен. Але тэлефанія ад Битрикс24 і яе інтэграцыя з CRM каштуе грошай, часам немалых. У артыкуле я раскажу вопыт інтэграцыі з адкрытымі інструментамі і папулярнай IP АТС Бясплатная АТС, а таксама разгледжу логіку працы розных частак

Я працую на аўтсорсе ў кампаніі, якая займаецца продажам і наладай, інтэграцыяй IP тэлефаніі. Калі мяне спыталі, ці можам мы прэч той вось і вось гэтай вось кампаніі прапанаваць нешта для інтэграцыі Битрикс24 з АТС, якія стаяць у кліентаў, а таксама з віртуальнымі АТС на розных VDS кампаніі, я пайшоў у Google. І ён мне вядома ж выдаў спасылку на артыкул у хабр, дзе ёсць і апісанне, і github, і накшталт усё працуе. Але пры спробе пакарыстацца гэтым рашэннем вылезла, што Битрикс24 ужо не той, што раней, і трэба шматлікае перарабляць. Акрамя таго, FreePBX гэта вам не голы астэрыск, тут думаць трэба як сумясціць зручнасць выкарыстання і хардкорны дыялплан у канфіг-файлах.

Вывучаем логіку працы

Такім чынам, для пачатку, як усё гэта павінна працаваць. Пры паступленні званка звонку на АТС (падзея SIP INVITE ад правайдэра) пачынаецца апрацоўка диалплана (плана набору, dialplan) – правілаў, што і ў якім парадку рабіць са званком. З першага пакета можна атрымаць шмат інфармацыі, якую потым можна выкарыстоўваць у правілах. Выдатным інструментам для вывучэння вантроб SIP з'яўляецца аналізатар sngrep (спасылка) які проста ставіцца ў папулярных дыстрыбутывах праз apt install/yum install і падобнае, але можна і з зыходнікаў сабраць. Паглядзім лог званка ў sngrep

Разбіраемся з FreePBX і інтэгруемся яго з Битрикс24 і не толькі

У спрошчаным выглядзе диалплан займаецца толькі першым пакетам, часам таксама падчас гутаркі здзяйсняецца пераклад званкоў, націскі кнопак (DTMF), розныя цікавасці тыпу FollowMe, RingGroup, IVR і іншага.

Што ўнутры Invite пакета

Разбіраемся з FreePBX і інтэгруемся яго з Битрикс24 і не толькі

Уласна большасць простых диалпланов працуюць з першымі двума палямі і ўся логіка круціцца вакол DID і CallerID. DID – куды тэлефануем, CallerID – хто тэлефануе.

Але ж у нас фірма а не адзін тэлефон — і значыць у АТС хутчэй за ўсё ёсць групы выкліку (адначасовы/паслядоўны званок некалькіх апаратаў) на гарадскіх нумарах (Ring Group), IVR (Добры дзень, вы патэлефанавалі… Націсніце адзін для…), Аўтаадказчыкі ( Phrases), Часовыя ўмовы (Time Conditions), Пераадрасацыя на іншыя нумары або на сотавы (FollowMe, Forward). Гэта значыць, што адназначна вызначыць каму насамрэч прыйдзе выклік і з кім будзе размова пры паступленні выкліку вельмі складана. Вось прыклад пачатку праходжання тыпавога выкліку ў АТС нашых кліентаў

Разбіраемся з FreePBX і інтэгруемся яго з Битрикс24 і не толькі

Пасля паспяховага ўваходу званка ў АТС адбываецца падарожжа яго па дыялплане ў розных «кантэкстах». Кантэкст з пункта гледжання Asterisk - гэта нумараваны набор каманд, кожная з якіх утрымоўвае фільтр па набраным нумары (ён завецца exten, для вонкавага выкліку на пачатковым этапе exten=DID). Камандамі ў радку дыялплана можа быць усё што заўгодна – унутраныя функцыі (напрыклад патэлефанаваць унутранаму абаненту – Dial(), пакласці трубку Hangup()), умоўныя аператары (IF, ELSE, ExecIF і падобныя), пераходы да іншых правілаў гэтага кантэксту (Goto, GotoIF), пераход іншым кантэкстам у выглядзе выкліку функцый (Gosub, Macro). Асобна стаіць дырэктыва include имя_контекста, якая дадае каманды іншага кантэксту ў канец бягучага кантэксту. Каманды, уключаныя праз include заўсёды выконваюцца пасля каманд бягучага кантэксту.

Уся логіка працы FreePBX пабудавана на ўключэнні сябар у сябра розных кантэкстаў праз include і выклік праз Gosub, Macro і апрацоўшчыкі Handler. Разгледзім кантэкст уваходных выклікаў FreePBX

Разбіраемся з FreePBX і інтэгруемся яго з Битрикс24 і не толькі

Выклік праходзіць па ўсіх кантэкстах зверху ўніз па чарзе, у кожным кантэксце могуць быць выклікі іншых кантэкстаў як макрасаў (Macro), функцый (Gosub) ці проста пераходы (Goto), таму рэальнае дрэва таго, што выклікаецца можна адсачыць толькі ў логах.

Тыпавая схема налады тыповай офіснай АТС паказана ніжэй. Пры выкліку ва ўваходных маршрутах шукаецца DID, па ім правяраюцца часовыя ўмовы, калі ўсё ў парадку - запускаецца галасавое меню. З яго па кнопцы 1 або таймаўту выхад на групу дазвону аператараў. Пасля канчатка званка выклікаецца макрас hangupcall, пасля якога нічога ўжо ў диалплане выканаць не атрымаецца, акрамя адмысловых апрацоўшчыкаў (hangup handler).

Разбіраемся з FreePBX і інтэгруемся яго з Битрикс24 і не толькі

Дзе ў гэтым алгарытме званка мы павінны пастаўляць інфармацыю аб пачатку званка ў CRM, дзе пачынаць запіс, дзе сканчаць запіс і адсылаць яго разам з інфармацыяй аб званку на CRM?

Інтэграцыя з вонкавымі сістэмамі

Што такое інтэграцыя АТС і CRM? Гэта настройкі і праграмы, якія канвертуюць дадзеныя і падзеі паміж двума гэтымі платформамі і перасылаюць адзін аднаму. Самым распаўсюджаным спосабам узаемадзеяння незалежных сістэм з'яўляецца API, а самым папулярным спосабам доступу да API з'яўляецца HTTP REST. Але толькі не для asterisk.

Усярэдзіне Asterisk ёсць:

  • AGI - сінхронны выклік знешніх праграм/кампанентаў, выкарыстоўваецца ў асноўным у дыялплане, ёсць бібліятэкі тыпу phpagi, PAGI

  • AMI - тэкставы TCP сокет, які працуе па прынцыпе падпіскі на падзеі і ўводу тэкставых каманд, нагадвае SMTP знутры, умее адсочваць падзеі і кіраваць выклікамі, ,ёсць бібліятэка PAMI - самая папулярная для стварэння сувязі з Asterisk

Прыклад вываду AMI

Event: Newchannel
Privilege: call,all
Channel: PJSIP/VMS_pjsip-0000078b
ChannelState: 4
ChannelStateDesc: Ring
CallerIDNum: 111222
CallerIDName: 111222
ConnectedLineNum:
ConnectedLineName:
Мова: en
AccountCode:
Context: from-pstn
Exten: s
Прыярытэт: 1
Uniqueid: 1599589046.5244
Linkedid: 1599589046.5244

  • ARI – сумесь таго, іншага, усё праз REST, WebSocket, у фармаце JSON – але вось са свежымі бібліятэкамі і абгорткамі не вельмі, на ўскідку знайшліся (phparia, phpari) якія станавіліся ў сваім развіцці года 3 таму.

Прыклад вываду ARI пры ініцыяцыі званка

{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" }

Выгода або нязручнасць, магчымасць або немагчымасць працы з тым ці іншым API вызначаюцца задачамі, якія неабходна вырашыць. Задачы для інтэграцыі з CRM наступныя:

  • Адсачыць пачатак выкліку, куды яго перавялі, выцягнуць CallerID, DID, часы пачатку і канца, можа быць дадзеныя з дырэкторыі (для пошуку сувязі тэлефона і карыстальніка CRM)

  • Пачаць і скончыць запіс званка, захаваць у патрэбным фармаце, паведаміць па канчатку запісу дзе ляжыць файл

  • Ініцыяваць званок па знешняй падзеі (з праграмы), патэлефанаваць унутранаму нумару, знешняму і злучыць іх

  • апцыянальна: інтэграваць з CRM, групамі дазвону і FollowME для аўтаматычнага пераводу званкоў пры адсутнасці на месцы(па інфармацыі CRM)

Усе гэтыя задачы можна вырашыць праз AMI ці ARI, але ARI падае значна менш інфармацыі, няма шматлікіх падзей, не адсочваюцца шматлікія зменныя, якія ў AMI усё ж ёсць (напрыклад выклікі макрасаў, заданне зменных усярэдзіне макрасаў, у тым ліку запіс званкоў). Таму, для правільнага і дакладнага адсочвання - выберам пакуль AMI (але не канчаткова). Акрамя таго (ну а куды ж без гэтага, мы людзі лянівыя) - у зыходнай працы (артыкул у хабр) выкарыстоўваюць PAMI. *Затым трэба паспрабаваць перапісаць на ARI, але не факт што атрымаецца.

Прыдумляем інтэграцыю нанова

Для таго, каб наш FreePBX мог паведамляць у AMI простымі спосабамі аб пачатку званка, часе заканчэння, нумарах, імёнах запісаных файлаў, разлічваць працягласць званка прасцей за ўсё скарыстацца тым жа трукам, што і зыходныя аўтары – увесці свае зменныя і парсіць выснову на іх прысутнасць. PAMI прапануе гэта рабіць проста праз функцыю-фільтр.

Вось прыклад задання сваёй зменнай для часу пачатку званка (s - гэта спецыяльны нумар у дыялплане, які выконваецца ДА пачатку пошуку па DID)

[ext-did-custom]

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

Прыклад AMI падзеі па гэтым радку

Event: Newchannel

Privilege: call,all

Channel: PJSIP/VMS_pjsip-0000078b

ChannelState: 4

ChannelStateDesc: Ring

CallerIDNum: 111222

CallerIDName: 111222

ConnectedLineNum:

ConnectedLineName:

Мова: en

AccountCode:

Context: from-pstn

Exten: s

Прыярытэт: 1

Uniqueid: 1599589046.5244

Linkedid: 1599589046.5244

Application: Set AppData:

CallStart=1599571046

Паколькі FreePBX перазапісвае файлы extention.conf і extention_additional.conf, мы будзем выкарыстоўваць файл extention_звычай.канф

Поўны код 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

Асаблівасць і адрозненнем ад арыгінальнага дыялплана аўтараў зыходнага артыкула

  • Дыялплан у фармаце .conf, бо гэтага жадае FreePBX (ды ён умее .ael, але не ўсе версіі і не заўсёды гэта зручна)

  • Замест апрацоўкі канчатка праз exten=>h уведзена апрацоўка праз hangup_handler, таму што FreePBX диалплан зарабіў толькі з ім

  • Папраўлены радок выкліку скрыпту, дабаўлены двукоссі і знешні нумар званка ExtNum.

  • Апрацоўкі вынесена ў _custom кантэксты і дазваляюць не чапаць і не кіраваць канфігі FreePBX - якія ўваходзяць праз [ext-did-custom], выходныя праз [outbound-allroutes-custom]

  • Няма прывязкі да нумароў - файл універсальны і мае патрэбу ў наладзе толькі шляхі і спасылка на сервер

Для пачатку працы трэба яшчэ пусціць скрыпты ў AMI па лагіне і паролю - для гэтага ў FreePBX таксама ёсць _custom файл

Файл manager_custom.conf

;;  это логин
[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

Гэтыя абодва файла трэба змясціць у /etc/asterisk, затым перачытаць канфігі (ці перазапусціць астэрыск)

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

Цяпер пяройдзем да PHP

Ініцыялізацыя скрыптоў і стварэнне сэрвісу

Паколькі схема працы з Битрикс 24, сэрвісам для AMI не зусім простая і празрыстая, на ёй трэба спыніцца асобна. Астэрыск пры актывацыі AMI проста адчыняе порт і ўсё. Пры далучэнні кліента яна запытвае аўтарызацыю, потым кліент падпісваецца на патрэбныя падзеі. Падзеі прыходзяць простым тэкстам, які PAMI пераўтворыць у структураваныя аб'екты і дае магчымасць заданне функцыі фільтрацыі толькі па падзеях, палях, нумарах і г.д.

Як толькі званок паступае, узнікае падзея NewExten пачынальна з бацькоўскага кантэксту [from-pstn], затым ідуць усе падзеі па парадку прытрымлівання радкоў у кантэкстах. Пры атрыманні інфармацыі з зададзеных у дыялплане _custom зменных CallMeCallerIDName і CallStart выклікаецца

  1. Функцыя запыту UserID, які адпавядае ўнутранаму нумару, куды прыйшоў званок. А калі гэта група дазвону? Пытанне палітычнае, трэба стварыць званок усім адразу (калі тэлефануюць усё адразу) ці ствараць па меры абзвону пры пачарговым званку? У большасці кліентаў стаіць стратэгія Fisrt Available, таму з гэтым няма праблем, тэлефануе толькі адзін. Але вырашаць пытанне трэба

  2. Функцыя рэгістрацыі званка ў Битрикс24, якая вяртае CallID, неабходны потым для паведамлення аб параметрах званка і спасылцы на запіс. Патрабуе ці ўнутраны нумар або UserID

Разбіраемся з FreePBX і інтэгруемся яго з Битрикс24 і не толькі

Пасля заканчэння званка выклікаецца функцыя загрузкі запісу, якая адначасова паведамляе статус завяршэння званка (Заняты, Няма адказу, Поспех), а таксама загружае спасылку на mp3 файл з запісам (калі ёсць).

Паколькі модуль CallMeIn.php павінен працаваць бесперапынна, для яго быў створаны SystemD файл запуску callme.service, які трэба пакласці ў /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

ініцыялізацыя і запуск скрыпту адбываецца праз systemctl ці service

# systemctl enable callme
# systemctl start callme

Сэрвіс будзе сам перазапускацца па неабходнасці (пры падзеннях). Сэрвіс сачэння за ўваходнымі не патрабуе ўсталёўкі вэб сервера, патрэбен толькі php (які сапраўды ёсць на серверы FeePBX). Але пры адсутнасці доступу да запісаў званкоў праз Вэб сервер (яшчэ і з https) не будзе магчымасці праслухоўваць запісы размоў.

Цяпер пагаворым пра выходныя званкі. У скрыпта CallMeOut.php дзве функцыі:

  • Ініцыяцыя званка пры паступленні запыту на php скрыпт (у тым ліку па кнопцы "Патэлефанаваць" у самім бітрыксе). Без вэб сервера не працуе, запыт паступае праз HTTP POST, у запыце змяшчаецца токен

  • Паведамленне аб званку, яго параметрах і запісах у Битрикс. Адбываецца па ініцыятыве Asterisk у дыялплане [sub-call-internal-ended] пры заканчэнні званка

Разбіраемся з FreePBX і інтэгруемся яго з Битрикс24 і не толькі

Вэб сервер патрэбен толькі для двух рэчаў – загрузка файлаў запісаў бітрыксам (па HTTPS) і выклік скрыпту CallMeOut.php. Можна выкарыстоўваць убудаваны сервер FreePBX, файлы для якога ляжаць /var/www/html, можна ўсталяваць іншы сервер ці прапісаць іншы шлях.

Вэб сервер

Пакінем наладу вэб сервера на самастойнае вывучэнне (тыц, тыц, тыц). Калі ў вас няма дамена, можна паспрабаваць FreeDomain( https://www.freenom.com/ru/index.html), якія на халяву дадуць вам імя для вашага белага IP (не забудзьцеся пракінуць парты 80, 443 праз роўтар, калі вонкавы адрас ёсць толькі на ім). Калі вы толькі стварылі DNS дамен, тое трэба пачакаць (ад 15 хвілін да 48 гадзін) пакуль усе серверы прагрузяцца. Па досведзе працы з айчыннымі парвайдэрамі - ад 1 гадзіны да сутак.

Аўтаматызацыя ўстаноўкі

На github пачата тэхналогія ўсталёўніка, каб можна было ўсталёўваць значна прасцей. Але гладка было на паперы - пакуль усталёўваны ўсё гэта ўручную, балазе пасля калупання ва ўсім гэтым стала крышталёва ясна, што з кім сябруе, хто куды ходзіць і як гэта дэбажыць. Усталёўніка пакуль няма (

Докер

Калі хочацца хутка паспрабаваць рашэнне - ёсць варыянт з Docker - хутка стварыць кантэйнер, даць яму парты вонкі, падсунуць файлы налад і паспрабаваць (гэта варыянт з LetsEncrypt кантэйнерам, калі сертыфікат ужо ёсць, проста трэба перанакіраваць зваротны проксі на вэб сервер FreePBX (яму мы далі іншы порт – 88), LetsEncrypt у докеры па матывах гэтага артыкула

Запускаць файл трэба ў запампаванай тэчцы праекту (пасля git clone), але папярэдне залезці ў канфігі астэрыска (тэчка asterisk) і прапісаць тамака шляхі да запісаў і URL вашага сайта

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:

Гэты файл docker-compose.yaml, запускаецца праз

docker-compose up -d

Калі nginx не запусціўся, значыць што тое не так з канфігурацыяй у тэчцы nginx/ssl_docker.conf

Іншыя інтэграцыі

А чаму б заадно не сунуць некалькі CRM у скрыпты, падумалі мы. Вывучылі некалькі API іншых CRM, асабліва бясплатнай убудаванай у некаторыя АТС – ShugarCRM і Vtiger, і так! можна, прынцып той жа. Але гэта ўжо іншая гісторыя, якую потым будзем заліваць на гітхаб асобна.

Спасылкі

Дысклеймер: любыя супадзенні з рэальнасць выдуманыя і гэта быў не я,

Крыніца: habr.com

Дадаць каментар