FreePBX izpratne un integrēšana ar Bitrix24 un citiem
Bitrix24 ir milzīgs kombināts, kas apvieno CRM, darbplūsmu, grāmatvedību un daudzas citas lietas, kas vadītājiem ļoti patīk un IT darbiniekiem īsti nepatīk. Portālu izmanto ļoti daudz mazo un vidējo uzņēmumu, tostarp mazās klīnikas, ražotāji un pat skaistumkopšanas saloni. Galvenā funkcija, ko vadītāji “mīl” ir telefonijas un CRM integrācija, kad jebkurš zvans uzreiz tiek ierakstīts CRM, tiek izveidotas klientu kartes, ienākot tiek parādīta informācija par klientu un uzreiz var redzēt, kas viņš ir, kāds viņš ir. var pārdot un cik viņš ir parādā. Bet telefonija no Bitrix24 un tās integrācija ar CRM maksā naudu, dažreiz daudz. Rakstā es jums pastāstīšu par integrācijas pieredzi ar atvērtajiem rīkiem un populāro IP PBX Bezmaksas PBX, kā arī apsveriet dažādu daļu darba loģiku
Strādāju par ārpakalpojumu sniedzēju uzņēmumā, kas pārdod un konfigurē, integrē IP telefoniju. Kad man jautāja, vai mēs varētu kaut ko piedāvāt šim un šim uzņēmumam, lai integrētu Bitrix24 ar klientu PBX, kā arī ar virtuālajiem PBX dažādos VDS uzņēmumos, es devos uz Google. Un, protams, viņš man iedeva saiti uz raksts habr, kur ir apraksts, un github, un viss it kā darbojas. Taču, mēģinot izmantot šo risinājumu, izrādījās, ka Bitrix24 vairs nav tas pats, kas iepriekš, un daudz kas ir jāpārstrādā. Turklāt FreePBX jums nav tukša zvaigznīte, šeit jums ir jādomā, kā konfigurācijas failos apvienot lietošanas ērtumu un stingru iezvanes plānu.
Mēs pētām darba loģiku
Tātad iesākumam, kā tam visam vajadzētu darboties. Kad tiek saņemts zvans no ārpuses PBX (SIP INVITE notikums no pakalpojumu sniedzēja), sākas sastādīšanas plāna (iezvanes plāna, iezvanes plāna) apstrāde - noteikumi, ko un kādā secībā ar zvanu darīt. No pirmās paketes jūs varat iegūt daudz informācijas, ko pēc tam var izmantot noteikumos. Lielisks rīks SIP iekšējo izpēti ir analizators sngrep (saite), kas ir vienkārši instalēta populāros izplatījumos, izmantojot apt install/yum install un tamlīdzīgi, taču to var arī izveidot no avota. Apskatīsim zvanu žurnālu sngrep
Vienkāršotā veidā sastādīšanas plāns nodarbojas tikai ar pirmo paketi, dažkārt arī sarunas laikā tiek pārsūtīti zvani, pogu nospiešanas (DTMF), dažādas interesantas lietas kā FollowMe, RingGroup, IVR un citas.
Kas atrodas uzaicinājumu pakotnē
Faktiski lielākā daļa vienkāršo zvanu plānu darbojas ar pirmajiem diviem laukiem, un visa loģika griežas ap DID un CallerID. DID - kur mēs zvanām, CallerID - kurš zvana.
Bet galu galā mums ir uzņēmums, nevis viens tālrunis - tas nozīmē, ka PBX, visticamāk, ir zvanu grupas (vairāku ierīču vienlaicīga / secīga zvanīšana) uz pilsētu numuriem (Zvanu grupa), IVR (Sveiki, jūs zvanījāt ... Nospiediet viens ...), Automātiskie atbildētāji (Frāzes), Laika nosacījumi, Pārsūtīšana uz citiem numuriem vai šūnu (FollowMe, Forward). Tas nozīmē, ka ir ļoti grūti viennozīmīgi noteikt, kurš tad īsti saņems zvanu un ar ko būs saruna, kad pienāk zvans. Šeit ir piemērs tipiska zvana sākumam mūsu klientu PBX
Pēc tam, kad zvans veiksmīgi nonāk PBX, tas ceļo pa iezvanes plānu dažādos "kontekstos". Konteksts no zvaigznītes viedokļa ir numurēta komandu kopa, no kurām katra satur filtru pēc sastādītā numura (to sauc exten, ārējam zvanam sākotnējā posmā exten=DID). Komandas sastādīšanas plāna rindā var būt jebkas - iekšējās funkcijas (piemēram, izsaukt iekšējo abonentu - Dial(), noliec telefonu - Hangup()), nosacījuma operatori (IF, ELSE, ExecIF un tamlīdzīgi), pāriet uz citiem šī konteksta noteikumiem (Goto, GotoIF), pāreja uz citiem kontekstiem funkcijas izsaukuma veidā (Gosub, Macro). Atsevišķa direktīva include имя_контекста, kas pašreizējā konteksta beigām pievieno komandas no cita konteksta. Komandas, kas iekļautas, izmantojot include, vienmēr tiek izpildītas pēc pašreizējā konteksta komandas.
Visa FreePBX loģika ir balstīta uz dažādu kontekstu iekļaušanu savā starpā, izmantojot Gosub, Macro un Handler apdarinātājus. Apsveriet ienākošo FreePBX zvanu kontekstu
Izsaukums pēc kārtas iet cauri visiem kontekstiem no augšas uz leju, katrā kontekstā var būt izsaukumi uz citiem kontekstiem, piemēram, makro (Macro), funkcijām (Gosub) vai vienkārši pārejām (Goto), tāpēc īstais sauktā koks var tikai izsekot žurnālos.
Tālāk ir parādīta tipiska PBX iestatīšanas shēma. Zvanot tiek meklēts DID ienākošajos maršrutos, tam tiek pārbaudīti pagaidu apstākļi, ja viss kārtībā, tiek palaista balss izvēlne. No tā, nospiežot pogu 1 vai taimautu, izejiet uz zvanu operatoru grupu. Pēc zvana beigām tiek izsaukts hangupcall makro, pēc kura sastādīšanas plānā vairs nevar darīt neko, izņemot īpašos apstrādātājus (hangup handler).
Kur šajā zvana algoritmā ir jāsniedz informācija par CRM zvana sākumu, kur sākt ierakstīšanu, kur beigt ierakstīšanu un nosūtīt to kopā ar informāciju par zvanu CRM?
Integrācija ar ārējām sistēmām
Kas ir PBX un CRM integrācija? Tie ir iestatījumi un programmas, kas pārvērš datus un notikumus starp šīm divām platformām un nosūta tos viena otrai. Visizplatītākais neatkarīgo sistēmu saziņas veids ir API, un vispopulārākais veids, kā piekļūt API, ir HTTP REST. Bet ne zvaigznītei.
Zvaigznītes iekšpusē ir:
AGI - ārējo programmu/komponentu sinhronais izsaukums, izmanto galvenokārt iezvanes plānā, ir tādas bibliotēkas kā phpagi, PAGI
AMI - teksta TCP ligzda, kas darbojas pēc notikumu abonēšanas un teksta komandu ievadīšanas principa, no iekšpuses atgādina SMTP, var izsekot notikumus un pārvaldīt zvanus, ir bibliotēka PAMI - vispopulārākais, lai izveidotu savienojumu ar Asterisk
AMI izvades piemērs
Pasākums: jauns kanāls
Privilēģija: zvaniet, visi
Kanāls: PJSIP/VMS_pjsip-0000078b
Kanāla stāvoklis: 4
ChannelStateDesc: zvana
Zvanītāja IDNum: 111222
Zvanītāja ID: 111222
ConnectedLineNum:
savienotās līnijas nosaukums:
Valoda: en
konta kods:
Konteksts: no-pstn
Paplašinājums: s
Prioritāte: 1
Unikāls: 1599589046.5244
Linkedid: 1599589046.5244
ARI ir abu sajaukums, izmantojot REST, WebSocket, JSON formātā — taču ar jaunām bibliotēkām un iesaiņojumiem, kas nav īpaši labi, atrasti neklātienē (phparia, phpari), kas kļuva to attīstībā apmēram pirms 3 gadiem.
Ērtības vai neērtības, iespēju vai neiespējamību strādāt ar konkrēto API nosaka uzdevumi, kas ir jāatrisina. Uzdevumi integrācijai ar CRM ir šādi:
Izsekojiet zvana sākumu, kur tas tika pārsūtīts, izvelciet CallerID, DID, sākuma un beigu laikus, iespējams, datus no kataloga (lai meklētu savienojumu starp tālruni un CRM lietotāju)
Sāciet un beidziet zvana ierakstīšanu, saglabājiet to vēlamajā formātā, ieraksta beigās paziņojiet, kur atrodas fails
Uzsāciet zvanu uz ārēju notikumu (no programmas), zvaniet uz iekšējo numuru, ārējo numuru un savienojiet tos
Neobligāti: integrējiet ar CRM, zvanītāju grupām un FollowME, lai automātiski pārsūtītu zvanus, ja nav vietas (saskaņā ar CRM)
Visus šos uzdevumus var atrisināt ar AMI vai ARI starpniecību, taču ARI sniedz daudz mazāk informācijas, notikumu nav daudz, daudzi mainīgie, kas AMI vēl ir (piemēram, makro izsaukumi, iestatīšanas mainīgie makro iekšienē, tajā skaitā zvanu ierakstīšana) netiek izsekoti. Tāpēc pareizai un precīzai uzskaitei pagaidām izvēlēsimies AMI (bet ne pilnībā). Turklāt (nu, kur gan būtu bez šī, mēs esam slinki cilvēki) - oriģināldarbā (raksts habr) izmantojiet PAMI. *Tad jums ir jāmēģina pārrakstīt uz ARI, bet ne to, ka tas darbosies.
Integrācijas atjaunošana
Lai mūsu FreePBX varētu vienkāršā veidā ziņot AMI par zvana sākumu, beigu laiku, numuriem, ierakstīto failu nosaukumiem, visvieglāk ir aprēķināt zvana ilgumu, izmantojot to pašu triku kā sākotnējie autori. - ievadiet savus mainīgos un parsējiet izvadi to klātbūtnei. PAMI iesaka to darīt, vienkārši izmantojot filtra funkciju.
Šeit ir piemērs, kā iestatīt savu mainīgo zvana sākuma laikam (s ir īpašs numurs sastādīšanas plānā, kas tiek veikts PIRMS DID meklēšanas sākšanas)
Tā kā FreePBX pārraksta failus extendion.conf un extension_extra.conf, mēs izmantosim failu pagarinājums_paraža.conf
Pilns paplašinājuma_custom.conf kods
[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
Iezīme un atšķirība no oriģinālā raksta autoru oriģinālā numura plāna -
Dialplan .conf formātā, kā FreePBX to vēlas (jā, tas var .ael, bet ne visas versijas un tas ne vienmēr ir ērti)
Tā vietā, lai apstrādātu beigas caur exten=>h, apstrāde tika ieviesta caur hangup_handler, jo FreePBX iezvanes plāns darbojās tikai ar to
Izlabota skripta izsaukuma virkne, pievienotas pēdiņas un ārējā zvana numurs ExtNum
Apstrāde tiek pārvietota uz _pielāgotiem kontekstiem un ļauj nepieskarties un nerediģēt FreePBX konfigurācijas — ienākošais, izmantojot [ext-did-custom], izejošs caur [outbound-allroutes-custom]
Nav saistīšanas ar cipariem - fails ir universāls, un tas ir jākonfigurē tikai ceļam un saitei uz serveri
Lai sāktu darbu, jums ir arī jāpalaiž skripti AMI, izmantojot pieteikumvārdu un paroli - šim nolūkam FreePBX ir arī _custom fails.
manager_custom.conf failu
;; это логин
[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
Abi šie faili ir jāievieto mapē /etc/asterisk, pēc tam atkārtoti izlasiet konfigurācijas (vai restartējiet zvaigznīti)
# astrisk -rv
Connected to Asterisk 16.6.2 currently running on freepbx (pid = 31629)
#freepbx*CLI> dialplan reload
Dialplan reloaded.
#freepbx*CLI> exit
Tagad pāriesim pie PHP
Skriptu inicializācija un pakalpojuma izveide
Tā kā shēma darbam ar Bitrix 24, pakalpojumu AMI, nav gluži vienkārša un pārskatāma, tā ir jāapspriež atsevišķi. Zvaigznīte, kad ir aktivizēts AMI, vienkārši atver portu un viss. Kad klients pievienojas, tas pieprasa autorizāciju, pēc tam klients abonē nepieciešamos pasākumus. Notikumi ir vienkāršā tekstā, ko PAMI pārvērš strukturētos objektos un nodrošina iespēju iestatīt filtrēšanas funkciju tikai interesējošiem notikumiem, laukiem, cipariem utt.
Tiklīdz tiek saņemts zvans, NewExten notikums tiek aktivizēts, sākot no vecāku [from-pstn] konteksta, pēc tam visi notikumi notiek konteksta rindu secībā. Kad tiek saņemta informācija no CallMeCallerIDName un CallStart mainīgajiem, kas norādīti _custom dialplan,
Lietotāja ID pieprasīšanas funkcija, kas atbilst paplašinājuma numuram, uz kuru tika veikts zvans. Ko darīt, ja tā ir iezvanpieejas grupa? Jautājums ir politisks, vai jāveido zvans visiem uzreiz (kad visi zvana uzreiz) vai jāveido kā zvana pēc kārtas? Lielākajai daļai klientu ir Fisrt Available stratēģija, tāpēc ar to nav problēmu, tikai viens zvans. Bet problēma ir jāatrisina.
Zvanu reģistrācijas funkcija programmā Bitrix24, kas atgriež CallID, kas pēc tam ir nepieciešama, lai ziņotu par zvana parametriem un saiti uz ierakstu. Nepieciešams paplašinājuma numurs vai lietotāja ID
Pēc zvana beigām tiek izsaukta ieraksta lejupielādes funkcija, kas vienlaikus ziņo par zvana pabeigšanas statusu (Aizņemts, Nav atbildes, Veiksmīgi), kā arī lejupielādē saiti uz mp3 failu ar ierakstu (ja tāds ir).
Tā kā modulim CallMeIn.php ir jādarbojas nepārtraukti, tam ir izveidots SystemD starta fails callme.service, kas jāievieto mapē /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
skripta inicializācija un palaišana notiek, izmantojot systemctl vai pakalpojumu
Pakalpojums pēc vajadzības restartēsies pats (avāriju gadījumā). Iesūtnes izsekošanas pakalpojumam nav jāinstalē tīmekļa serveris, ir nepieciešams tikai php (kas noteikti atrodas FeePBX serverī). Bet, ja nebūs piekļuves zvanu ierakstiem, izmantojot tīmekļa serveri (arī ar https), zvanu ierakstus nebūs iespējams klausīties.
Tagad parunāsim par izejošajiem zvaniem. CallMeOut.php skriptam ir divas funkcijas:
Zvana iniciēšana, kad tiek saņemts pieprasījums pēc php skripta (tostarp izmantojot pogu "Zvanīt" pašā Bitrix). Tas nedarbojas bez tīmekļa servera, pieprasījums tiek saņemts caur HTTP POST, pieprasījumā ir marķieris
Ziņojums par zvanu, tā parametriem un ierakstiem Bitrix. Aktivizē zvaigznīte [sub-call-internal-ended] iezvanes plānā, kad zvans beidzas
Tīmekļa serveris ir nepieciešams tikai divām lietām - Bitrix ierakstu failu lejupielādei (izmantojot HTTPS) un CallMeOut.php skripta izsaukšanai. Varat izmantot iebūvēto FreePBX serveri, kura faili ir /var/www/html, varat instalēt citu serveri vai norādīt citu ceļu.
Web serveris
Atstāsim tīmekļa servera iestatīšanu neatkarīgai izpētei (tyts, tyts, tyts). Ja jums nav domēna, varat izmēģināt FreeDomain( https://www.freenom.com/ru/index.html), kas piešķirs jums bezmaksas nosaukumu jūsu baltajam IP (neaizmirstiet pārsūtīt portus 80, 443 caur maršrutētāju, ja ārējā adrese ir tikai tajā). Ja tikko izveidojāt DNS domēnu, jums jāgaida (no 15 minūtēm līdz 48 stundām), līdz tiek ielādēti visi serveri. Saskaņā ar pieredzi darbā ar vietējiem pakalpojumu sniedzējiem - no 1 stundas līdz dienai.
Instalācijas automatizācija
Lai padarītu instalēšanu vēl vienkāršāku, vietnē github ir izstrādāts instalētājs. Bet uz papīra tas gāja gludi - kamēr mēs to visu instalējam manuāli, jo pēc tam visam, padomājot, kļuva pilnīgi skaidrs, kas ar ko draudzējas, kurš kur iet un kā to atkļūdot. Vēl nav instalētāja
dokers
Ja vēlaties ātri izmēģināt risinājumu - ir iespēja ar Docker - ātri izveidojiet konteineru, piešķiriet tam pieslēgvietas uz āru, nolaidiet iestatījumu failus un mēģiniet (šī ir iespēja ar LetsEncrypt konteineru, ja jums jau ir sertifikāts , jums vienkārši jānovirza reversais starpniekserveris uz FreePBX tīmekļa serveri (mēs tam piešķīrām citu portu 88), LetsEncrypt docker, pamatojoties uz no šī raksta
Fails ir jāpalaiž lejupielādētajā projekta mapē (pēc git clone), bet vispirms atveriet zvaigznītes konfigurācijas (zvaigznītes mapē) un ierakstiet tur ceļus uz ierakstiem un savas vietnes URL.
Šis docker-compose.yaml fails tiek palaists, izmantojot
docker-compose up -d
Ja nginx netiek startēts, tad kaut kas nav kārtībā ar konfigurāciju mapē nginx/ssl_docker.conf
Citas integrācijas
Un kāpēc gan neievietot dažus CRM skriptos vienlaikus, mēs domājām. Mēs pētījām vairākas citas CRM API, īpaši bezmaksas iebūvēto PBX - ShugarCRM un Vtiger, un jā! jā, princips ir tas pats. Bet tas ir cits stāsts, kuru mēs vēlāk augšupielādēsim github atsevišķi.