ProHoster > blog > administrasi > Memahami FreePBX dan mengintegrasikannya dengan Bitrix24 dan lainnya
Memahami FreePBX dan mengintegrasikannya dengan Bitrix24 dan lainnya
Bitrix24 adalah gabungan besar yang menggabungkan CRM, alur kerja, akuntansi, dan banyak hal lain yang sangat disukai manajer dan tidak disukai staf TI. Portal ini digunakan oleh banyak perusahaan kecil dan menengah, termasuk klinik kecil, produsen, dan bahkan salon kecantikan. Fungsi utama yang "dicintai" manajer adalah integrasi telepon dan CRM, ketika panggilan apa pun segera direkam dalam CRM, kartu klien dibuat, ketika masuk, informasi tentang klien ditampilkan dan Anda dapat langsung melihat siapa dia, apa dia dapat dijual dan berapa utangnya. Tetapi telepon dari Bitrix24 dan integrasinya dengan CRM membutuhkan biaya, terkadang banyak. Dalam artikel ini saya akan memberi tahu Anda pengalaman mengintegrasikan dengan alat terbuka dan IP PBX yang populer FreePBX, dan juga mempertimbangkan logika pekerjaan berbagai bagian
Saya bekerja sebagai agen outsourcing di perusahaan yang menjual dan mengonfigurasi, mengintegrasikan telepon IP. Ketika saya ditanya apakah kami dapat menawarkan sesuatu kepada ini dan perusahaan ini untuk mengintegrasikan Bitrix24 dengan PBX yang dimiliki pelanggan, serta dengan PBX virtual di berbagai perusahaan VDS, saya pergi ke Google. Dan tentu saja dia memberi saya link ke artikel di habr, di mana ada deskripsi, dan github, dan semuanya tampak berfungsi. Namun saat mencoba menggunakan solusi ini, ternyata Bitrix24 tidak lagi sama seperti sebelumnya, dan banyak yang perlu dilakukan ulang. Selain itu, FreePBX bukanlah tanda bintang kosong untuk Anda, di sini Anda perlu memikirkan cara menggabungkan kemudahan penggunaan dan dialplan hardcore dalam file konfigurasi.
Kami mempelajari logika kerja
Jadi sebagai permulaan, bagaimana semuanya harus bekerja. Ketika panggilan datang dari luar PBX (acara SIP INVITE dari penyedia), pemrosesan dialplan (dialplan, dialplan) dimulai - aturan tentang apa dan bagaimana urutan panggilan tersebut. Dari paket pertama, Anda bisa mendapatkan banyak informasi, yang kemudian dapat digunakan dalam aturan. Alat yang sangat baik untuk mempelajari bagian dalam SIP adalah penganalisa ambil (link) yang hanya diinstal di distribusi populer melalui apt install/yum install dan sejenisnya, tetapi juga dapat dibuat dari sumber. Mari kita lihat log panggilan di sngrep
Dalam bentuk yang disederhanakan, dialplan hanya berurusan dengan paket pertama, terkadang juga selama percakapan, panggilan dialihkan, penekanan tombol (DTMF), berbagai hal menarik seperti FollowMe, RingGroup, IVR dan lain-lain.
Apa yang ada di dalam Paket Undangan
Sebenarnya, sebagian besar dialplan sederhana bekerja dengan dua bidang pertama, dan seluruh logika berputar di sekitar DID dan CallerID. DID - di mana kita menelepon, CallerID - siapa yang menelepon.
Tetapi bagaimanapun, kami memiliki perusahaan dan bukan satu telepon - yang berarti bahwa PBX kemungkinan besar memiliki grup panggilan (dering simultan / berturut-turut dari beberapa perangkat) di nomor kota (Grup Dering), IVR (Halo, Anda menelepon ... Tekan satu untuk ...), Mesin penjawab ( Frase), Kondisi Waktu, Penerusan ke nomor lain atau ke sel (FollowMe, Forward). Ini berarti sangat sulit untuk menentukan dengan jelas siapa yang benar-benar akan menerima panggilan dan dengan siapa akan berbicara ketika panggilan masuk. Berikut adalah contoh awal panggilan khas di PBX klien kami
Setelah panggilan berhasil masuk ke PBX, ia berjalan melalui dialplan dalam "konteks" yang berbeda. Konteks dari sudut pandang Asterisk adalah sekumpulan perintah bernomor, yang masing-masing berisi filter berdasarkan nomor yang dipanggil (disebut exten, untuk panggilan eksternal pada tahap awal exten=DID). Perintah di baris dialplan dapat berupa apa saja - fungsi internal (misalnya, memanggil pelanggan internal - Dial(), letakkan telepon - Hangup()), operator kondisional (IF, ELSE, ExecIF dan sejenisnya), transisi ke aturan lain dari konteks ini (Goto, GotoIF), transisi ke konteks lain dalam bentuk pemanggilan fungsi (Gosub, Makro). Direktif terpisah include имя_контекста, yang menambahkan perintah dari konteks lain ke akhir konteks saat ini. Perintah yang disertakan melalui include selalu dijalankan setelah perintah dari konteks saat ini.
Seluruh logika FreePBX dibangun di atas penyertaan konteks yang berbeda satu sama lain melalui penyertaan dan panggilan melalui penangan Gosub, Makro, dan Handler. Pertimbangkan konteks panggilan masuk FreePBX
Panggilan melewati semua konteks dari atas ke bawah secara bergantian, di setiap konteks dapat ada panggilan ke konteks lain seperti makro (Makro), fungsi (Gosub) atau hanya transisi (Goto), jadi pohon sebenarnya dari apa yang disebut hanya bisa dilacak dalam log.
Sebuah diagram pengaturan tipikal untuk PBX tipikal ditunjukkan di bawah ini. Saat menelepon, DID dicari di rute masuk, kondisi sementara diperiksa, jika semuanya beres, menu suara diluncurkan. Dari situ, dengan menekan tombol 1 atau batas waktu, keluar ke grup operator panggilan. Setelah panggilan berakhir, makro hangupcall dipanggil, setelah itu tidak ada yang dapat dilakukan di dialplan, kecuali penangan khusus (penangan hangup).
Di mana dalam algoritme panggilan ini kami harus memberikan informasi tentang awal panggilan ke CRM, di mana harus mulai merekam, di mana harus mengakhiri rekaman, dan mengirimkannya bersama dengan informasi tentang panggilan ke CRM?
Integrasi dengan sistem eksternal
Apa itu integrasi PBX dan CRM? Ini adalah pengaturan dan program yang mengonversi data dan peristiwa antara kedua platform ini dan mengirimkannya satu sama lain. Cara paling umum bagi sistem independen untuk berkomunikasi adalah melalui API, dan cara paling populer untuk mengakses API adalah HTTP REST. Tapi tidak untuk tanda bintang.
Di dalam Asterisk adalah:
AGI - panggilan sinkron ke program / komponen eksternal, digunakan terutama di dialplan, ada perpustakaan seperti itu phpagi, halaman
AMI - soket TCP teks yang bekerja dengan prinsip berlangganan acara dan memasukkan perintah teks, menyerupai SMTP dari dalam, dapat melacak acara dan mengelola panggilan, ada perpustakaan PAMI - yang paling populer untuk membuat koneksi dengan Asterisk
Contoh keluaran AMI
Acara: Saluran baru
Hak istimewa: panggilan, semua
Saluran: PJSIP/VMS_pjsip-0000078b
Status Saluran: 4
ChannelStateDesc: Dering
Nomor ID Penelepon: 111222
Nama ID Penelepon: 111222
Nomor Jalur Terhubung:
nama baris terhubung:
Bahasa: en
Kode akun:
Konteks: dari-pstn
Perpanjangan: s
Prioritas: 1
Nomor unik: 1599589046.5244
Linkedid: 1599589046.5244
ARI adalah campuran keduanya, semua melalui REST, WebSocket, dalam format JSON - tetapi dengan pustaka dan pembungkus baru, tidak terlalu bagus, ditemukan begitu saja (phparia, phpari) yang menjadi perkembangannya sekitar 3 tahun yang lalu.
Kenyamanan atau ketidaknyamanan, kemungkinan atau ketidakmungkinan bekerja dengan API tertentu ditentukan oleh tugas yang perlu diselesaikan. Tugas untuk integrasi dengan CRM adalah sebagai berikut:
Lacak awal panggilan, ke mana ia ditransfer, tarik CallerID, DID, waktu mulai dan akhir, mungkin data dari direktori (untuk mencari koneksi antara ponsel dan pengguna CRM)
Mulai dan akhiri rekaman panggilan, simpan dalam format yang diinginkan, beri tahu di akhir rekaman di mana file tersebut berada
Mulai panggilan pada acara eksternal (dari program), panggil nomor internal, nomor eksternal dan sambungkan
Opsional: mengintegrasikan dengan CRM, grup dialer dan FollowME untuk transfer panggilan otomatis tanpa adanya tempat (menurut CRM)
Semua tugas ini dapat diselesaikan melalui AMI atau ARI, tetapi ARI memberikan informasi yang jauh lebih sedikit, tidak banyak kejadian, banyak variabel yang masih dimiliki AMI (misalnya, panggilan makro, variabel pengaturan di dalam makro, termasuk perekaman panggilan) tidak dilacak. Oleh karena itu, untuk pelacakan yang benar dan akurat, mari pilih AMI untuk saat ini (tetapi tidak sepenuhnya). Selain itu (yah, di mana tanpa ini, kami adalah orang-orang malas) - dalam karya aslinya (artikel di habr) menggunakan PAMI. *Maka Anda perlu mencoba menulis ulang ke ARI, tetapi bukan fakta bahwa itu akan berhasil.
Menemukan kembali integrasi
Agar FreePBX kami dapat melaporkan ke AMI dengan cara sederhana tentang awal panggilan, waktu berakhir, nomor, nama file yang direkam, paling mudah untuk menghitung durasi panggilan menggunakan trik yang sama dengan penulis aslinya. - masukkan variabel Anda dan parsing output untuk keberadaannya. PAMI menyarankan melakukan ini hanya melalui fungsi filter.
Berikut adalah contoh pengaturan variabel Anda sendiri untuk waktu mulai panggilan (s adalah nomor khusus dalam dialplan yang dilakukan SEBELUM memulai pencarian DID)
Karena FreePBX menimpa file extension.conf dan extension_tambahan.conf, kita akan menggunakan file tersebut ekstensi_adat.conf
Kode lengkap extension_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
Fitur dan perbedaan dari dialplan asli dari penulis artikel asli -
Dialplan dalam format .conf, sesuai keinginan FreePBX (ya, bisa .ael, tapi tidak semua versi dan tidak selalu nyaman)
Alih-alih memproses akhir melalui exten=>h, pemrosesan diperkenalkan melalui hangup_handler, karena dialplan FreePBX hanya berfungsi dengannya
Memperbaiki string panggilan skrip, kutipan tambahan, dan nomor panggilan eksternal ExtNum
Pemrosesan dipindahkan ke _custom contexts dan memungkinkan Anda untuk tidak menyentuh atau mengedit konfigurasi FreePBX - masuk melalui [ext-melakukan-custom], keluar melalui [keluar-semua rute-kustom]
Tidak mengikat angka - file bersifat universal dan hanya perlu dikonfigurasi untuk jalur dan tautan ke server
Untuk memulai, Anda juga perlu menjalankan skrip di AMI dengan login dan kata sandi - untuk ini, FreePBX juga memiliki file _custom
file 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
Kedua file ini harus ditempatkan di /etc/asterisk, lalu baca kembali konfigurasinya (atau restart tanda bintangnya)
# astrisk -rv
Connected to Asterisk 16.6.2 currently running on freepbx (pid = 31629)
#freepbx*CLI> dialplan reload
Dialplan reloaded.
#freepbx*CLI> exit
Sekarang mari beralih ke PHP
Menginisialisasi skrip dan membuat layanan
Karena skema untuk bekerja dengan Bitrix 24, layanan untuk AMI, tidak sepenuhnya sederhana dan transparan, ini harus didiskusikan secara terpisah. Asterisk, saat AMI diaktifkan, cukup buka port dan hanya itu. Saat klien bergabung, ia meminta otorisasi, lalu klien berlangganan ke acara yang diperlukan. Acara datang dalam teks biasa, yang diubah PAMI menjadi objek terstruktur dan menyediakan kemampuan untuk mengatur fungsi pemfilteran hanya untuk acara yang diminati, bidang, angka, dll.
Segera setelah panggilan masuk, acara NewExten dipicu mulai dari konteks induk [from-pstn], lalu semua acara berjalan sesuai urutan baris dalam konteks. Ketika informasi diterima dari variabel CallMeCallerIDName dan CallStart yang ditentukan dalam _custom dialplan,
Fungsi meminta UserID yang sesuai dengan nomor ekstensi tempat panggilan datang. Bagaimana jika itu adalah grup dial-up? Pertanyaannya politis, apakah Anda perlu membuat panggilan ke semua orang sekaligus (saat semua orang menelepon sekaligus) atau membuat panggilan saat mereka menelepon secara bergantian? Sebagian besar klien memiliki strategi First Available, jadi tidak ada masalah dengan ini, hanya satu panggilan. Tapi masalahnya perlu diselesaikan.
Fungsi pendaftaran panggilan di Bitrix24, yang mengembalikan ID Panggilan, yang kemudian diperlukan untuk melaporkan parameter panggilan dan tautan ke rekaman. Memerlukan nomor ekstensi atau UserID
Setelah panggilan berakhir, fungsi unduh rekaman dipanggil, yang secara bersamaan melaporkan status penyelesaian panggilan (Sibuk, Tidak ada jawaban, Berhasil), dan juga mengunduh tautan ke file mp3 dengan catatan tersebut (jika ada).
Karena modul CallMeIn.php perlu dijalankan terus menerus, file startup SystemD telah dibuat untuknya callme.service, yang harus diletakkan di /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
inisialisasi dan peluncuran skrip terjadi melalui systemctl atau layanan
Layanan akan memulai ulang sendiri sesuai kebutuhan (jika terjadi crash). Layanan inbox tracking tidak membutuhkan web server untuk diinstall, hanya dibutuhkan php (yang pasti ada di server FeePBX). Tetapi dengan tidak adanya akses ke catatan panggilan melalui server Web (juga dengan https), tidak mungkin untuk mendengarkan catatan panggilan.
Sekarang mari kita bicara tentang panggilan keluar. Skrip CallMeOut.php memiliki dua fungsi:
Inisiasi panggilan saat permintaan diterima untuk skrip php (termasuk menggunakan tombol "Panggil" di Bitrix itu sendiri). Itu tidak berfungsi tanpa server web, permintaan diterima melalui HTTP POST, permintaan berisi token
Pesan tentang panggilan, parameternya, dan rekamannya di Bitrix. Diaktifkan oleh Asterisk di dialplan [sub-panggilan-internal-berakhir] saat panggilan berakhir
Server web diperlukan hanya untuk dua hal - mengunduh file rekaman Bitrix (melalui HTTPS) dan memanggil skrip CallMeOut.php. Anda dapat menggunakan server FreePBX bawaan, yang file-nya adalah /var/www/html, Anda dapat menginstal server lain atau menentukan jalur yang berbeda.
server web
Mari tinggalkan penyiapan server web untuk belajar mandiri (tyts, tyts, tyts). Jika Anda tidak memiliki domain, Anda dapat mencoba FreeDomain( https://www.freenom.com/ru/index.html), yang akan memberi Anda nama gratis untuk IP putih Anda (jangan lupa untuk meneruskan port 80, 443 melalui router jika alamat eksternal hanya ada di sana). Jika Anda baru saja membuat domain DNS, Anda harus menunggu (dari 15 menit hingga 48 jam) hingga semua server dimuat. Menurut pengalaman bekerja dengan penyedia domestik - dari 1 jam hingga sehari.
Otomatisasi instalasi
Penginstal telah dikembangkan di github untuk mempermudah penginstalan. Tapi itu mulus di atas kertas - saat kami menginstal semuanya secara manual, karena setelah mengotak-atik semua ini menjadi sangat jelas apa berteman dengan siapa, siapa pergi ke mana dan bagaimana cara men-debugnya. Belum ada penginstal
Buruh pelabuhan
Jika Anda ingin segera mencoba solusinya - ada opsi dengan Docker - buat wadah dengan cepat, berikan porta di luar, selipkan file pengaturan dan coba (ini adalah opsi dengan wadah LetsEncrypt, jika Anda sudah memiliki sertifikat, Anda hanya perlu mengarahkan proxy terbalik ke server web FreePBX (kami memberikannya port lain adalah 88), LetsEncrypt di buruh pelabuhan berdasarkan artikel ini
Anda perlu menjalankan file di folder proyek yang diunduh (setelah git clone), tetapi pertama-tama masuk ke konfigurasi asterisk (folder asterisk) dan tulis jalur ke catatan dan URL situs Anda di sana
Jika nginx tidak dimulai, berarti ada yang salah dengan konfigurasi di folder nginx/ssl_docker.conf
Integrasi lainnya
Dan mengapa tidak memasukkan beberapa CRM ke dalam skrip pada saat yang sama, pikir kami. Kami mempelajari beberapa API CRM lainnya, terutama PBX bawaan gratis - ShugarCRM dan Vtiger, dan ya! ya, prinsipnya sama. Tapi ini cerita lain, yang nantinya akan kami unggah ke github secara terpisah.