تكامل النجمة و Bitrix24

تكامل النجمة و Bitrix24
تحتوي الشبكة على خيارات مختلفة لدمج IP-PBX Asterisk و Bitrix24 CRM ، لكننا مع ذلك قررنا كتابة خياراتنا الخاصة.

وظيفيًا ، كل شيء قياسي:

  • من خلال النقر على الرابط مع رقم هاتف العميل في Bitrix24 ، تقوم Asterisk بربط الرقم الداخلي للمستخدم الذي تم إجراء هذه النقرة نيابة عنه مع رقم هاتف العميل. في Bitrix24 ، يتم تسجيل سجل المكالمة ، وفي نهاية المكالمة ، يتم سحب سجل المحادثة.
  • تصل مكالمة إلى Asterisk من الخارج - في واجهة Bitrix24 ، نعرض بطاقة العميل للموظف الذي وصلت هذه المكالمة إلى رقمه.
    إذا لم يكن هناك عميل كهذا ، فافتح البطاقة لإنشاء عميل متوقع جديد.
    بمجرد اكتمال المكالمة ، نعكس ذلك في البطاقة ونقوم بسحب تسجيل المحادثة.

تحت الخفض ، سأخبرك بكيفية إعداد كل شيء لنفسك وإعطاء رابط إلى جيثب - نعم ، نعم ، خذها واستخدمها!

وصف عام

أطلقنا على تكاملنا CallMe. CallMe هو تطبيق ويب صغير مكتوب بلغة PHP.

التقنيات والخدمات المستخدمة

  • PHP 5.6
  • مكتبة 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 ، فلنقم بتشفير الشهادة.

إذا فعلت كل شيء بشكل صحيح ، فعند النقر على الرابط ، سترى شيئًا كهذا

تكامل النجمة و Bitrix24

إعداد Bitrix24

لنقم بإنشاء خطافين للويب.

خطاف الويب الوارد.

ضمن حساب المسؤول (مع المعرف 1) ، انتقل على طول المسار: التطبيقات -> الخطافات على الويب -> إضافة الرد التلقائي على الويب -> الرد التلقائي على الويب

تكامل النجمة و Bitrix24

املأ معلمات خطاف الويب الوارد كما في لقطات الشاشة:

تكامل النجمة و Bitrix24

تكامل النجمة و Bitrix24

وانقر فوق حفظ.

بعد الحفظ ، سيوفر Bitrix24 عنوان URL لخطاف الويب الوارد ، على سبيل المثال:

تكامل النجمة و Bitrix24

احفظ نسختك من عنوان URL بدون اللاحقة / الملف الشخصي / - سيتم استخدامها في التطبيق للعمل مع المكالمات الواردة.

انا أملكه https://b24-xsynia.bitrix24.ru/rest/1/7eh61lh8pahw0fwt/

الرد التلقائي على الويب الصادر.

التطبيقات -> Webhooks -> إضافة Webhook -> Webhook الصادر

التفاصيل في لقطات الشاشة:

تكامل النجمة و Bitrix24

تكامل النجمة و Bitrix24

احفظ واحصل على رمز التفويض

تكامل النجمة و Bitrix24

انا أملكه xcrp2ylhzzd2v43cmfjqmkvrgrcbkni6. تحتاج أيضًا إلى نسخه إلى نفسك ، فهو ضروري لإجراء مكالمات صادرة.

المهم!

يجب تكوين شهادة SSL على خادم Bitrix24 (يمكنك استخدام Letsencrypt) ، وإلا فلن تعمل BitrixXNUMX api. إذا كان لديك إصدار سحابي ، فلا تقلق - SSL موجود بالفعل.

المهم!

في حقل "عنوان المعالج" ، يجب الإشارة إلى عنوان يمكن الوصول إليه من الإنترنت!

ومع اللمسة الأخيرة ، دعنا نثبِّت CallMeOut كتطبيق لإجراء المكالمات (بحيث أنه من خلال النقر على الرقم الموجود في PBX ، سينطلق الأمر لبدء المكالمة).

في القائمة ، حدد: المزيد -> الاتصالات الهاتفية -> المزيد -> الإعدادات ، أدخل "رقم المكالمات الصادرة افتراضيًا" التطبيق: CallMeOut وانقر على "حفظ"

تكامل النجمة و 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 (لدينا الامتدادات 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 يخزن عنوان 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 من خلال تجعيد النظام.

والمزيد من السحر - مكالمة واردة:

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 CallerID (الاسم) عامل CallMeCallerIDName.

يتم تعيين متغير CallMeCallerIDName نفسه ، بدوره ، بواسطة تطبيق CallMe (إذا كان لدى Bitrix24 اسمًا كاملاً لرقم المتصل ، فسنقوم بتعيينه على أنه CallerID (الاسم)، لا - لن نفعل أي شيء).

إعداد التطبيق

ملف إعدادات التطبيق - /var/www/pbx.vistep.ru/config.php

وصف معلمات التطبيق:

  • اتصل - إذا كان 1 ، فستتم كتابة جميع الأحداث التي تتم معالجتها بواسطة التطبيق في ملف السجل ، 0 - لا نكتب أي شيء
  • التكنولوجيا SIP / PJSIP / IAX / إلخ
  • AuthorToken - رمز ترخيص Bitrix24 ، رمز تفويض خطاف الويب الصادر
  • bitrixApiUrl - عنوان URL لخطاف الويب الوارد ، بدون ملف تعريف /
  • امتدادات - قائمة الأرقام الخارجية
  • سياق الكلام - سياق إنشاء المكالمة
  • listener_timeout - سرعة معالجة الحدث من علامة النجمة
  • النجمة - مصفوفة مع إعدادات الاتصال بعلامة النجمة:
  • مضيف - 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

);

إعداد المشرف

يتم استخدام المشرف لبدء عملية معالج الحدث من 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

اختتام

لقد اتضح أن الأمر صعب للغاية ، لكنني متأكد من أن المشرف المتمرس سيكون قادرًا على التنفيذ وإرضاء مستخدميه.

كما وعدت، ارتباط إلى جيثب.

أسئلة ، اقتراحات - من فضلك في التعليقات. أيضًا ، إذا كنت مهتمًا بكيفية تطور هذا التكامل ، فاكتب ، وسأحاول في المقالة التالية الكشف عن كل شيء بمزيد من التفصيل.

المصدر: www.habr.com

إضافة تعليق