Asterisk 和 Bitrix24 的集成

Asterisk 和 Bitrix24 的集成
該網絡有不同的選項來集成 IP-PBX Asterisk 和 CRM Bitrix24,但我們還是決定自己編寫。

在功能上,一切都是標準的:

  • 通過在 Bitrix24 中點擊帶有客戶電話號碼的鏈接,Asterisk 將代表這次點擊的用戶的內部號碼與客戶的電話號碼聯繫起來。 在Bitrix24中,會記錄通話記錄,通話結束時,拉出通話記錄。
  • 一個呼叫從外部到達 Asterisk - 在 Bitrix24 界面中,我們向收到此呼叫的員工出示客戶卡。
    如果沒有這樣的客戶,請打開卡片以創建新的潛在客戶。
    通話一結束,我們就會在卡片中反映這一點,並調出通話錄音。

切下,我會告訴你如何為自己設置一切,並提供一個指向 github 的鏈接——是的,是的,拿走並使用它!

一般描述

我們稱我們的集成為 CallMe。 CallMe 是一個用 PHP 編寫的小型 Web 應用程序。

使用的技術和服務

  • PHP 5.6的
  • PHP AMI 庫
  • 作曲家
  • nginx + php fpm
  • AMI(星號管理器接口)
  • Bitrix webhooks(簡化的 REST API 實現)

預設

在安裝了 Asterisk 的服務器上,需要安裝 web 服務器(我們有 nginx + php-fpm)、supervisor 和 git。

安裝命令(CentOS):

yum install nginx php-fpm supervisor git

我們傳遞 Web 服務器可用的目錄,從 git 中拉取應用程序並為該文件夾設置必要的權限:


cd /var/www
git clone https://github.com/ViStepRU/callme.git
chown nginx. -R callme/

接下來配置nginx,我們的config位於

/etc/nginx/conf.d/pbx.vistep.ru.conf

server {
	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,讓我們加密證書。

如果你做的一切都正確,那麼通過點擊鏈接你應該看到這樣的東西

Asterisk 和 Bitrix24 的集成

設置 Bitrix24

讓我們創建兩個 webhook。

傳入的網絡鉤子。

在管理員帳戶下(ID 為 1)沿著路徑:Applications -> Webhooks -> Add webhook -> Incoming webhook

Asterisk 和 Bitrix24 的集成

按照屏幕截圖填寫傳入的 webhook 的參數:

Asterisk 和 Bitrix24 的集成

Asterisk 和 Bitrix24 的集成

然後點擊保存。

保存後,Bitrix24 會提供傳入的 webhook 的 URL,例如:

Asterisk 和 Bitrix24 的集成

保存不帶尾隨 /profile/ 的 URL 版本 - 它將在應用程序中用於處理來電。

我有 https://b24-xsynia.bitrix24.ru/rest/1/7eh61lh8pahw0fwt/

傳出網絡鉤子。

應用程序 -> Webhooks -> 添加 Webhook -> 傳出 Webhook

詳情見截圖:

Asterisk 和 Bitrix24 的集成

Asterisk 和 Bitrix24 的集成

保存並獲取授權碼

Asterisk 和 Bitrix24 的集成

我有 xcrp2ylhzzd2v43cmfjqmkvrgrcbkni6. 您還需要將其複制給自己,需要撥打電話。

重要的信息!

必須在 Bitrix24 服務器上配置 ssl 證書(可以使用 letsencrypt),否則 BitrixXNUMX api 將無法工作。 如果您有云版本,請不要擔心 - ssl 已經存在。

重要的信息!

在“處理器地址”字段中,必須指明可從 Internet 訪問的地址!

最後一步,讓我們將 CallMeOut 安裝為用於撥打電話的應用程序(以便通過單擊 PBX 上的號碼,將彈出一個命令來發起呼叫)。

在菜單中選擇:更多->電話->更多->設置,設置為“默認撥出號碼”應用程序:CallMeOut,點擊“保存”

Asterisk 和 Bitrix24 的集成

星號設置

為了 Asterisk 和 Bitrix24 之間的成功交互,我們需要將 callme AMI 用戶添加到 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

接下來,需要使用撥號方案(我們有 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});
}

};

讓我們從頭開始:指令 全局.

多變的 網址記錄 存儲對話錄音文件的 URL,Bitrix24 將根據該 URL 將它們拉入名片中。

接下來我們感興趣的是macro宏 記錄.

在這裡,除了記錄對話外,我們還將設置變量 全名.

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 表中的條目(那裡不需要),設置呼叫的結束時間,計算持續時間,如果呼叫結果未知 - 設置(變量 叫我性格) 最後一步,通過系統 curl 將所有內容髮送到 Bitrix。

還有一點神奇 - 來電:

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());

她說 PBX 安裝 來電顯示(姓名) 多變的 CallMe來電顯示名稱.

CallMeCallerIDName 變量本身由 CallMe 應用程序設置(如果 Bitrix24 具有呼叫者號碼的全名,我們將其設置為 來電顯示(姓名),不 - 我們不會做任何事情)。

應用程序設置

應用程序設置文件 - /var/www/pbx.vistep.ru/config.php

應用參數說明:

  • 叫我調試 - 如果為 1,則應用程序處理的所有事件都將寫入日誌文件,0 - 我們不寫入任何內容
  • 高科技 SIP/PJSIP/IAX/等
  • 授權令牌 — Bitrix24 授權令牌,傳出 webhook 授權碼
  • bitrixApiUrl — 傳入 webhook 的 URL,沒有配置文件/
  • 擴展 — 外部號碼列表
  • 上下文 — 呼叫發起的上下文
  • 監聽器超時 - 來自星號的事件處理速度
  • 星號 - 帶有星號連接設置的數組:
  • 主持人 - 星號服務器的 ip 或主機名
  • 方案 — 連接圖 (tcp://, tls://)
  • 端口 - 港口
  • 用戶名 - 用戶名
  • 秘密 - 密碼
  • 連接超時 - 連接超時
  • 讀超時 - 讀取超時

示例設置文件:

 <?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 用於啟動Asterisk CallMeIn.php 事件處理進程,該進程監聽來電並與Bitrix24 進行交互(出示卡片、隱藏卡片等)。

要創建的設置文件:

/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

結論

事實證明這很困難,但我相信有經驗的管理員將能夠實施並取悅他的用戶。

按照承諾, 鏈接到github.

問題,建議 - 請在評論中。 此外,如果您對這種集成的開發過程感興趣,請寫信,在下一篇文章中,我將嘗試更詳細地揭示一切。

來源: www.habr.com

添加評論