Tích hợp Asterisk và Bitrix24

Tích hợp Asterisk và Bitrix24
Có nhiều tùy chọn khác nhau để tích hợp IP-PBX Asterisk và CRM Bitrix24 trên mạng, nhưng chúng tôi vẫn quyết định tự viết.

Về chức năng, mọi thứ đều tiêu chuẩn:

  • Bằng cách nhấp vào liên kết có số điện thoại của khách hàng trong Bitrix24, Asterisk kết nối số nội bộ của người dùng thay mặt họ thực hiện nhấp chuột với số điện thoại của khách hàng. Trong Bitrix24, bản ghi cuộc gọi được ghi lại và khi kết thúc cuộc gọi, bản ghi cuộc trò chuyện sẽ được kéo lên.
  • Asterisk nhận cuộc gọi từ bên ngoài - trong giao diện Bitrix24, chúng tôi hiển thị thẻ khách hàng cho nhân viên có số điện thoại nhận cuộc gọi này.
    Nếu không có khách hàng nào như vậy, chúng tôi sẽ mở thẻ để tạo khách hàng tiềm năng mới.
    Ngay sau khi cuộc gọi kết thúc, chúng tôi phản ánh điều này trên thẻ và đưa ra bản ghi âm cuộc trò chuyện.

Bên dưới phần cắt, tôi sẽ hướng dẫn bạn cách thiết lập mọi thứ cho chính bạn và cung cấp cho bạn liên kết tới github - vâng, vâng, hãy lấy nó và sử dụng nó!

Mô tả chung

Chúng tôi gọi sự tích hợp của mình là CallMe. CallMe là một ứng dụng web nhỏ được viết bằng PHP.

Công nghệ và dịch vụ được sử dụng

  • PHP 5.6
  • Thư viện PHP AMI
  • sáng tác
  • Nginx + php-fpm
  • giám sát
  • AMI (Giao diện quản lý dấu hoa thị)
  • Webhooks Bitrix (triển khai API REST được đơn giản hóa)

đặt trước

Trên máy chủ có Asterisk, bạn cần cài đặt máy chủ web (đối với chúng tôi đó là nginx+php-fpm), trình giám sát và git.

Lệnh cài đặt (CentOS):

yum install nginx php-fpm supervisor git

Chúng tôi đi đến thư mục có thể truy cập được trên máy chủ web, kéo ứng dụng từ Git và đặt các quyền cần thiết cho thư mục:


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

Tiếp theo, hãy định cấu hình nginx, cấu hình của chúng tôi nằm ở

/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;
		}
}

Tôi sẽ để phân tích cấu hình, các vấn đề bảo mật, lấy chứng chỉ và thậm chí chọn máy chủ web nằm ngoài phạm vi của bài viết - rất nhiều điều đã được viết về vấn đề này. Ứng dụng này không có hạn chế, nó hoạt động trên cả http và https.

Chúng tôi sử dụng https, hãy mã hóa chứng chỉ.

Nếu bạn đã làm mọi thứ chính xác, thì khi nhấp vào liên kết, bạn sẽ thấy một cái gì đó như thế này

Tích hợp Asterisk và Bitrix24

Thiết lập Bitrix24

Hãy tạo hai webhook.

Webhook đang đến.

Trong tài khoản quản trị viên (có id 1), hãy làm theo đường dẫn: Ứng dụng -> Webhooks -> Thêm webhook -> Webhook đến

Tích hợp Asterisk và Bitrix24

Điền các thông số của webhook đến như trong ảnh chụp màn hình:

Tích hợp Asterisk và Bitrix24

Tích hợp Asterisk và Bitrix24

Và bấm lưu.

Sau khi lưu, Bitrix24 sẽ cung cấp URL của webhook đến, ví dụ:

Tích hợp Asterisk và Bitrix24

Lưu phiên bản URL của bạn mà không có /profile/ cuối cùng - nó sẽ được sử dụng trong ứng dụng để xử lý các cuộc gọi đến.

Tôi có cái này https://b24-xsynia.bitrix24.ru/rest/1/7eh61lh8pahw0fwt/

Webhook gửi đi.

Ứng dụng -> Webhooks -> Thêm webhook -> Webhook gửi đi

Thông tin chi tiết một lần nữa trên ảnh chụp màn hình:

Tích hợp Asterisk và Bitrix24

Tích hợp Asterisk và Bitrix24

Lưu và nhận mã ủy quyền

Tích hợp Asterisk và Bitrix24

Tôi có cái này xcrp2ylhzzd2v43cmfjqmkvrgrcbkni6. Bạn cũng cần phải sao chép nó cho chính mình; bạn cần nó để thực hiện các cuộc gọi đi.

Quan trọng!

Chứng chỉ SSL phải được cấu hình trên máy chủ Bitrix24 (bạn có thể sử dụng letencrypt), nếu không api Bitrix sẽ không hoạt động. Nếu bạn có phiên bản đám mây, đừng lo lắng - nó đã có ssl.

Quan trọng!

Trường "Địa chỉ bộ xử lý" phải chứa địa chỉ có thể truy cập được từ Internet!

Và cuối cùng, hãy cài đặt CallMeOut của chúng tôi làm ứng dụng thực hiện cuộc gọi (để khi bạn nhấp vào số trên PBX, lệnh bắt đầu cuộc gọi sẽ bay đi).

Trong menu chọn: Khác -> Điện thoại -> Khác -> Cài đặt, đặt trong “Số cuộc gọi đi mặc định” Ứng dụng: CallMeOut và nhấp vào “Lưu”

Tích hợp Asterisk và Bitrix24

Đang thiết lập dấu hoa thị

Để tương tác thành công giữa Asterisk và Bitrix24, chúng ta cần thêm callme người dùng AMI vào 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

Tiếp theo, có một số thủ thuật sẽ cần được triển khai thông qua dialplan (đối với chúng tôi đây là phần mở rộng.ael).

Tôi sẽ cung cấp toàn bộ hồ sơ và sau đó tôi sẽ đưa ra lời giải thích:

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

};

Hãy bắt đầu lại từ đầu: chỉ thị toàn cầu.

Biến HỒ SƠ URL lưu trữ URL tới các file ghi âm cuộc trò chuyện, theo đó Bitrix24 sẽ kéo chúng vào thẻ liên hệ.

Tiếp theo chúng ta quan tâm đến macro vĩ mô ghi âm.

Ở đây, ngoài việc ghi lại cuộc hội thoại, chúng ta sẽ đặt biến Tên đầy đủ.

Set(FullFname=${URLRECORDS}/${datedir}/${fname}.mp3);

Nó lưu trữ URL đầy đủ vào một tệp cụ thể (macro được gọi ở mọi nơi).

Hãy phân tích cuộc gọi đi:

_. => {
	&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});
}

Giả sử chúng ta gọi 89991234567, trước hết chúng ta đến đây:

&recording(${CALLERID(number)},${EXTEN});

những thứ kia. Macro ghi âm cuộc hội thoại được gọi và các biến cần thiết được đặt.

Tiếp theo

        Set(__CallIntNum=${CALLERID(num)})
	Set(CallStart=${STRFTIME(epoch,,%s)});

Chúng tôi ghi lại ai đã bắt đầu cuộc gọi và ghi lại thời gian bắt đầu cuộc gọi.

Và sau khi hoàn thành, trong một bối cảnh đặc biệt 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});
}

vô hiệu hóa mục nhập vào bảng CDR cho tiện ích mở rộng này (không cần thiết ở đó), đặt thời gian kết thúc cuộc gọi, tính thời lượng, nếu không biết kết quả của cuộc gọi - đặt (biến GọiTôiBố trí) và bước cuối cùng, gửi mọi thứ tới Bitrix thông qua hệ thống cuộn tròn.

Và một điều kỳ diệu nữa - một cuộc gọi đến:

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

Ở đây chúng tôi chỉ quan tâm đến một dòng.

ExecIF(${CallMeCallerIDName}?Set(CALLERID(name)=${CallMeCallerIDName}):NoOp());

Cô bảo tổng đài cài đặt ID người gọi (tên) bằng biến Gọi cho tôiTên người gọiID.

Biến CallMeCallerIDName lần lượt được thiết lập bởi ứng dụng CallMe (nếu Bitrix24 có tên đầy đủ cho số người gọi, hãy đặt nó là ID người gọi (tên), không - chúng tôi sẽ không làm gì cả).

Thiết lập ứng dụng

Tệp cài đặt ứng dụng - /var/www/pbx.vistep.ru/config.php

Mô tả các tham số ứng dụng:

  • Gọi cho tôiGỡ lỗi — nếu là 1 thì tất cả các sự kiện được ứng dụng xử lý sẽ được ghi vào tệp nhật ký, 0 — chúng tôi không ghi gì cả
  • công nghệ cao - SIP/PJSIP/IAX/v.v.
  • mã thông báo xác thực — Mã thông báo ủy quyền Bitrix24, mã ủy quyền webhook gửi đi
  • bitrixApiUrl — URL của webhook đến, không có hồ sơ/
  • phần mở rộng - danh sách các số bên ngoài
  • bối cảnh - bối cảnh để bắt đầu cuộc gọi
  • người nghe_timeout — tốc độ xử lý sự kiện từ dấu hoa thị
  • dấu hoa thị - một mảng có các cài đặt để kết nối với dấu hoa thị:
  • chủ nhà — ip hoặc tên máy chủ của máy chủ có dấu hoa thị
  • Đề án — sơ đồ kết nối (tcp://, tls://)
  • cổng - Hải cảng
  • tên truy nhập - Tên tài khoản
  • bí mật - mật khẩu
  • kết nối_timeout - hết thời gian kết nối
  • giờ đọc đã kết thúc - giờ đọc đã kết thúc

tập tin cài đặt ví dụ:

 <?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

);

Thiết lập giám sát

Người giám sát được sử dụng để khởi chạy quy trình xử lý sự kiện từ Asterisk CallMeIn.php, quy trình này sẽ giám sát các cuộc gọi đến và tương tác với Bitrix24 (hiển thị thẻ, ẩn thẻ, v.v.).

Tệp cài đặt sẽ được tạo:

/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

Khởi chạy và khởi động lại ứng dụng:

supervisorctl start callme
supervisorctl restart callme

Xem trạng thái hoạt động của ứng dụng:

supervisorctl status callme
callme                           RUNNING   pid 11729, uptime 17 days, 16:58:07

Kết luận

Nó hóa ra khá phức tạp, nhưng tôi chắc chắn rằng quản trị viên có kinh nghiệm sẽ có thể thực hiện nó và làm hài lòng người dùng của mình.

Như đã hứa, liên kết tới github.

Câu hỏi, gợi ý - xin vui lòng để lại trong phần bình luận. Ngoài ra, nếu bạn quan tâm đến quá trình phát triển của sự tích hợp này, hãy viết và trong bài viết tiếp theo, tôi sẽ cố gắng tiết lộ mọi thứ chi tiết hơn.

Nguồn: www.habr.com

Thêm một lời nhận xét