Integration von Asterisk und Bitrix24

Integration von Asterisk und Bitrix24
Es gibt verschiedene Möglichkeiten, IP-PBX Asterisk und CRM Bitrix24 in das Netzwerk zu integrieren, aber wir haben uns dennoch entschieden, unsere eigenen zu schreiben.

Von der Funktionalität her ist alles Standard:

  • Durch Klicken auf einen Link mit der Telefonnummer eines Kunden in Bitrix24 verbindet Asterisk die interne Nummer des Benutzers, in dessen Namen der Klick erfolgt ist, mit der Telefonnummer des Kunden. In Bitrix24 wird eine Aufzeichnung des Anrufs aufgezeichnet und am Ende des Anrufs eine Aufzeichnung des Gesprächs abgerufen.
  • Asterisk erhält einen Anruf von außerhalb – in der Bitrix24-Schnittstelle zeigen wir die Kundenkarte dem Mitarbeiter, an dessen Nummer dieser Anruf angekommen ist.
    Wenn es keinen solchen Kunden gibt, öffnen wir die Karte zum Erstellen eines neuen Leads.
    Sobald das Gespräch beendet ist, vermerken wir dies auf der Karte und rufen eine Gesprächsaufzeichnung auf.

Unterhalb des Ausschnitts erkläre ich Ihnen, wie Sie alles selbst einrichten und gebe Ihnen einen Link zu Github – ja, ja, nehmen Sie es und verwenden Sie es!

Allgemeine Beschreibung

Wir haben unsere Integration CallMe genannt. CallMe ist eine kleine in PHP geschriebene Webanwendung.

Verwendete Technologien und Dienste

  • PHP 5.6
  • PHP-AMI-Bibliothek
  • Komponieren
  • Nginx + PHP-FPM
  • Supervisor
  • AMI (Asterisk Manager Interface)
  • Bitrix-Webhooks (vereinfachte REST-API-Implementierung)

Voreinstellung

Auf einem Server mit Asterisk müssen Sie einen Webserver (bei uns ist es nginx+php-fpm), Supervisor und Git installieren.

Installationsbefehl (CentOS):

yum install nginx php-fpm supervisor git

Wir gehen in das für den Webserver zugängliche Verzeichnis, ziehen die Anwendung aus Git und legen die erforderlichen Rechte für den Ordner fest:


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

Als nächstes konfigurieren wir Nginx, in dem sich unsere Konfiguration befindet

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

Ich werde das Parsen der Konfiguration, Sicherheitsprobleme, den Erhalt eines Zertifikats und sogar die Auswahl eines Webservers außerhalb des Rahmens des Artikels lassen – darüber wurde viel geschrieben. Die Anwendung unterliegt keinen Einschränkungen, sie funktioniert sowohl über http als auch über https.

Wir verwenden https, verschlüsseln wir das Zertifikat.

Wenn Sie alles richtig gemacht haben, sollten Sie beim Klicken auf den Link so etwas sehen

Integration von Asterisk und Bitrix24

Bitrix24 einrichten

Lassen Sie uns zwei Webhooks erstellen.

Eingehender Webhook.

Folgen Sie unter dem Administratorkonto (mit der ID 1) dem Pfad: Anwendungen -> Webhooks -> Webhook hinzufügen -> Eingehender Webhook

Integration von Asterisk und Bitrix24

Geben Sie die Parameter des eingehenden Webhooks wie in den Screenshots ein:

Integration von Asterisk und Bitrix24

Integration von Asterisk und Bitrix24

Und klicken Sie auf Speichern.

Nach dem Speichern stellt Bitrix24 die URL des eingehenden Webhooks bereit, zum Beispiel:

Integration von Asterisk und Bitrix24

Speichern Sie Ihre Version der URL ohne das endgültige /profile/ – es wird in der Anwendung verwendet, um mit eingehenden Anrufen zu arbeiten.

ich habe das https://b24-xsynia.bitrix24.ru/rest/1/7eh61lh8pahw0fwt/

Ausgehender Webhook.

Anwendungen -> Webhooks -> Webhook hinzufügen -> Ausgehender Webhook

Details gibt es noch einmal auf den Screenshots:

Integration von Asterisk und Bitrix24

Integration von Asterisk und Bitrix24

Speichern Sie und erhalten Sie den Autorisierungscode

Integration von Asterisk und Bitrix24

ich habe das xcrp2ylhzzd2v43cmfjqmkvrgrcbkni6. Sie müssen es auch selbst kopieren; Sie benötigen es, um ausgehende Anrufe zu tätigen.

Wichtig!

Auf dem Bitrix24-Server muss ein SSL-Zertifikat konfiguriert sein (Sie könnenletsencrypt verwenden), sonst funktioniert die Bitrix-API nicht. Wenn Sie eine Cloud-Version haben, machen Sie sich keine Sorgen – sie verfügt bereits über SSL.

Wichtig!

Das Feld „Prozessoradresse“ muss eine aus dem Internet erreichbare Adresse enthalten!

Und als letzten Schliff installieren wir unser CallMeOut als Anwendung zum Tätigen von Anrufen (sodass, wenn Sie auf der Telefonanlage auf die Nummer klicken, der Befehl zum Einleiten des Anrufs wegfliegt).

Wählen Sie im Menü: Mehr -> Telefonie -> Mehr -> Einstellungen, stellen Sie unter „Standard-Rufnummer für ausgehende Anrufe“ ein. Anwendung: CallMeOut und klicken Sie auf „Speichern“.

Integration von Asterisk und Bitrix24

Asterisk einrichten

Für eine erfolgreiche Interaktion zwischen Asterisk und Bitrix24 müssen wir den AMI-Benutzer callme zur manager.conf hinzufügen:

[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

Als nächstes müssen einige Tricks über Dialplan implementiert werden (bei uns ist das extensions.ael).

Ich stelle die gesamte Datei zur Verfügung und gebe dann eine Erklärung:

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

};

Fangen wir von vorne an: der Direktive globals.

Variable URLRECORDS speichert die URL zu den Gesprächsaufzeichnungsdateien, anhand derer Bitrix24 diese in die Kontaktkarte zieht.

Als nächstes interessieren wir uns für das Makro-Makro Einspielung vor.

Hier werden wir zusätzlich zur Aufzeichnung von Gesprächen die Variable festlegen Vollständiger Fname.

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

Es speichert die vollständige URL zu einer bestimmten Datei (das Makro wird überall aufgerufen).

Lassen Sie uns den ausgehenden Anruf analysieren:

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

Nehmen wir an, wir rufen 89991234567 an, zunächst einmal kommen wir hierher:

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

diese. Das Konversationsaufzeichnungsmakro wird aufgerufen und die notwendigen Variablen werden gesetzt.

Weiter

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

Wir erfassen, wer den Anruf initiiert hat und erfassen die Startzeit des Anrufs.

Und nach seiner Fertigstellung in einem besonderen Kontext 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});
}

Deaktivieren Sie den Eintrag in die CDR-Tabelle für diese Nebenstelle (er wird dort nicht benötigt), legen Sie die Endzeit des Anrufs fest, berechnen Sie die Dauer, wenn das Ergebnis des Anrufs nicht bekannt ist - setzen Sie (Variable CallMeDisposition) und im letzten Schritt alles über den System-Curl an Bitrix senden.

Und noch ein bisschen mehr Magie – ein eingehender Anruf:

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

Hier interessiert uns nur eine Zeile.

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

Sie weist die Telefonanlage an, sie zu installieren AnruferID(Name) gleich variabel CallMeCallerIDName.

Die CallMeCallerIDName-Variable selbst wird wiederum von der CallMe-Anwendung festgelegt (wenn Bitrix24 einen vollständigen Namen für die Nummer des Anrufers hat, legen Sie ihn fest als). AnruferID(Name), nein - wir werden nichts tun).

Einrichten der Anwendung

Anwendungseinstellungsdatei – /var/www/pbx.vistep.ru/config.php

Beschreibung der Anwendungsparameter:

  • CallMeDEBUG — wenn 1, dann werden alle von der Anwendung verarbeiteten Ereignisse in die Protokolldatei geschrieben, 0 — wir schreiben nichts
  • Tech - SIP/PJSIP/IAX/etc
  • AuthToken — Bitrix24-Autorisierungstoken, ausgehender Webhook-Autorisierungscode
  • bitrixApiUrl — URL des eingehenden Webhooks, ohne Profil/
  • Erweiterungen — Liste externer Nummern
  • Kontext – Kontext für die Einleitung eines Anrufs
  • listener_timeout — Geschwindigkeit der Ereignisverarbeitung von Asterisk
  • Sternchen — ein Array mit Einstellungen für die Verbindung zum Sternchen:
  • Gastgeber — IP oder Hostname des Asterisk-Servers
  • Schema — Verbindungsdiagramm (tcp://, tls://)
  • port - Hafen
  • Benutzername - Benutzername
  • secret - Passwort
  • Verbindungs ​​Timeout - Verbindungszeitüberschreitung
  • read_timeout - Timeout lesen

Beispiel-Einstellungsdatei:

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

Supervisor wird verwendet, um den Event-Handler-Prozess von Asterisk CallMeIn.php zu starten, der eingehende Anrufe überwacht und mit Bitrix24 interagiert (Karte anzeigen, Karte ausblenden usw.).

Zu erstellende Einstellungsdatei:

/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

Starten Sie die Anwendung und starten Sie sie neu:

supervisorctl start callme
supervisorctl restart callme

Anzeigen des Betriebsstatus der Anwendung:

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

Abschluss

Es stellte sich als ziemlich kompliziert heraus, aber ich bin sicher, dass ein erfahrener Administrator es implementieren und seinen Benutzern gefallen wird.

Wie versprochen, Link zu Github.

Fragen, Anregungen – hinterlassen Sie diese bitte in den Kommentaren. Wenn Sie auch daran interessiert sind, wie die Entwicklung dieser Integration verlaufen ist, schreiben Sie, und im nächsten Artikel werde ich versuchen, alles detaillierter zu enthüllen.

Source: habr.com

Kommentar hinzufügen