การรวม Asterisk และ Bitrix24

การรวม Asterisk และ Bitrix24
มีตัวเลือกที่แตกต่างกันสำหรับการรวม IP-PBX Asterisk และ CRM Bitrix24 บนเครือข่าย แต่เรายังคงตัดสินใจเขียนของเราเอง

ในแง่ของฟังก์ชันการทำงาน ทุกอย่างเป็นมาตรฐาน:

  • ด้วยการคลิกลิงก์ที่มีหมายเลขโทรศัพท์ของลูกค้าใน Bitrix24 เครื่องหมายดอกจันจะเชื่อมโยงหมายเลขภายในของผู้ใช้ซึ่งทำการคลิกในนามของหมายเลขโทรศัพท์ของลูกค้า ใน Bitrix24 บันทึกการโทรจะถูกบันทึก และเมื่อสิ้นสุดการโทร บันทึกการสนทนาจะถูกดึงขึ้นมา
  • เครื่องหมายดอกจันรับสายจากภายนอก - ในอินเทอร์เฟซ Bitrix24 เราจะแสดงบัตรลูกค้าแก่พนักงานที่ได้รับสายนี้
    หากไม่มีลูกค้าดังกล่าว เราจะเปิดการ์ดเพื่อสร้างลูกค้าเป้าหมายใหม่
    ทันทีที่การโทรเสร็จสิ้น เราจะสะท้อนสิ่งนี้บนการ์ดและดึงบันทึกการสนทนาขึ้นมา

ด้านล่างของการตัด ฉันจะบอกวิธีตั้งค่าทุกอย่างให้กับตัวคุณเอง และให้ลิงก์ไปยัง GitHub แก่คุณ ใช่ ใช่ นำไปใช้เลย!

คำอธิบายทั่วไป

เราเรียกการรวม CallMe ของเรา CallMe เป็นเว็บแอปพลิเคชั่นขนาดเล็กที่เขียนด้วย PHP

เทคโนโลยีและบริการที่ใช้

  • PHP ฮิต
  • ไลบรารี PHP AMI
  • แต่ง
  • Nginx + php-fpm
  • ผู้ดำเนินงาน
  • AMI (อินเทอร์เฟซตัวจัดการเครื่องหมายดอกจัน)
  • Bitrix webhooks (การใช้งาน REST API แบบง่าย)

การตั้งค่าล่วงหน้า

บนเซิร์ฟเวอร์ที่มีเครื่องหมายดอกจัน คุณต้องติดตั้งเว็บเซิร์ฟเวอร์ (สำหรับเราคือ nginx+php-fpm) ผู้ดูแล และ git

คำสั่งการติดตั้ง (CentOS):

yum install nginx php-fpm supervisor git

ไปที่ไดเร็กทอรีที่เว็บเซิร์ฟเวอร์สามารถเข้าถึงได้ดึงแอปพลิเคชันจาก Git และตั้งค่าสิทธิ์ที่จำเป็นให้กับโฟลเดอร์:


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

ต่อไปมากำหนดค่า nginx ซึ่งการกำหนดค่าของเราตั้งอยู่

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

ฉันจะออกจากการแยกวิเคราะห์การกำหนดค่าปัญหาด้านความปลอดภัยการได้รับใบรับรองและแม้แต่การเลือกเว็บเซิร์ฟเวอร์ที่อยู่นอกขอบเขตของบทความ - มีการเขียนมากมายเกี่ยวกับเรื่องนี้ แอปพลิเคชันไม่มีข้อจำกัด ใช้งานได้ทั้ง http และ https

เราใช้ https มาเข้ารหัสใบรับรองกันดีกว่า

หากคุณทำทุกอย่างถูกต้องแล้วเมื่อคลิกที่ลิงค์คุณจะเห็นสิ่งนี้

การรวม Asterisk และ Bitrix24

การตั้งค่า Bitrix24

มาสร้าง webhook สองอันกันเถอะ

เว็บฮุคขาเข้า

ภายใต้บัญชีผู้ดูแลระบบ (ที่มีรหัส 1) ให้ปฏิบัติตามเส้นทาง: แอปพลิเคชัน -> Webhooks -> เพิ่ม webhook -> webhook ขาเข้า

การรวม Asterisk และ Bitrix24

กรอกพารามิเตอร์ของ webhook ที่เข้ามาดังในภาพหน้าจอ:

การรวม Asterisk และ Bitrix24

การรวม Asterisk และ Bitrix24

และคลิกบันทึก

หลังจากบันทึก Bitrix24 จะระบุ URL ของ webhook ที่เข้ามา เช่น:

การรวม Asterisk และ Bitrix24

บันทึก URL เวอร์ชันของคุณโดยไม่มี /profile/ สุดท้าย - จะถูกใช้ในแอปพลิเคชันเพื่อทำงานกับสายเรียกเข้า

ฉันมีสิ่งนี้ https://b24-xsynia.bitrix24.ru/rest/1/7eh61lh8pahw0fwt/

เว็บฮุคขาออก

แอปพลิเคชัน -> Webhooks -> เพิ่ม webhook -> webhook ขาออก

รายละเอียดอยู่ในภาพหน้าจออีกครั้ง:

การรวม Asterisk และ Bitrix24

การรวม Asterisk และ Bitrix24

บันทึกและรับรหัสอนุญาต

การรวม Asterisk และ Bitrix24

ฉันมีสิ่งนี้ xcrp2ylhzzd2v43cmfjqmkvrgrcbkni6. คุณต้องคัดลอกมันเพื่อตัวคุณเองด้วย คุณต้องใช้มันเพื่อโทรออก

ที่สำคัญ!

ต้องกำหนดค่าใบรับรอง SSL บนเซิร์ฟเวอร์ Bitrix24 (คุณสามารถใช้ Letsencrypt ได้) มิฉะนั้น Bitrix API จะไม่ทำงาน หากคุณมีเวอร์ชันคลาวด์ ไม่ต้องกังวล เพราะมันมี ssl อยู่แล้ว

ที่สำคัญ!

ช่อง "ที่อยู่โปรเซสเซอร์" จะต้องมีที่อยู่ที่สามารถเข้าถึงได้จากอินเทอร์เน็ต!

สุดท้ายนี้ มาติดตั้ง 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

ถัดไป มีเคล็ดลับหลายประการที่จะต้องดำเนินการผ่าน 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});
}

};

เริ่มจากจุดเริ่มต้น: คำสั่ง Globals.

ตัวแปร URLบันทึก เก็บ URL ไปยังไฟล์บันทึกการสนทนา ตามที่ Bitrix24 จะดึงลงในบัตรข้อมูลที่ติดต่อ

ต่อไปเราสนใจมาโครมาโคร การบันทึก.

ที่นี่ นอกเหนือจากการบันทึกการสนทนาแล้ว เรายังตั้งค่าตัวแปรด้วย ชื่อเต็ม.

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 สำหรับส่วนขยายนี้ (ไม่จำเป็น), กำหนดเวลาสิ้นสุดของการโทร, คำนวณระยะเวลาหากไม่ทราบผลลัพธ์ของการโทร - ตั้งค่า (ตัวแปร โทรหาฉันDISPOSITION) และขั้นตอนสุดท้าย ส่งทุกอย่างไปที่ Bitrix ผ่านทาง system 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());

เธอบอกให้ PBX ติดตั้ง หมายเลขผู้โทร(ชื่อ) เท่ากับตัวแปร CallMeCallerIDชื่อ.

ตัวแปร CallMeCallerIDName เองก็ถูกตั้งค่าโดยแอปพลิเคชัน CallMe (หาก Bitrix24 มีชื่อเต็มสำหรับหมายเลขผู้โทร ให้ตั้งเป็น หมายเลขผู้โทร(ชื่อ)ไม่ - เราจะไม่ทำอะไรเลย)

การตั้งค่าแอปพลิเคชัน

ไฟล์การตั้งค่าแอปพลิเคชัน - /var/www/pbx.vistep.ru/config.php

คำอธิบายของพารามิเตอร์การใช้งาน:

  • CallMeDEBUG — ถ้าเป็น 1 กิจกรรมทั้งหมดที่แอปพลิเคชันประมวลผลจะถูกเขียนลงในไฟล์บันทึก 0 — เราไม่ได้เขียนอะไรเลย
  • เทคโนโลยี - SIP/PJSIP/IAX/ฯลฯ
  • โทเค็นการรับรองความถูกต้อง — โทเค็นการอนุญาต Bitrix24, รหัสการอนุญาต webhook ขาออก
  • bitrixApiUrl — URL ของ webhook ที่เข้ามา โดยไม่มีโปรไฟล์/
  • ส่วนขยาย – รายการหมายเลขภายนอก
  • สิ่งแวดล้อม — บริบทสำหรับการโทรออก
  • Listener_หมดเวลา — ความเร็วของการประมวลผลเหตุการณ์จากเครื่องหมายดอกจัน
  • ดอกจัน — อาร์เรย์พร้อมการตั้งค่าสำหรับเชื่อมต่อกับเครื่องหมายดอกจัน:
  • เจ้าภาพ — ip หรือชื่อโฮสต์ของเซิร์ฟเวอร์เครื่องหมายดอกจัน
  • โครงการ — แผนภาพการเชื่อมต่อ (tcp://, tls://)
  • พอร์ต - ท่าเรือ
  • ชื่อผู้ใช้ - ชื่อผู้ใช้
  • ลับ - รหัสผ่าน
  • เชื่อมต่อ_หมดเวลา - หมดเวลาการเชื่อมต่อ
  • 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

);

การตั้งค่าหัวหน้างาน

หัวหน้างานใช้เพื่อเรียกใช้กระบวนการจัดการเหตุการณ์จาก 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.

คำถามข้อเสนอแนะ - โปรดทิ้งไว้ในความคิดเห็น นอกจากนี้ หากคุณสนใจว่าการพัฒนาการบูรณาการนี้ดำเนินไปอย่างไร ให้เขียนและในบทความถัดไป ฉันจะพยายามเปิดเผยทุกอย่างโดยละเอียดยิ่งขึ้น

ที่มา: will.com

เพิ่มความคิดเห็น