
У сетцы ёсць розныя варыянты інтэграцыі IP-АТС Asterisk і CRM Битрикс24, але мы, усё ж такі, вырашылі напісаць сваю.
Па функцыянале ўсё стандартна:
- Клікам на спасылку з нумарам тэлефона кліента ў Бітрыкс24, Asterisk злучае ўнутраны нумар карыстальніка, ад імя якога гэты клік здзейснены, з нумарам тэлефона кліента. У Битрикс24 фіксуецца запіс аб званку і па заканчэнні выкліку падцягваецца запіс размовы.
- На Asterisk паступае званок звонку - у інтэрфейсе Битрикс24 паказваем картку кліента таму супрацоўніку, на нумар якога гэты званок прыляцеў.
Калі такога кліента няма, адкрыем картку стварэння новага ліда.
Як толькі званок завершаны, адлюстроўваем гэта ў картцы і падцягваем запіс размовы.
Пад катом распавяду як усё наладзіць у сябе і дам лінк на github - так-так, забірайце і карыстайцеся!
агульнае апісанне
Сваю інтэграцыю мы назвалі CallMe. CallMe - гэта невялікае вэб-дадатак, напісанае на PHP.
Выкарыстоўваныя тэхналогіі і сэрвісы
- PHP 5.6
- кампазітар
- Nginx + php-fpm
- руководитель
- AMI (Asterisk Manager Interface)
- Вэбхукі Bitrix (спрошчаная рэалізацыя REST API)
Папярэдняя настройка
На серверы з Asterisk неабходна ўсталяваць web-сервер (у нас гэта nginx+php-fpm), supervisor і git.
Каманда для ўстаноўкі (CentOS):
yum install nginx php-fpm supervisor gitПераходзім дырэкторыю, даступную вэб-серверу, цягнем з гіта прыкладанне і выстаўляем патрэбныя правы на тэчку:
cd /var/www
git clone https://github.com/ViStepRU/callme.git
chown nginx. -R callme/
Далей наладзім nginx, наш канфіг размясціўся ў
/etc/nginx/conf.d/pbx.vistep.ru.confserver {
server_name www.pbx.vistep.ru pbx.vistep.ru;
listen *:80;
rewrite ^ https://pbx.vistep.ru$request_uri? permanent;
}
server {
# listen *:80;
# server_name pbx.vistep.ru;
access_log /var/log/nginx/pbx.vistep.ru.access.log main;
error_log /var/log/nginx/pbx.vistep.ru.error.log;
listen 443 ssl http2;
server_name pbx.vistep.ru;
resolver 8.8.8.8;
ssl_stapling on;
ssl on;
ssl_certificate /etc/letsencrypt/live/pbx.vistep.ru/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/pbx.vistep.ru/privkey.pem;
ssl_dhparam /etc/nginx/certs/dhparam.pem;
ssl_session_timeout 24h;
ssl_session_cache shared:SSL:2m;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers kEECDH+AES128:kEECDH:kEDH:-3DES:kRSA+AES128:kEDH+3DES:DES-CBC3-SHA:!RC4:!aNULL:!eNULL:!MD5:!EXPORT:!LOW:!SEED:!CAMELLIA:!IDEA:!PSK:!SRP:!SSLv2;
ssl_prefer_server_ciphers on;
add_header Strict-Transport-Security "max-age=31536000;";
add_header Content-Security-Policy-Report-Only "default-src https:; script-src https: 'unsafe-eval' 'unsafe-inline'; style-src https: 'unsafe-inline'; img-src https: data:; font-src https: data:; report-uri /csp-report";
root /var/www/callme;
index index.php;
location ~ /. {
deny all; # запрет для скрытых файлов
}
location ~* /(?:uploads|files)/.*.php$ {
deny all; # запрет для загруженных скриптов
}
location ~* ^.+.(ogg|ogv|svg|svgz|eot|otf|woff|mp4|ttf|rss|atom|jpg|jpeg|gif|png|ico|zip|tgz|gz|rar|bz2|doc|xls|exe|ppt|tar|mid|midi|wav|bmp|rtf)$ {
access_log off;
log_not_found off;
expires max; # кеширование статики
}
location ~ .php {
root /var/www/callme;
index index.php;
fastcgi_pass unix:/run/php/php5.6-fpm.sock;
# fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root/$fastcgi_script_name;
include /etc/nginx/fastcgi_params;
}
}
Разбор канфіга, пытанні бяспекі, атрыманне сертыфіката і нават выбар web-сервера я пакіну за рамкамі артыкула - пра гэта шмат напісана. У дадатку няма абмежаванняў, яно працуе і па http і па https.
У нас - https, сертыфікат let's encrypt.
Калі вы ўсё зрабілі правільна, то перайшоўшы па спасылцы павінны ўбачыць нешта падобнае

Настройка Битрикс24
Створым два вебхука.
Уваходны вебхук.
Пад уліковым запісам адміністратара (з id 1) ідзем па шляху: Прыкладанні -> Вэбхукі -> Дадаць вебхук -> Уваходны вебхук

Запаўняем параметры ўваходнага вэбхука як на скрінах:


І ціснем захаваць.
Пасля захавання Битрикс24 прадаставіць URL уваходнага вэбхука, напрыклад:

Захавайце сабе ваш варыянт URL без завяршальнага /profile/ - ён будзе выкарыстоўвацца ў дадатку для працы з уваходнымі званкамі.
У мяне гэта https://b24-xsynia.bitrix24.ru/rest/1/7eh61lh8pahw0fwt/
Выходны вебхук.
Прыкладанні -> Вэбхукі -> Дадаць вебхук -> Выходны вебхук
Падрабязнасці зноў на скрынях:


Захоўваем і атрымліваем код аўтарызацыі

У мяне гэта xcrp2ylhzzd2v43cmfjqmkvrgrcbkni6. Яго таксама трэба скапіяваць сабе, ён патрэбен для здзяйснення выходных званкоў.
Важна!
На серверы Битрикс24 павінен быць наладжаны ssl-сертыфікат (можна выкарыстоўваць letsencrypt), інакш api бітрыкса не будзе працаваць. Калі ў вас хмарная версія, можаце не хвалявацца - там ужо ёсць ssl.
Важна!
У полі «Адрас апрацоўшчыка» павінен быць указаны даступны з сеткі Інтэрнет адрас!
І апошняй рыскай усталюем наш CallMeOut у якасці прыкладання для здзяйснення званкоў (каб па кліку на нумар на АТС ляцела каманда для арыгіналы званка).
У меню выбіраемы: Яшчэ -> Тэлефонія -> Яшчэ -> Налады, ставім у «Нумар для выходнага званка па-змаўчанні» Дадатак: CallMeOut і ціснем «Захаваць»

Настройка asterisk
Для паспяховага ўзаемадзеяння Asterisk і Bitrix24 нам трэба дадаць AMI-карыстальніка callme у manager.conf:
[callme]
secret = JD3clEB8_f23r-3ry84gJ
deny = 0.0.0.0/0.0.0.0
permit = 127.0.0.1/255.255.255.0
permit= 10.100.111.249/255.255.255.255
permit = 192.168.254.0/255.255.255.0
read = system,call,log,verbose,agent,user,config,dtmf,reporting,cdr,dialplan
write = system,call,agent,log,verbose,user,config,command,reporting,originate
Далей ёсць некалькі хітрасцяў, якія запатрабуецца ўкараніць пасродкам dialplan (у нас гэта extensions.ael).
Прыводжу ўвесь файл, а пасля дам зацемкі:
globals {
WAV=/var/www/pbx.vistep.ru/callme/records/wav; //Временный каталог с WAV
MP3=/var/www/pbx.vistep.ru/callme/records/mp3; //Куда выгружать mp3 файлы
URLRECORDS=https://pbx.vistep.ru/callme/records/mp3;
RECORDING=1; // Запись, 1 - включена.
};
macro recording(calling,called) {
if ("${RECORDING}" = "1"){
Set(fname=${UNIQUEID}-${STRFTIME(${EPOCH},,%Y-%m-%d-%H_%M)}-${calling}-${called});
Set(datedir=${STRFTIME(${EPOCH},,%Y/%m/%d)});
System(mkdir -p ${MP3}/${datedir});
System(mkdir -p ${WAV}/${datedir});
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");
Set(FullFname=${URLRECORDS}/${datedir}/${fname}.mp3);
Set(CDR(filename)=${fname}.mp3);
Set(CDR(recordingfile)=${fname}.wav);
Set(CDR(realdst)=${called});
MixMonitor(${WAV}/${datedir}/${fname}.wav,b,${monopt});
};
};
context incoming {
888999 => {
&recording(${CALLERID(number)},${EXTEN});
Answer();
ExecIF(${CallMeCallerIDName}?Set(CALLERID(name)=${CallMeCallerIDName}):NoOp()); // выставляем CallerID если узнали его у Битрикс24
Set(CallStart=${STRFTIME(epoch,,%s)});
Queue(Q1,tT);
Set(CallMeDISPOSITION=${CDR(disposition)});
Hangup();
}
h => {
Set(CDR_PROP(disable)=true);
Set(CallStop=${STRFTIME(epoch,,%s)});
Set(CallMeDURATION=${MATH(${CallStop}-${CallStart},int)});
ExecIF(${ISNULL(${CallMeDISPOSITION})}?Set(CallMeDISPOSITION=${CDR(disposition)}):NoOP(=== CallMeDISPOSITION already was set ===));
}
}
context default {
_X. => {
Hangup();
}
};
context dial_out {
_[1237]XX => {
&recording(${CALLERID(number)},${EXTEN});
Set(__CallIntNum=${CALLERID(num)})
Set(CallStart=${STRFTIME(epoch,,%s)});
Dial(SIP/${EXTEN},,tTr);
Hangup();
}
_11XXX => {
&recording(${CALLERID(number)},${EXTEN});
Set(CallStart=${STRFTIME(epoch,,%s)});
Set(__CallIntNum=${CALLERID(num)});
Dial(SIP/${EXTEN:2}@toOurAster,,t);
Hangup();
}
_. => {
&recording(${CALLERID(number)},${EXTEN});
Set(__CallIntNum=${CALLERID(num)})
Set(CallStart=${STRFTIME(epoch,,%s)});
Dial(SIP/${EXTEN}@toOurAster,,t);
Hangup();
}
h => {
Set(CDR_PROP(disable)=true);
Set(CallStop=${STRFTIME(epoch,,%s)});
Set(CallMeDURATION=${MATH(${CallStop}-${CallStart},int)});
if(${ISNULL(${CallMeDISPOSITION})}) {
Set(CallMeDISPOSITION=${CDR(disposition)});
}
System(curl -s http://pbx.vistep.ru/CallMeOut.php --data action=sendcall2b24 --data call_id=${CallMeCALL_ID} --data-urlencode FullFname=${FullFname} --data CallIntNum=${CallIntNum} --data CallDuration=${CallMeDURATION} --data-urlencode CallDisposition=${CallMeDISPOSITION});
}
};
Пачнём з самага пачатку: дырэктыва глабальныя.
пераменная URLRECORDS захоўвае ў сабе URL да файлаў запісаў гутарак, па якім Bitrix24 будзе іх падцягваць у картку кантакту.
Далей нам цікавы макрас макрас запіс.
Тут, акрамя запісу размоваў, мы ўсталюем зменную FullFname.
Set(FullFname=${URLRECORDS}/${datedir}/${fname}.mp3);Яна захоўвае поўны URL да канкрэтнага файла (макрас выклікаецца ўсюды).
Разбяром выходны званок:
_. => {
&recording(${CALLERID(number)},${EXTEN});
Set(__CallIntNum=${CALLERID(num)})
Set(CallStart=${STRFTIME(epoch,,%s)});
Dial(SIP/${EXTEN}@toOurAster,,t);
Hangup();
}
h => {
Set(CDR_PROP(disable)=true);
Set(CallStop=${STRFTIME(epoch,,%s)});
Set(CallMeDURATION=${MATH(${CallStop}-${CallStart},int)});
if(${ISNULL(${CallMeDISPOSITION})}) {
Set(CallMeDISPOSITION=${CDR(disposition)});
}
System(curl -s http://pbx.vistep.ru/CallMeOut.php --data action=sendcall2b24 --data call_id=${CallMeCALL_ID} --data-urlencode FullFname=${FullFname} --data CallIntNum=${CallIntNum} --data CallDuration=${CallMeDURATION} --data-urlencode CallDisposition=${CallMeDISPOSITION});
}
Дапусцім мы тэлефануем на 89991234567, перш за ўсё трапляем сюды:
&recording(${CALLERID(number)},${EXTEN});г.зн. выклікаецца макрас запісы размовы і прастаўляюцца патрэбныя зменныя.
Далей
Set(__CallIntNum=${CALLERID(num)})
Set(CallStart=${STRFTIME(epoch,,%s)});
запісваем хто ініцыяваў званок і фіксуем час старту званка.
І па яго завяршэнні, у спецыяльным кантэксце h
h => {
Set(CDR_PROP(disable)=true);
Set(CallStop=${STRFTIME(epoch,,%s)});
Set(CallMeDURATION=${MATH(${CallStop}-${CallStart},int)});
if(${ISNULL(${CallMeDISPOSITION})}) {
Set(CallMeDISPOSITION=${CDR(disposition)});
}
System(curl -s http://pbx.vistep.ru/CallMeOut.php --data action=sendcall2b24 --data call_id=${CallMeCALL_ID} --data-urlencode FullFname=${FullFname} --data CallIntNum=${CallIntNum} --data CallDuration=${CallMeDURATION} --data-urlencode CallDisposition=${CallMeDISPOSITION});
}
адключаем запіс у табліцу CDR для гэтага экстэншэна (не трэба яно там), выстаўляем час завяршэння званка, вылічаем працягласць, калі вынік званка не вядомы - ставім (пераменная) CallMeDISPOSITION) і, апошнім крокам, шлем ўсё бітрыкс праз сістэмны curl.
І яшчэ крыху магіі – уваходны званок:
888999 => {
&recording(${CALLERID(number)},${EXTEN});
Answer();
ExecIF(${CallMeCallerIDName}?Set(CALLERID(name)=${CallMeCallerIDName}):NoOp()); // выставляем CallerID если узнали его у Битрикс24
Set(CallStart=${STRFTIME(epoch,,%s)}); // начинаем отсчет времени звонка
Queue(Q1,tT);
Set(CallMeDISPOSITION=${CDR(disposition)});
Hangup();
}
Тут нас цікавіць толькі адзін радок.
ExecIF(${CallMeCallerIDName}?Set(CALLERID(name)=${CallMeCallerIDName}):NoOp());Яна кажа АТС ўсталяваць CallerID(name) роўным зменнай CallMeCallerIDName.
Сама зменная CallMeCallerIDName, у сваю чаргу, усталёўваецца дадаткам CallMe (калі ў Bitrix24 ёсць прозвішча, імя па нумары патэлефанаваўшага - усталюем у якасці CallerID(name), не - нічога не будзем рабіць).
Настройка прыкладання
Файл настроек прыкладання - /var/www/pbx.vistep.ru/config.php
Апісанне параметраў прыкладання:
- CallMeDEBUG - калі 1, то ў лог файл будуць пісацца ўсе падзеі, апрацоўваныя дадаткам, 0 - нічога не пішам
- тэхналогіі - SIP/PJSIP/IAX/etc
- authToken - токен аўтарызацыі бітрыкс24, код аўтарызацыі выходнага вэбхука
- bitrixApiUrl — URL уваходнага вэбхука, без profile/
- extentions - спіс знешніх нумароў
- кантэкст - кантэкст для арыгіналу званка
- listener_timeout - хуткасць апрацоўкі падзей ад asterisk
- зорачка - масіў з наладамі падлучэння да астэрыску:
- гаспадар - ip або hostname сервера астэрыск
- схема - схема падлучэння (tcp://, tls://)
- порт - порт
- імя карыстальніка - Імя карыстальніка
- таямніца - пароль
- connect_timeout - таймаўт падключэння
- read_timeout - таймаўт чытання
прыклад файла настроек:
<?php
return array(
'CallMeDEBUG' => 1, // дебаг сообщения в логе: 1 - пишем, 0 - не пишем
'tech' => 'SIP',
'authToken' => 'xcrp2ylhzzd2v43cmfjqmkvrgrcbkni6', //токен авторизации битрикса
'bitrixApiUrl' => 'https://b24-xsynia.bitrix24.ru/rest/1/7eh61lh8pahw0fwt/', //url к api битрикса (входящий вебхук)
'extentions' => array('888999'), // список внешних номеров, через запятую
'context' => 'dial_out', //исходящий контекст для оригинации звонка
'asterisk' => array( // настройки для подключения к астериску
'host' => '10.100.111.249',
'scheme' => 'tcp://',
'port' => 5038,
'username' => 'callme',
'secret' => 'JD3clEB8_f23r-3ry84gJ',
'connect_timeout' => 10000,
'read_timeout' => 10000
),
'listener_timeout' => 300, //скорость обработки событий от asterisk
);Настройка supervisor
Supervisor служыць для запуску працэсу-апрацоўшчыка падзей ад Asterisk CallMeIn.php, які адсочвае ўваходныя званкі і ўзаемадзейнічае з Битрикс24 (паказаць картку, схаваць картку і г.д.).
Файл настроек, які неабходна стварыць:
/etc/supervisord.d/callme.conf
[program:callme]
command=/usr/bin/php CallMeIn.php
directory=/var/www/pbx.vistep.ru
autostart=true
autorestart=true
startretries=5
stderr_logfile=/var/www/pbx.vistep.ru/logs/daemon.log
stdout_logfile=/var/www/pbx.vistep.ru/logs/daemon.logЗапуск і рэстарт прыкладання:
supervisorctl start callme
supervisorctl restart callmeпрагляд статусу працы прыкладання:
supervisorctl status callme
callme RUNNING pid 11729, uptime 17 days, 16:58:07Заключэнне
Атрымалася досыць складана, але ўпэўнены - дасведчаны адміністратар здолее ўкараніць у сябе і парадаваць сваіх карыстальнікаў.
Як абяцаў, .
Пытанні, пажаданні - прашу ў каментары. Таксама калі цікава як ішла распрацоўка гэтай інтэграцыі, напішыце, а ў чарговым артыкуле я пастараюся расчыніць усё больш дэталёва.
Крыніца: habr.com
