
Es gibt verschiedene Integrationsmöglichkeiten der IP-TK-Anlage Asterisk und des CRM Bitrix24, aber wir haben uns entschieden, unsere eigene Lösung zu entwickeln.
Der Funktionsumfang ist standardmĂ€Ăig:
- Durch einen Klick auf den Link mit der Kundentelefonnummer in Bitrix24 verbindet Asterisk die interne Durchwahl des Benutzers, der diesen Link angeklickt hat, mit der Telefonnummer des Kunden. In Bitrix24 wird der Anruf protokolliert und am Ende des GesprÀchs wird die Aufnahme des GesprÀchs bereitgestellt.
- Wenn ein Anruf von auĂen auf Asterisk eingeht, wird die Kundenkarte im Bitrix24-Interface dem Mitarbeiter angezeigt, auf dessen Nummer dieser Anruf eingegangen ist.
Wenn kein solcher Kunde vorhanden ist, wird die Karte fĂŒr die Erstellung eines neuen Leads geöffnet.
Sobald der Anruf beendet ist, werden wir dies in der Karte vermerken und die GesprÀchsaufnahme bereitstellen.
Im Folgenden erklĂ€re ich, wie du alles bei dir einrichtest und gebe dir den Link zu GitHub â ja, ja, nimm ihn und nutze ihn!
Allgemeine Beschreibung
Unsere Integration haben wir CallMe genannt. CallMe ist eine kleine Webanwendung, die in PHP geschrieben wurde.
Verwendete Technologien und Dienste
- PHP 5.6
- Composer
- Nginx + php-fpm
- Supervisor
- AMI (Asterisk Manager Interface)
- Bitrix Webhooks (vereinfachte Implementierung der REST API)
Alles, was Sie brauchen, ist ein Kubernetes-Cluster und ein konfiguriertes Tool
Auf dem Server mit Asterisk muss ein Webserver installiert werden (bei uns ist das nginx+php-fpm), Supervisor und Git.
Befehl zur Installation (CentOS):
yum install nginx php-fpm supervisor gitWechseln Sie in das Verzeichnis, das fĂŒr den Webserver zugĂ€nglich ist, ziehen Sie die Anwendung aus Git und setzen Sie die erforderlichen Berechtigungen fĂŒr den Ordner:
cd /var/www
git clone https://github.com/ViStepRU/callme.git
chown nginx. -R callme/
Dann konfigurieren wir nginx, unsere Konfiguration befindet sich in
/etc/nginx/conf.d/pbx.vistep.ru.confserver {
server_name www.pbx.vistep.de pbx.vistep.de;
listen *:80;
rewrite ^ https://pbx.vistep.de$request_uri? permanent;
}
server {
# listen *:80;
# server_name pbx.vistep.de;
access_log /var/log/nginx/pbx.vistep.de.access.log main;
error_log /var/log/nginx/pbx.vistep.de.error.log;
listen 443 ssl http2;
server_name pbx.vistep.de;
resolver 8.8.8.8;
ssl_stapling on;
ssl on;
ssl_certificate /etc/letsencrypt/live/pbx.vistep.de/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/pbx.vistep.de/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; # Verbot fĂŒr versteckte Dateien
}
location ~* /(?:uploads|files)/.*.php$ {
deny all; # Verbot fĂŒr hochgeladene Skripte
}
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; # Caching von Statischen Dateien
}
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;
}
}
Die Konfiguration, Sicherheitsfragen, das Erhalten eines Zertifikats und sogar die Auswahl des Webservers werde ich auĂen vor lassen â darĂŒber gibt es bereits viele Informationen. Die Anwendung hat keine EinschrĂ€nkungen, sie funktioniert sowohl ĂŒber HTTP als auch ĂŒber HTTPS.
Bei uns ist HTTPS aktiv, mit einem Let's Encrypt-Zertifikat.
Wenn alles richtig gemacht wurde, sollten Sie beim Klicken auf den Link etwas Ăhnliches sehen.

Einrichtung von Bitrix24
Wir erstellen zwei Webhooks.
Eingehender Webhook.
Unter dem Administrator-Konto (mit der ID 1) navigieren wir zu: Apps -> Webhooks -> Webhook hinzufĂŒgen -> Eingehender Webhook

FĂŒllen Sie die Parameter des eingehenden Webhooks wie in den Screenshots aus:


Und klicken Sie auf Speichern.
Nach dem Speichern stellt Bitrix24 die URL des eingehenden Webhooks zur VerfĂŒgung, zum Beispiel:

Speichern Sie Ihre URL-Version ohne das abschlieĂende /profile/ â sie wird in der Anwendung fĂŒr eingehende Anrufe verwendet.
Bei mir ist es https://b24-xsynia.bitrix24.ru/rest/1/7eh61lh8pahw0fwt/
Ausgehender Webhook.
Apps -> Webhooks -> Webhook hinzufĂŒgen -> Ausgehender Webhook
Details wieder in den Screenshots:


Speichern und den Autorisierungscode erhalten

Bei mir ist es xcrp2ylhzzd2v43cmfjqmkvrgrcbkni6. Diesen mĂŒssen Sie ebenfalls kopieren, da er fĂŒr ausgehende Anrufe benötigt wird.
Wichtig!
Auf dem Bitrix24-Server muss ein SSL-Zertifikat eingerichtet werden (Let's Encrypt kann verwendet werden), da sonst die API von Bitrix nicht funktioniert. Wenn Sie die Cloud-Version verwenden, mĂŒssen Sie sich keine Sorgen machen â dort ist bereits SSL vorhanden.
Wichtig!
Im Feld âHandler-Adresseâ muss eine ĂŒber das Internet zugĂ€ngliche Adresse angegeben werden!
Und als letzten Schritt fĂŒgen wir unsere CallMeOut-App fĂŒr Anrufe hinzu (damit beim Klicken auf die Nummer im PBX ein Befehl zur Anrufinitiierung gesendet wird).
Im MenĂŒ wĂ€hlen wir: Mehr -> Telefonie -> Mehr -> Einstellungen, setzen in âNummer fĂŒr ausgehende Anrufe (standardmĂ€Ăig)â die Anwendung: CallMeOut und klicken auf âSpeichernâ.

Asterisk-Konfiguration
FĂŒr eine erfolgreiche Interaktion zwischen Asterisk und Bitrix24 mĂŒssen wir den AMI-Benutzer callme in 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
Danach gibt es einige Tricks, die wir ĂŒber den Dialplan einfĂŒgen mĂŒssen (bei uns ist das extensions.ael).
Hier ist die gesamte Datei, und danach gebe ich ErklÀrungen:
globals {
WAV=\/var\/www\/pbx.vistep.de\/callme\/records\/wav; \/\/ TemporĂ€rer Katalog fĂŒr WAV
MP3=\/var\/www\/pbx.vistep.de\/callme\/records\/mp3; \/\/ Speicherort fĂŒr MP3-Dateien
URLRECORDS=https:\/\/pbx.vistep.de\/callme\/records\/mp3;
RECORDING=1; \/\/ Aufnahme, 1 - aktiviert.
};
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()); \/\/ Setzen der CallerID, falls bekannt aus Bitrix24
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 war bereits gesetzt ===));
}
}
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.de\/CallMeOut.php --data action=sendcall2b24 --data call_id=${CallMeCALL_ID} --data-urlencode FullFname=${FullFname} --data CallIntNum=${CallIntNum} --data CallDuration=${CallMeDURATION} --data-urlencode CallDisposition=${CallMeDISPOSITION});
}
};
Lassen Sie uns von Grund auf neu beginnen: die Direktive globals.
Die Variable URLRECORDS speichert die URL zu den GesprÀchsaufzeichnungsdateien, die Bitrix24 zur Anzeige im Kontaktkarte verwendet.
Als NĂ€chstes interessiert uns das Makro recording.
Hier werden wir neben der GesprÀchsaufzeichnung auch die Variable FullFname.
Set(FullFname=${URLRECORDS}/${datedir}/${fname}.mp3);speichern, die die vollstĂ€ndige URL zur spezifischen Datei enthĂ€lt (das Makro wird ĂŒberall aufgerufen).
Untersuchen wir den Ausgangs-Anruf:
_. => {
&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});
}
Angenommen, wir rufen die 89991234567 an, gelangen wir zuerst hierher:
&recording(${CALLERID(number)},${EXTEN});d.h. das Makro zur GesprÀchsaufzeichnung wird aufgerufen und die erforderlichen Variablen gesetzt.
Weiter
Set(__CallIntNum=${CALLERID(num)})
Set(CallStart=${STRFTIME(epoch,,%s)});
wir zeichnen auf, wer den Anruf initiiert hat und protokollieren die Startzeit des Anrufs.
Und nach dessen Abschluss, im speziellen 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});
}
wir deaktivieren die Aufzeichnung in der CDR-Tabelle fĂŒr diese Durchwahl (es ist dort nicht notwendig), setzen die Endzeit des Anrufs, berechnen die Dauer, falls das Ergebnis des Anrufs unbekannt ist - setzen wir (Variable CallMeDISPOSITION) und als letzter Schritt senden wir alles an Bitrix durch den Systemcurl.
Und noch ein wenig Magie - eingehender Anruf:
888999 => {
&recording(${CALLERID(number)},${EXTEN});
Answer();
ExecIF(${CallMeCallerIDName}?Set(CALLERID(name)=${CallMeCallerIDName}):NoOp()); // setzen CallerID, wenn wir ihn bei Bitrix24 erfahren haben
Set(CallStart=${STRFTIME(epoch,,%s)}); // Beginn der Zeitmessung des Anrufs
Queue(Q1,tT);
Set(CallMeDISPOSITION=${CDR(disposition)});
Hangup();
}
Hier interessiert uns nur eine Zeile.
ExecIF(${CallMeCallerIDName}?Set(CALLERID(name)=${CallMeCallerIDName}):NoOp());Sie sagt der TK-Anlage, dass sie CallerID(name) gleich der Variable CallMeCallerIDName.
Die Variable CallMeCallerIDName wird von der Anwendung CallMe festgelegt (wenn in Bitrix24 der Name des Anrufers vorhanden ist â setzen wir ihn als. CallerID(name), wenn nicht â tun wir nichts).
Anwendungseinstellungen
Die Einstellungsdatei der Anwendung â /var/www/pbx.vistep.ru/config.php
Beschreibung der Anwendungsparameter:
- CallMeDEBUG â Wenn 1, werden alle Ereignisse, die von der Anwendung verarbeitet werden, in die Protokolldatei geschrieben, 0 â es wird nichts geschrieben.
- tech â SIP/PJSIP/IAX/etc.
- authToken â Authentifizierungstoken fĂŒr Bitrix24, Authentifizierungscode fĂŒr den ausgehenden Webhook.
- bitrixApiUrl â URL fĂŒr den eingehenden Webhook, ohne profile/
- extentions â Liste der externen Rufnummern
- context â Kontext fĂŒr die Initiierung des Anrufs.
- listener_timeout â Verarbeitungsgeschwindigkeit der Ereignisse von Asterisk.
- asterisk â Array mit den Verbindungseinstellungen zu Asterisk:
- host â IP oder Hostname des Asterisk-Servers.
- scheme â Verbindungsart (tcp://, tls://)
- port â Port.
- Benutzername â Benutzername.
- secret â Passwort.
- connect_timeout â VerbindungszeitĂŒberschreitung.
- read_timeout â LesezeitĂŒberschreitung.
Beispiel fĂŒr eine Einstellungsdatei:
1, // Debug-Nachrichten im Log: 1 - schreiben, 0 - nicht schreiben
'tech' => 'SIP',
'authToken' => 'xcrp2ylhzzd2v43cmfjqmkvrgrcbkni6', // Authentifizierungstoken fĂŒr Bitrix
'bitrixApiUrl' => 'https://b24-xsynia.bitrix24.de/rest/1/7eh61lh8pahw0fwt/', // URL zur Bitrix API (eingehender Webhook)
'extentions' => array('888999'), // Liste externer Nummern, durch Kommas getrennt
'context' => 'dial_out', // Ausgangskontext fĂŒr den Anruf
'asterisk' => array( // Einstellungen fĂŒr die Verbindung zu Asterisk
'host' => '10.100.111.249',
'scheme' => 'tcp://',
'port' => 5038,
'username' => 'callme',
'secret' => 'JD3clEB8_f23r-3ry84gJ',
'connect_timeout' => 10000,
'read_timeout' => 10000
),
'listener_timeout' => 300, // Verarbeitungsrate von Ereignissen von Asterisk
);Konfiguration des Supervisors
Der Supervisor dient zum Starten des Ereignisverarbeitungsprozesses von Asterisk CallMeIn.php, der eingehende Anrufe verfolgt und mit Bitrix24 interagiert (Karte anzeigen, Karte ausblenden usw.).
Die zu erstellende Konfigurationsdatei:
/etc/supervisord.d/callme.conf
[program:callme]
command=/usr/bin/php CallMeIn.php
directory=/var/www/pbx.vistep.de
autostart=true
autorestart=true
startretries=5
stderr_logfile=/var/www/pbx.vistep.de/logs/daemon.log
stdout_logfile=/var/www/pbx.vistep.de/logs/daemon.logStarten und Neustarten der Anwendung:
supervisorctl start callme
supervisorctl restart callmeStatus des Anwendungsbetriebs ansehen:
supervisorctl status callme
callme LĂUFT pid 11729, Uptime 17 Tage, 16:58:07Fazit
Es ist ziemlich kompliziert geworden, aber ich bin ĂŒberzeugt â ein erfahrener Administrator wird es implementieren und seine Benutzer erfreuen.
Wie versprochen, .
Fragen oder WĂŒnsche â bitte in die Kommentare. Wenn Sie auch interessiert sind, wie die Entwicklung dieser Integration verlief, schreiben Sie mir, und ich werde in einem der nĂ€chsten Artikel alles detaillierter erlĂ€utern.
Quelle: habr.com
