Wir beschäftigen uns mit FreePBX und integrieren es mit Bitrix24 und nicht nur damit.

Bitrix24 ist eine riesige Kombination, die sowohl CRM, Dokumentenmanagement, Buchhaltung und viele andere Dinge vereint, die den Managern sehr gefallen und dem IT-Personal weniger. Das Portal wird von vielen kleinen und mittleren Unternehmen genutzt, einschließlich kleiner Kliniken, Herstellern und sogar Schönheitssalons. Die Hauptfunktion, die die Manager "lieben", ist die Integration von Telefonie und CRM, wobei jeder Anruf sofort im CRM erfasst wird, Kundenkarten erstellt werden, bei eingehenden Anrufen Informationen über den Kunden angezeigt werden und man sofort sieht, wer er ist, was man ihm verkaufen kann und wie viel er schuldet. Aber die Telefonie von Bitrix24 und ihre Integration mit CRM kostet Geld, manchmal nicht wenig. In diesem Artikel werde ich die Erfahrungen mit der Integration von Open-Source-Tools und einer beliebten IP-ATC teilen. FreePBX, und ich werde die Logik der Funktionsweise verschiedener Teile beleuchten.

Ich arbeite im Outsourcing für ein Unternehmen, das den Verkauf und die Einrichtung sowie die Integration von IP-Telefonie anbietet. Als ich gefragt wurde, ob wir diesem und jenem Unternehmen etwas zur Integration von Bitrix24 mit den ATCs, die bei den Kunden eingesetzt werden, sowie mit virtuellen ATCs von verschiedenen VDS-Anbietern anbieten können, ging ich zu Google. Und natürlich gab er mir den Link zu einem Artikel auf Habr, wo sowohl eine Beschreibung als auch ein GitHub vorhanden sind, und anscheinend funktioniert alles. Aber beim Versuch, diese Lösung zu nutzen, stellte sich heraus, dass Bitrix24 nicht mehr das ist, was es früher war, und vieles umgebaut werden muss. Außerdem ist FreePBX nicht einfach nur ein nackter Asterisk; man muss sich Gedanken darüber machen, wie man Benutzerfreundlichkeit und einen harten Dialplan in Konfigurationsdateien vereinbaren kann.

Untersuchung der Arbeitslogik

Also, zunächst, wie sollte das alles funktionieren. Bei einem externen Anruf auf die ATC (Ereignis SIP INVITE vom Anbieter) beginnt die Bearbeitung des Dialplans (Dialplan) – Regeln, was und in welcher Reihenfolge mit dem Anruf zu tun ist. Aus dem ersten Paket kann man viele Informationen gewinnen, die dann in den Regeln verwendet werden können. Ein hervorragendes Werkzeug zum Studium der Inneren von SIP ist der Analyzer sngrep (Link, der einfach in gängigen Distributionen über apt install/yum install und ähnliches installiert werden kann, aber man kann ihn auch aus dem Quellcode erstellen. Lassen Sie uns das Anrufprotokoll in sngrep ansehen.

Wir beschäftigen uns mit FreePBX und integrieren es mit Bitrix24 und nicht nur damit.

In vereinfachter Form befasst sich der Dialplan nur mit dem ersten Paket, gelegentlich erfolgt während des Gesprächs auch die Umstellung von Anrufen, das Drücken von Tasten (DTMF), verschiedene interessante Funktionen wie FollowMe, RingGroup, IVR und andere.

Was sich im Invite-Paket befindet

Wir beschäftigen uns mit FreePBX und integrieren es mit Bitrix24 und nicht nur damit.

Die meisten einfachen Dialpläne arbeiten tatsächlich mit den ersten beiden Feldern, und die gesamte Logik dreht sich um DID und CallerID. DID — wohin wir anrufen, CallerID — wer anruft.

Aber wir sind ein Unternehmen und nicht nur ein Telefon — und das bedeutet, dass die Telefonanlage wahrscheinlich Anrufgruppen (gleichzeitiger/sequenzieller Anruf mehrerer Geräte) bei den Ortsrufnummern (Ring Group), IVR (Hallo, Sie haben ... angerufen. Drücken Sie eins für ...) , Sprachboxen (Phrases), zeitliche Bedingungen (Time Conditions), Weiterleitung an andere Nummern oder auf Mobiltelefone (FollowMe, Forward) hat. Das bedeutet, es ist sehr schwierig, eindeutig zu bestimmen, an wen der Anruf tatsächlich geht und mit wem das Gespräch beim Eintreffen des Anrufs stattfinden wird. Hier ist ein Beispiel für den Beginn eines typischen Anrufs in der Telefonanlage unserer Kunden.

Wir beschäftigen uns mit FreePBX und integrieren es mit Bitrix24 und nicht nur damit.

Nach erfolgreichem Eintreffen des Anrufs in der Telefonanlage erfolgt seine Reise durch den Dialplan in verschiedenen „Kontexten“. Ein Kontext aus der Sicht von Asterisk ist eine nummerierte Reihe von Befehlen, von denen jeder einen Filter für die gewählte Nummer enthält (dies wird exten genannt, für einen externen Anruf in der Anfangsphase exten=DID). Die Befehle im Dialplan können alles Mögliche sein – interne Funktionen (zum Beispiel einen internen Teilnehmer anrufen — Dial(), das Gespräch beenden — Hangup()), bedingte Operatoren (IF, ELSE, ExecIF und ähnliche), Sprünge zu anderen Regeln dieses Kontextes (Goto, GotoIF), Sprünge zu anderen Kontexten in Form von Funktionsaufrufen (Gosub, Macro). Besonderes Augenmerk verdient die Direktive include kontext_name, , die Befehle eines anderen Kontexts am Ende des aktuellen Kontexts hinzufügt. Befehle, die über include eingebunden werden, werden stets ausgeführt nach den Befehlen des aktuellen Kontextes.

Die gesamte Logik der Funktionsweise von FreePBX basiert auf dem Einschluss unterschiedlicher Kontexte durch include und Aufrufen über Gosub, Macro und Handler-Verarbeitung. Betrachten wir den Kontext der eingehenden Anrufe von FreePBX.

Wir beschäftigen uns mit FreePBX und integrieren es mit Bitrix24 und nicht nur damit.

Der Anruf passiert alle Kontexte von oben nach unten der Reihe nach; in jedem Kontext können andere Kontexte in Form von Makros (Macro), Funktionen (Gosub) oder einfachen Sprüngen (Goto) aufgerufen werden, weshalb der tatsächliche Baum dessen, was aufgerufen wird, nur in den Protokollen nachverfolgt werden kann.

Das typische Schema zur Einrichtung einer typischen Bürotelefonanlage ist unten dargestellt. Bei Anrufen wird im eingehenden Routing nach DID gesucht, zeitliche Bedingungen werden überprüft, und wenn alles in Ordnung ist, wird ein Sprachmenü gestartet. Darin gibt es die Möglichkeit, mit Taste 1 oder nach Zeitüberschreitung zu einer Gruppe von Operatoren durchzustellen. Nach dem Ende des Anrufs wird das Makro hangupcall aufgerufen, nach dem im Dialplan keine weiteren Aktionen durchgeführt werden können, außer durch spezielle Handler (hangup handler).

Wir beschäftigen uns mit FreePBX und integrieren es mit Bitrix24 und nicht nur damit.

An welcher Stelle in diesem Anrufalgorithmus müssen wir Informationen über den Beginn des Anrufs an das CRM übermitteln, wo mit der Aufnahme begonnen wird, wo die Aufnahme endet und wie sie zusammen mit den Anrufinformationen an das CRM gesendet wird?

Integration mit externen Systemen

Was ist die Integration von PBX und CRM? Das sind Einstellungen und Programme, die Daten und Ereignisse zwischen diesen beiden Plattformen konvertieren und austauschen. Die häufigste Art der Interaktion unabhängiger Systeme erfolgt über APIs, und der beliebteste Zugang zu APIs ist HTTP REST. Aber nicht für Asterisk.

Innerhalb von Asterisk gibt es:

  • AGI – synchroner Aufruf externer Programme/Komponenten, hauptsächlich im Dialplan verwendet, es gibt Bibliotheken wie phpagi, PAGI

  • AMI – textbasierter TCP-Socket, der nach dem Prinzip der Ereignisanmeldung und der Eingabe von Textbefehlen funktioniert, ähnlich wie SMTP im Inneren, kann Ereignisse verfolgen und Anrufe steuern, es gibt die Bibliothek PAMI – die beliebteste zur Herstellung einer Verbindung mit Asterisk

Beispielausgabe AMI

Event: Newchannel
Privileg: call,all
Channel: PJSIP/VMS_pjsip-0000078b
ChannelState: 4
ChannelStateDesc: Ring
CallerIDNum: 111222
CallerIDName: 111222
ConnectedLineNum:
ConnectedLineName:
Language: en
AccountCode:
Context: from-pstn
Exten: s
Priority: 1
Uniqueid: 1599589046.5244
Linkedid: 1599589046.5244

  • ARI – eine Mischung aus beidem, alles über REST, WebSocket, im JSON-Format – aber mit den neuen Bibliotheken und Wrappern nicht so gut, ich habe (phparia, phpari) gefunden, die sich vor etwa 3 Jahren in ihrer Entwicklung befanden.

Beispielausgabe ARI beim Initiieren eines Anrufs

{ "variable":"CallMeCallerIDName", "value":"111222", "type":"ChannelVarset", "timestamp":"2020-09-09T09:38:36.269+0000", "channel":{"id":"1599644315.5334", "name":"PJSIP/VMSpjsip-000007b6", "state":"Ring", "caller":{"name":"111222", "number":"111222"}, "connected":{"name":"", "number":""}, "accountcode":"", "dialplan":{"context":"from-pstn", "exten":"s", "priority":2, "appname":"Stasis", "appdata":"hello-world"}, "creationtime":"2020-09-09T09:38:35.926+0000", "language":"ru"}, "asteriskid":"48:5b:aa:aa:aa:aa", "application":"hello-world"}

Komfort oder Unbehagen, die Möglichkeit oder Unmöglichkeit, mit einem bestimmten API zu arbeiten, werden durch die Aufgaben bestimmt, die gelöst werden müssen. Die Aufgaben für die Integration mit CRM sind folgende:

  • Den Beginn des Anrufs nachverfolgen, wohin er weitergeleitet wurde, CallerID, DID, Anfangs- und Endzeit sowie möglicherweise Daten aus dem Verzeichnis extrahieren (um die Verbindung zwischen Telefon und CRM-Nutzer zu finden)

  • Einen Anruf starten und beenden, im gewünschten Format speichern und nach Abschluss des Aufrufs mitteilen, wo die Datei liegt

  • Einen Anruf durch ein externes Ereignis (aus einem Programm) initiieren, eine interne Nummer anrufen, eine externe Nummer anrufen und beide verbinden

  • Optional: mit CRM, Rückrufgruppen und FollowME integrieren, um Anrufe bei Abwesenheit automatisch umzuleiten (basierend auf Informationen aus dem CRM)

All diese Aufgaben können über AMI oder ARI gelöst werden, aber ARI bietet viel weniger Informationen, es gibt viele Ereignisse nicht, viele Variablen werden nicht verfolgt, die es bei AMI gibt (z.B. Makroaufrufe, Setzen von Variablen innerhalb von Makros, einschließlich der Aufzeichnung von Anrufen). Daher wählen wir vorerst AMI für eine korrekte und genaue Verfolgung (aber nicht endgültig). Außerdem (naja, wo wären wir ohne das, wir sind faul) – im ursprünglichen Projekt (Artikel auf Habr) benutzen PAMI. *Danach sollten wir versuchen, es auf ARI umzuschreiben, aber es ist nicht sicher, ob es klappt.

Wir erfinden die Integration neu

Damit unser FreePBX über einfache Methoden an AMI über den Beginn eines Anrufs, die Endzeit, Nummern und Namen der aufgezeichneten Dateien berichten kann, ist es am einfachsten, denselben Trick zu verwenden wie die ursprünglichen Autoren – unsere Variablen einzuführen und die Ausgabe auf deren Vorhandensein zu parsen. PAMI bietet dies einfach über eine Filterfunktion an.

Hier ein Beispiel für das Setzen einer eigenen Variable für den Beginn eines Anrufs (s ist eine spezielle Nummer im Dialplan, die VOR dem Beginn der DID-Suche ausgeführt wird)

[ext-did-custom]

exten => s,1,Set(CallStart=${STRFTIME(epoch,,%s)})

Beispiel für ein AMI-Ereignis aus dieser Zeile

Event: Newchannel

Privileg: call,all

Channel: PJSIP/VMS_pjsip-0000078b

ChannelState: 4

ChannelStateDesc: Ring

CallerIDNum: 111222

CallerIDName: 111222

ConnectedLineNum:

ConnectedLineName:

Language: en

AccountCode:

Context: from-pstn

Exten: s

Priority: 1

Uniqueid: 1599589046.5244

Linkedid: 1599589046.5244

Application: Set AppData:

CallStart=1599571046

Da FreePBX die Dateien extention.conf und extention_additional.conf neu schreibt, werden wir die Datei extention_custom.conf

Vollständiger Code von extention_custom.conf

[globals]	
;; Überprüfen Sie die Pfade und Berechtigungen der Ordner - der Benutzer asterisk muss Schreibrechte haben
;; Hier werden die Gespräche gespeichert
WAV=\/var\/www\/html\/callme\/records\/wav 
MP3=\/var\/www\/html\/callme\/records\/mp3

;; Über diese Pfade werden Aufzeichnungen abgespielt und heruntergeladen
URLRECORDS=https:\/\/www.host.ru\/callmeplus\/records\/mp3

;; Adresse für den Callback bei einem ausgehenden Anruf
URLPHP=https:\/\/www.host.ru\/callmeplus

;; Ja, wir zeichnen die Gespräche auf
RECORDING=1

;; Dies ist ein Makro zur Aufzeichnung von Gesprächen in unseren Ordner.
;; Man kann auch die Systemaufzeichnung verwenden, aber lassen wir vorerst diese - 
;; sie funktioniert
[recording]
exten => ~~s~~,1,Set(LOCAL(calling)=${ARG1})
exten => ~~s~~,2,Set(LOCAL(called)=${ARG2})
exten => ~~s~~,3,GotoIf($["${RECORDING}" = "1"]?4:14)
exten => ~~s~~,4,Set(fname=${UNIQUEID}-${STRFTIME(${EPOCH},,%Y-%m-%d-%H_%M)}-${calling}-${called})
exten => ~~s~~,5,Set(datedir=${STRFTIME(${EPOCH},,%Y\/%m\/%d)})
exten => ~~s~~,6,System(mkdir -p ${MP3}\/${datedir})
exten => ~~s~~,7,System(mkdir -p ${WAV}\/${datedir})
exten => ~~s~~,8,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")
exten => ~~s~~,9,Set(FullFname=${URLRECORDS}\/${datedir}\/${fname}.mp3)
exten => ~~s~~,10,Set(CDR(filename)=${fname}.mp3)
exten => ~~s~~,11,Set(CDR(recordingfile)=${fname}.wav)
exten => ~~s~~,12,Set(CDR(realdst)=${called})
exten => ~~s~~,13,MixMonitor(${WAV}\/${datedir}\/${fname}.wav,b,${monopt})
exten => ~~s~~,14,NoOp(Finish if_recording_1)
exten => ~~s~~,15,Return()


;; Dies ist der Hauptkontext für den Beginn des Gesprächs
[ext-did-custom]

;; Es ist unkonventionell, das hier so zu machen, aber es funktioniert - wir fügen eine '8' zur Nummer hinzu
exten =>  s,1,Set(CALLERID(num)=8${CALLERID(num)})

;; Hier sind verschiedene Variablen für das Skript
exten =>  s,n,Gosub(recording,~~s~~,1(${CALLERID(number)},${EXTEN}))
exten =>  s,n,ExecIF(${CallMeCallerIDName}?Set(CALLERID(name)=${CallMeCallerIDName}):NoOp())
exten =>  s,n,Set(CallStart=${STRFTIME(epoch,,%s)})
exten =>  s,n,Set(CallMeDISPOSITION=${CDR(disposition)})

;; Das Wichtigste! Der Handler für das Ende des Gesprächs. 
;; Die üblichen Wege zur Verarbeitung des Endes über (exten=>h,1,washiersteht) in FreePBX funktionieren nicht - Macro(hangupcall,) stört alles. 
;; Daher hängen wir den Hangup_Handler an das Ende des Anrufs
exten => s,n,Set(CHANNEL(hangup_handler_push)=sub-call-from-cid-ended,s,1(${CALLERID(num)},${EXTEN}))

;; Handler für das Ende eines eingehenden Anrufs
[sub-call-from-cid-ended]

;; Wir melden die Werte am Ende des Anrufs
exten => s,1,Set(CDR_PROP(disable)=true)
exten => s,n,Set(CallStop=${STRFTIME(epoch,,%s)})
exten => s,n,Set(CallMeDURATION=${MATH(${CallStop}-${CallStart},int)})

;; Status des Anrufs - Antwort, keine Antwort...
exten => s,n,Set(CallMeDISPOSITION=${CDR(disposition)})
exten => s,n,Return


;; Handler für ausgehende Anrufe - alles analog
[outbound-allroutes-custom]

;; Aufnahme
exten => _.,1,Gosub(recording,~~s~~,1(${CALLERID(number)},${EXTEN}))
;; Variablen
exten => _.,n,Set(__CallIntNum=${CALLERID(num)})
exten => _.,n,Set(CallExtNum=${EXTEN})
exten => _.,n,Set(CallStart=${STRFTIME(epoch,,%s)})
exten => _.,n,Set(CallmeCALLID=${SIPCALLID})

;; Wir hängen den Hangup_Handler an das Ende des Anrufs
exten => _.,n,Set(CHANNEL(hangup_handler_push)=sub-call-internal-ended,s,1(${CALLERID(num)},${EXTEN}))

;; Handler für das Ende eines ausgehenden Anrufs
[sub-call-internal-ended]

;; Variablen
exten => s,1,Set(CDR_PROP(disable)=true)
exten => s,n,Set(CallStop=${STRFTIME(epoch,,%s)})
exten => s,n,Set(CallMeDURATION=${MATH(${CallStop}-${CallStart},int)})
exten => s,n,Set(CallMeDISPOSITION=${CDR(disposition)})

;; Aufruf des Skripts, das den Anruf an das CRM meldet - dies ist ausgehend, 
;; also im Grunde am Ende
exten => s,n,System(curl -s ${URLPHP}\/CallMeOut.php --data action=sendcall2b24 --data ExtNum=${CallExtNum} --data call_id=${SIPCALLID} --data-urlencode FullFname='${FullFname}' --data CallIntNum=${CallIntNum} --data CallDuration=${CallMeDURATION} --data-urlencode CallDisposition='${CallMeDISPOSITION}')
exten => s,n,Return

Die Besonderheit und der Unterschied zum ursprünglichen Dialplan der Autoren des Ausgangsartikels sind

  • Dialplan im .conf-Format, da FreePBX dies verlangt (ja, es kann .ael, aber nicht alle Versionen und nicht immer ist das bequem)

  • Anstelle der Verarbeitung des Endes über exten=>h wurde die Verarbeitung über hangup_handler eingeführt, da der FreePBX-Dialplan nur mit ihm funktioniert hat

  • Die Zeile zum Aufrufen des Skripts wurde korrigiert, Anführungszeichen und eine externe Rufnummer ExtNum hinzugefügt

  • Die Verarbeitungen wurden in _custom-Kontexte ausgelagert, sodass die FreePBX-Konfigurationen nicht angefasst und nicht geändert werden müssen – eingehend über [ext-did-custom], ausgehend über [outbound-allroutes-custom]

  • Es gibt keine Bindung an Rufnummern – die Datei ist universell und benötigt nur die Anpassung des Pfades und den Verweis auf den Server

Um zu starten, müssen die Skripte in AMI mit Benutzernamen und Passwort freigegeben werden – dazu gibt es auch in FreePBX eine _custom-Datei

Datei manager_custom.conf

;;  das ist der Benutzername
[callmeplus]
;; das ist das Passwort
secret = trampampamturlala
deny = 0.0.0.0/0.0.0.0

;; ich arbeite mit einer lokalen Maschine - aber wenn nötig, können auch andere angegeben werden
permit = 127.0.0.1/255.255.255.255
read = system,call,log,verbose,agent,user,config,dtmf,reporting,cdr,dialplan
write = system,call,agent,log,verbose,user,config,command,reporting,originate

Diese beiden Dateien müssen in /etc/asterisk abgelegt werden, dann müssen die Konfigurationen neu gelesen werden (oder Asterisk neu gestartet werden)

# astrisk -rv
  Connected to Asterisk 16.6.2 currently running on freepbx (pid = 31629)
#freepbx*CLI> dialplan reload
     Dialplan reloaded.
#freepbx*CLI> exit

Jetzt kommen wir zu PHP

Initialisierung der Skripte und Erstellung des Dienstes

Da das Arbeiten mit Bitrix24, einem Dienst für AMI, nicht ganz einfach und klar ist, sollte hier separat darauf eingegangen werden. Asterisk öffnet beim Aktivieren von AMI einfach den Port und das war's. Bei der Verbindung eines Clients wird eine Autorisierung angefordert, danach abonniert der Client die benötigten Ereignisse. Die Ereignisse kommen als einfacher Text, den PAMI in strukturierte Objekte umwandelt und die Möglichkeit bietet, eine Filterfunktion nur für die interessierenden Ereignisse, Felder, Nummern usw. festzulegen.

Sobald der Anruf eingeht, tritt das Ereignis NewExten im übergeordneten Kontext [from-pstn] auf; anschließend folgen alle Ereignisse in der Reihenfolge der Zeilen in den Kontexten. Bei Erhalt von Informationen aus den im Dialplan definierten _custom-Variablen CallMeCallerIDName und CallStart wird aufgerufen.

  1. Die Funktion abfragen UserID, die der internen Nummer entspricht, an die der Anruf geleitet wurde. Und was ist, wenn es sich um eine Anrufgruppe handelt? Das ist eine politische Frage, sollte man alle gleichzeitig anrufen (wenn alle gleichzeitig anrufen) oder bei jedem eingehenden Anruf nacheinander anrufen? Die meisten Kunden haben die Strategie First Available, daher gibt es damit keine Probleme; es ruft nur einer an. Aber die Frage muss geklärt werden.

  2. Die Funktion zur Registrierung von Anrufen in Bitrix24, die die benötigte CallID zurückgibt, die später für die Übermittlung von Anrufparametern und den Link zur Aufzeichnung benötigt wird. Erfordert entweder die interne Nummer oder die UserID.

Wir beschäftigen uns mit FreePBX und integrieren es mit Bitrix24 und nicht nur damit.

Nach Beendigung des Anrufs wird die Funktion zum Laden der Aufzeichnung aufgerufen, die gleichzeitig den Status des Anrufabschlusses (Besetzt, Keine Antwort, Erfolg) meldet und den Link zur mp3-Datei der Aufzeichnung (falls vorhanden) lädt.

Da das Modul CallMeIn.php kontinuierlich arbeiten muss, wurde eine SystemD-Startdatei erstellt. callme.service, die in /etc/systemd/system/callme.service abgelegt werden muss.

[Unit]
Description=CallMe

[Service]
WorkingDirectory=/var/www/html/callmeplus
ExecStart=/usr/bin/php /var/www/html/callmeplus/CallMeIn.php 2>&1 >>/var/log/callmeplus.log
ExecStop=/bin/kill -WINCH ${MAINPID}
KillSignal=SIGKILL

Restart=on-failure
RestartSec=10s

#Hier muss man schauen, welche Berechtigungen für die Ordner benötigt werden
#User=www-data  #Ubuntu - debian
#User=nginx #Centos

[Install]
WantedBy=multi-user.target

Die Initialisierung und der Start des Skripts erfolgen über systemctl oder service.

# systemctl enable callme
# systemctl start callme

Der Dienst wird bei Bedarf automatisch neu gestartet (bei Abstürzen). Der Dienst zur Überwachung eingehender Anrufe erfordert keine Installation eines Webservers, es wird nur PHP benötigt (das definitiv auf dem FeePBX-Server vorhanden ist). Aber ohne Zugriff auf die Anrufaufzeichnungen über den Webserver (insbesondere mit https) gibt es keine Möglichkeit, die Gesprächsaufzeichnungen anzuhören.

Jetzt sprechen wir über ausgehende Anrufe. Das Skript CallMeOut.php hat zwei Funktionen:

  • Initiierung eines Anrufs bei Eingang einer Anfrage an das PHP-Skript (einschließlich über die Schaltfläche „Anrufen“ in Bitrix selbst). Funktioniert ohne Webserver nicht, die Anfrage kommt über HTTP POST, in der Anfrage befindet sich ein Token.

  • Benachrichtigung über den Anruf, dessen Parameter und Aufzeichnungen in Bitrix. Erfolgt auf Initiative von Asterisk im Dialplan [sub-call-internal-ended] am Ende des Anrufs.

Wir beschäftigen uns mit FreePBX und integrieren es mit Bitrix24 und nicht nur damit.

Der Webserver wird nur für zwei Dinge benötigt - das Hochladen von Aufzeichnungsdateien durch Bitrix (über HTTPS) und den Aufruf des Skripts CallMeOut.php. Man kann den integrierten FreePBX-Server verwenden, dessen Dateien sich in /var/www/html befinden, man kann einen anderen Server installieren oder einen anderen Pfad angeben.

Webserver

Lass uns die Konfiguration des Webservers zur Selbststudie überlassen (klick, klick, klick). Wenn du keine Domain hast, kannst du FreeDomain ausprobieren ( https://www.freenom.com/ru/index.html), die dir kostenlos einen Namen für deine öffentliche IP zur Verfügung stellen (vergiss nicht, die Ports 80, 443 über den Router weiterzuleiten, wenn die externe Adresse nur darauf vorhanden ist). Wenn du gerade erst eine DNS-Domain erstellt hast, musst du warten (von 15 Minuten bis 48 Stunden), bis alle Server aktualisiert sind. Nach Erfahrung mit heimischen Anbietern — von 1 Stunde bis zu einem Tag.

Automatisierung der Installation

Auf GitHub wurde mit der Entwicklung eines Installers begonnen, um die Installation noch einfacher zu gestalten. Doch es war nur auf dem Papier glatt — während wir das alles manuell installieren, wurde nach dem Eingreifen in all das klar, mit wem man es zu tun hat, wo man hin geht und wie man das debuggt. Ein Installer ist bisher nicht vorhanden (

Docker

Wenn du schnell eine Lösung ausprobieren möchtest — es gibt eine Möglichkeit mit Docker — einen Container schnell erstellen, ihm Ports nach außen öffnen, Konfigurationsdateien bereitstellen und ausprobieren (das ist eine Option mit dem LetsEncrypt-Container, falls das Zertifikat bereits vorhanden ist, muss nur der Reverse Proxy auf den FreePBX-Webserver umgeleitet werden (wir haben ihm einen anderen Port — 88 — zugewiesen), LetsEncrypt in Docker inspiriert von dieses Artikels

Die Datei muss im heruntergeladenen Projektordner (nach git clone) ausgeführt werden, aber vorher muss man die Konfigurationen von Asterisk (Ordner asterisk) aufrufen und dort die Pfade zu den Aufzeichnungen und der URL deiner Seite eintragen.

version: '3.3'
services:
  nginx:
    image: nginx:1.15-alpine
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - .\/nginx\/ssl_docker.conf:\/etc\/nginx\/conf.d\/ssl_docker.conf
  certbot:
    image: certbot\/certbot
  freepbx:
    image: flaviostutz\/freepbx
    ports:
      - 88:80 # zur Konfiguration
      - 5060:5060\/udp
      - 5160:5160\/udp
      - 127.0.0.1:5038:5038 # für CallMeOut.php
#      - 3306:3306
      - 18000-18100:18000-18100\/udp
    restart: always
    environment:
      - ADMIN_PASSWORD=admin123
    volumes:
      - backup:\/backup
      - recordings:\/var\/spool\/asterisk\/monitor
      - .\/callme:\/var\/www\/html\/callme
      - .\/systemd\/callme.service:\/etc\/systemd\/system\/callme.conf
      - .\/asterisk\/manager_custom.conf:\/etc\/asterisk\/manager_custom.conf
      - .\/asterisk\/extensions_custom.conf:\/etc\/asterisk\/extensions_custom.conf
#      - .\/conf\/startup.sh:\/startup.sh

volumes:
  backup:
  recordings:

Diese Datei docker-compose.yaml wird über

docker-compose up -d

Wenn Nginx nicht gestartet ist, stimmt etwas mit der Konfiguration im Ordner nginx\/ssl_docker.conf nicht.

Andere Integrationen

Warum nicht gleich mehrere CRMs in die Skripte integrieren, haben wir gedacht. Wir haben mehrere APIs anderer CRMs untersucht, insbesondere die kostenlose, die in einige PBXs integriert ist — ShugarCRM und Vtiger, und ja! es ist möglich, das Prinzip ist dasselbe. Aber das ist eine andere Geschichte, die wir später separat auf GitHub hochladen werden.

Links

Haftungsausschluss: Jegliche Übereinstimmungen mit der Realität sind rein fiktiv und ich war es nicht,

Quelle: habr.com

60GB SSD 8Gb DDR4