Wir beschäftigen uns mit FreePBX und integrieren es mit Bitrix24 und mehr.

Bitrix24 ist eine umfassende Lösung, die CRM, Dokumentenmanagement, Buchhaltung und viele weitere Funktionen vereint, die bei Managern beliebt sind, jedoch oft auf weniger Freude bei IT-Teams stoßen. Viele kleine und mittelständische Unternehmen, darunter kleine Kliniken, Hersteller und sogar Schönheitssalons, nutzen dieses Portal. Die Hauptfunktion, die Manager „lieben“, ist die Integration von Telefonie und CRM: Jeder Anruf wird sofort in der CRM erfasst, es werden Kundenkarten erstellt und beim Eingehenden Anruf werden die Kundeninformationen angezeigt, wodurch klar wird, wer der Kunde ist, was man ihm anbieten kann und wie viel er noch schuldet. Allerdings sind die Telefonie-Funktionen von Bitrix24 und deren Integration in die CRM nicht kostenlos und können manchmal hohe Kosten verursachen. In diesem Artikel werde ich die Erfahrung mit der Integration offener Lösungen und der beliebten IP-Telefonanlage FreePBX erläutern und die Funktionsweise der verschiedenen Teile untersuchen. FreePBX, und werde die Funktionsweise der verschiedenen Teile näher betrachten.

Ich arbeite freiberuflich für ein Unternehmen, das sich mit dem Verkauf und der Einrichtung sowie der Integration von IP-Telefonie beschäftigt. Als ich gefragt wurde, ob wir der eben genannten Firma etwas für die Integration von Bitrix24 mit den Telefonsystemen, die bei den Kunden installiert sind, oder auch mit den virtuellen Telefonsystemen auf verschiedenen VDS des Unternehmens anbieten könnten, bin ich zu Google gegangen. Und natürlich hat er mir einen Link zu einem Artikel auf Habr, wo es sowohl eine Beschreibung als auch GitHub gibt, und anscheinend funktioniert alles. Aber als ich versuchte, diese Lösung zu nutzen, stellte ich fest, dass Bitrix24 nicht mehr das ist, was es früher war, und vieles umgestaltet werden muss. Außerdem ist FreePBX nicht einfach nur Asterisk; hier muss man darüber nachdenken, wie man Benutzerfreundlichkeit mit dem komplexen Dialplan in den Konfigurationsdateien vereinen kann.

Wir analysieren die Logik der Funktionsweise

Also, zunächst einmal, wie sollte das alles funktionieren? Bei einem eingehenden Anruf auf die Telefonanlage (Ereignis SIP INVITE vom Anbieter) beginnt die Verarbeitung des Dialplans — den Regeln, was mit dem Anruf in welcher Reihenfolge zu tun ist. Aus dem ersten Paket lassen sich viele Informationen gewinnen, die später in den Regeln verwendet werden können. Ein hervorragendes Werkzeug zur Untersuchung der inneren Abläufe von SIP ist der Analysator sngrep (Link) der einfach in gängigen Distributionen über apt install/yum install und ähnliche Methoden installiert wird, aber auch aus den Source-Codes kompiliert werden kann. Lassen Sie uns das Anrufprotokoll in sngrep ansehen.

Wir beschäftigen uns mit FreePBX und integrieren es mit Bitrix24 und mehr.

Vereinfacht gesagt, kümmert sich der Dialplan nur um das erste Paket. Manchmal werden auch während des Gesprächs Anrufweiterleitungen, Tasteneingaben (DTMF) sowie verschiedene interessante Funktionen wie FollowMe, RingGroup, IVR und andere umgesetzt.

Was im Invite-Paket enthalten ist.

Wir beschäftigen uns mit FreePBX und integrieren es mit Bitrix24 und mehr.

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 – deshalb gibt es in der Telefonanlage wahrscheinlich Gruppenanrufe (gleichzeitige/folgende Anrufe mehrerer Telefone) für Festnetznummern (Ring Group), IVR (Hallo, Sie haben… Drücken Sie eins für…), Voicemail (Phrasen), Zeitbedingungen (Time Conditions), Weiterleitungen zu anderen Nummern oder auf Mobiltelefone (FollowMe, Forward). Das bedeutet, dass es äußerst schwierig ist, genau zu bestimmen, wohin der Anruf tatsächlich geleitet wird und mit wem das Gespräch bei 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 mehr.

Nach einem erfolgreichen Anruf in die PBX beginnt die Reise des Anrufs durch den Dialplan in verschiedenen "Kontexten". Ein Kontext aus der Perspektive von Asterisk ist eine nummerierte Reihe von Befehlen, von denen jeder einen Filter für die gewählte Nummer enthält (diese wird als exten bezeichnet, für einen externen Anruf zu Beginn ist 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 Anweisungen (IF, ELSE, ExecIF und ähnliche), Übergänge zu anderen Regeln dieses Kontextes (Goto, GotoIF), Wechsel zu anderen Kontexten durch Funktionsaufrufe (Gosub, Macro). Besonders hervorzuheben ist die Direktive include name_kontext, , die Befehle eines anderen Kontextes ans Ende des aktuellen Kontextes anhängt. Über include eingefügte Befehle werden immer ausgeführt nach befehlen des aktuellen Kontextes. Die gesamte Logik der Funktionsweise von FreePBX beruht auf der Einbeziehung verschiedener Kontexte durch include und den Aufruf über Gosub, Macro und Handler. Lassen Sie uns den Kontext der eingehenden Anrufe in FreePBX betrachten.

Die gesamte Logik von FreePBX basiert auf der Verschachtelung verschiedener Kontexte durch Includes sowie durch Aufrufe mittels Gosub, Macro und Handler-Handlern. Lassen Sie uns den Kontext der eingehenden Anrufe in FreePBX betrachten.

Wir beschäftigen uns mit FreePBX und integrieren es mit Bitrix24 und mehr.

Der Anruf erfolgt in allen Kontexten der Reihe nach von oben nach unten. In jedem Kontext können andere Kontexte als Makros (Macro), Funktionen (Gosub) oder einfache Sprünge (Goto) aufgerufen werden. Daher kann der tatsächliche Baum dessen, was aufgerufen wird, nur in den Logs nachverfolgt werden.

Das typische Schema zur Einrichtung einer konventionellen Büro-Telefonanlage ist nachfolgend dargestellt. Bei eingehenden Anrufen wird nach der DID gesucht, um die zeitlichen Bedingungen zu prüfen. Wenn alles in Ordnung ist, wird das Sprachmenü gestartet. Über die Taste 1 oder nach einem Timeout erfolgt der Anschluss an die Gruppe der Operatoren. Nach dem Ende des Anrufs wird das Makro hangupcall aufgerufen, wonach im Dialplan nichts mehr ausgeführt werden kann, außer durch spezielle Handler (hangup handler).

Wir beschäftigen uns mit FreePBX und integrieren es mit Bitrix24 und mehr.

An welcher Stelle in diesem Anrufalgorithmus sollten wir die Informationen über den Anrufbeginn an die CRM-Software übermitteln, wo das Aufzeichnen beginnen und enden soll und wo diese Informationen zusammen mit den Anrufdaten an das CRM gesendet werden sollen?

Integration mit externen Systemen

Was ist die Integration von PBX und CRM? Es handelt sich um Einstellungen und Programme, die Daten und Ereignisse zwischen diesen beiden Plattformen konvertieren und austauschen. Die gängigste Methode für die Interaktion unabhängiger Systeme ist die API, und der populärste Zugang zu APIs erfolgt über HTTP REST. Aber nicht für Asterisk.

Innerhalb von Asterisk gibt es:

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

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

Beispiel für AMI-Ausgabe

Ereignis: Newchannel
Berechtigung: call,all
Kanal: PJSIP/VMS_pjsip-0000078b
Kanalstatus: 4
Kanalstatusbeschreibung: Rings
AnruferIDNummer: 111222
AnruferIDName: 111222
VerbundenesLineNummer:
VerbundenesLineName:
Sprache: en
AccountCode:
Kontext: from-pstn
Exten: s
Priorität: 1
EindeutigeID: 1599589046.5244
VerknüpfteID: 1599589046.5244

  • ARI – eine Mischung aus beidem, alles über REST, WebSocket, im JSON-Format – aber die neuen Bibliotheken und Wrapper sind nicht sehr leistungsfähig, zufällig fand ich (phparia, phpari) die vor etwa 3 Jahren in der Entwicklung stagnieren.

Beispiel für ARI-Ausgabe bei Anrufinitiierung

{ «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»:»de» }, «asteriskid»:»48:5b:aa:aa:aa:aa», «application»:»hello-world» }

Ob der Zugriff auf die eine oder andere API einfach oder schwierig ist, hängt von den Aufgaben ab, die gelöst werden müssen. Die Anforderungen für die Integration mit dem CRM sind wie folgt:

  • Den Beginn des Anrufs und sein Ziel verfolgen, CallerID, DID, Start- und Endzeiten extrahieren, eventuell Daten aus dem Verzeichnis abrufen (um die Verbindung zwischen Telefon und CRM-Nutzer zu finden).

  • Die Aufnahme des Anrufs starten und beenden, im gewünschten Format speichern und nach Abschluss der Aufnahme mitteilen, wo die Datei abgelegt wurde.

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

  • Optional: Integration mit CRM, Anrufgruppen und FollowME für die automatische Umleitung von Anrufen bei Abwesenheit (basierend auf CRM-Informationen).

All diese Aufgaben können über AMI oder ARI gelöst werden, aber ARI bietet wesentlich weniger Informationen, viele Ereignisse werden nicht erfasst, und viele Variablen, die in AMI vorhanden sind (zum Beispiel Makroaufrufe, das Setzen von Variablen innerhalb von Makros, einschließlich der Aufzeichnung von Anrufen), werden nicht verfolgt. Daher wählen wir zunächst AMI für das richtige und präzise Tracking (aber nicht endgültig). Außerdem (wo wären wir ohne das, wir sind schließlich faul) — in der ursprünglichen Arbeit (Artikel in Habr) verwenden PAMI. *Dann sollten wir versuchen, es auf ARI umzuschreiben, aber ob das gelingt, ist ungewiss.

Wir denken die Integration neu aus.

Damit unser FreePBX auf einfache Weise über AMI Informationen über den Beginn eines Anrufs, die Endzeit, die Telefonnummern, die Namen der aufgezeichneten Dateien übermittelt, können wir den gleichen Trick wie die ursprünglichen Autoren nutzen — eigene Variablen einführen und deren Vorhandensein im Output parsen. PAMI bietet dies einfach über eine Filterfunktion an.

Hier ein Beispiel, um eine eigene Variable für die Startzeit des Anrufs festzulegen (s ist eine spezielle Nummer im Dialplan, die VOR der Suche nach DID ausgeführt wird).

[ext-did-custom]

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

Beispiel für ein AMI-Ereignis in dieser Zeile

Ereignis: Newchannel

Berechtigung: call,all

Kanal: PJSIP/VMS_pjsip-0000078b

Kanalstatus: 4

Kanalstatusbeschreibung: Rings

AnruferIDNummer: 111222

AnruferIDName: 111222

VerbundenesLineNummer:

VerbundenesLineName:

Sprache: en

AccountCode:

Kontext: from-pstn

Exten: s

Priorität: 1

EindeutigeID: 1599589046.5244

VerknüpfteID: 1599589046.5244

Anwendung: AppData festlegen:

CallStart=1599571046

Da FreePBX die Dateien extension.conf und extension_additional.conf überschreibt, werden wir die Datei extension_custom.conf

Vollständiger Code von extension_custom.conf

[globals]
;; Überprüfen Sie die Pfade und Berechtigungen für 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

;; Unter diesen Pfaden werden die Aufzeichnungen abgespielt und heruntergeladen
URLRECORDS=https://www.host.ru/callmeplus/records/mp3

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

;; Ja, wir zeichnen Gespräch auf
RECORDING=1

;; Dies ist ein Makro zur Aufzeichnung von Gesprächen in unseren Ordner. 
;; Man kann auch die Systemaufnahme 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 zwar unkonventionell, das so zu machen und hier, aber es funktioniert - fügen wir der Nummer '8' 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 normalen Wege zur Verarbeitung des Endes über (exten=>h,1,somethinghere) in FreePBX funktionieren nicht - Macro(hangupcall,) stört alles. 
;; Daher hängen wir 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]

;; Berichten Sie über die Werte beim 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, nicht antwort...
exten => s,n,Set(CallMeDISPOSITION=${CDR(disposition)})
exten => s,n,Return


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

;; Aufzeichnung
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 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 im CRM meldet - es handelt sich um einen ausgehenden, 
;; sodass im Grunde bei Beendigung
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

Das Hauptmerkmal und Unterschied des Dialplans von den ursprünglichen Autoren des Artikels ist —

  • Der Dialplan im .conf-Format, wie es FreePBX verlangt (ja, er kann auch .ael, aber nicht alle Versionen unterstützen das immer und es ist nicht immer praktisch)

  • Anstelle der Behandlung des Endes über exten=>h erfolgt die Behandlung über hangup_handler, da der Dialplan von FreePBX nur damit funktioniert

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

  • Die Bearbeitungen wurden in _custom-Kontexte ausgelagert, sodass die FreePBX-Konfigurationen nicht bearbeitet werden müssen — eingehende über [ext-did-custom], ausgehende über [outbound-allroutes-custom]

  • Keine Bindung an Nummern — die Datei ist universell und erfordert nur die Konfiguration des Pfades und den Verweis auf den Server

Um zu beginnen, müssen die Skripte über AMI mit Login und Passwort aktiviert werden — dafür gibt es auch eine _custom-Datei in FreePBX

Die Datei manager_custom.conf

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

;; ich arbeite mit der lokalen Maschine – aber wenn nötig, können auch andere hinzugefügt 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

Beide Dateien müssen in /etc/asterisk abgelegt werden, dann müssen die Konfigurationen neu geladen (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

Kommen wir nun zu PHP.

Initialisierung von Skripten und Erstellung des Dienstes.

Da das Arbeiten mit Bitrix 24, dem Dienst für AMI, nicht ganz einfach und transparent ist, wollen wir darauf näher eingehen. Asterisk öffnet bei der Aktivierung von AMI einfach den Port und das war's. Bei der Verbindung des Clients erfolgt eine Autorisierungsanfrage, danach meldet sich der Client für die gewünschten Ereignisse an. Die Ereignisse kommen als einfacher Text an, den PAMI in strukturierte Objekte umwandelt und die Möglichkeit bietet, Filterfunktionen nur für die interessierenden Ereignisse, Felder, Nummern usw. festzulegen.

Sobald der Anruf eingeht, wird das Ereignis NewExten im übergeordneten Kontext [from-pstn] ausgelöst, gefolgt von allen Ereignissen in der Reihenfolge der Zeilen in den Kontexten. Bei Erhalt von Informationen aus den im Dialplan festgelegten _custom-Variablen CallMeCallerIDName und CallStart wird ein Aufruf gestartet.

  1. Die Funktion zur Abfrage der UserID, die der internen Nummer entspricht, an die der Anruf gerichtet war. Und was ist, wenn es sich um eine Gruppennummer handelt? Das ist eine politische Frage; wir müssen entscheiden, ob wir alle gleichzeitig anrufen (wenn alle gleichzeitig anrufen) oder ob wir nacheinander anrufen, während wir die Anrufe abarbeiten. Die meisten Kunden haben die Strategie 'First Available', daher gibt es in diesem Fall keine Probleme; es kann nur einer anrufen. Aber wir müssen das Thema klären.

  2. Die Funktion zur Registrierung von Anrufen in Bitrix24, die den CallID zurückgibt, die später für die Übermittlung der Anrufparameter und den Link zur Aufnahme erforderlich ist. Sie benötigt entweder eine interne Nummer oder eine UserID.

Wir beschäftigen uns mit FreePBX und integrieren es mit Bitrix24 und mehr.

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

Da das Modul CallMeIn.php kontinuierlich arbeiten muss, wurde eine SystemD-Startdatei dafür erstellt. callme.service, die in /etc/systemd/system/callme.service platziert 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 müssen die Berechtigungen der Verzeichnisse überprüft 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 Überwachungsdienst für eingehende Anrufe benötigt keinen Webserver, sondern nur PHP (das auf dem FeePBX-Server vorhanden ist). Ohne Zugriff auf die Anrufprotokolle über den Webserver (zudem mit https) ist es jedoch nicht möglich, die Sprachaufzeichnungen anzuhören.

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

  • Initiierung eines Anrufs bei eingehendem Antrag auf das PHP-Skript (einschließlich per Knopf "Anrufen" im Bitrix selbst). Ohne Webserver funktioniert es nicht, der Antrag erfolgt über HTTP POST, im Antrag ist ein Token enthalten.

  • Mitteilung über den Anruf, seine Parameter und Aufzeichnungen in Bitrix. Dies geschieht auf Initiative von Asterisk im Dialplan [sub-call-internal-ended] nach Beendigung des Anrufs.

Wir beschäftigen uns mit FreePBX und integrieren es mit Bitrix24 und mehr.

Ein Webserver wird für zwei Hauptaufgaben benötigt: das Hochladen von Bitrix-Daten (über HTTPS) und das Aufrufen des Skripts CallMeOut.php. Sie können den integrierten FreePBX-Server verwenden, dessen Dateien sich unter /var/www/html befinden, oder einen anderen Server installieren bzw. einen anderen Pfad festlegen.

Webserver

Die Konfiguration des Webservers überlassen wir Ihrer eigenen Erkundung (klick hier, klick hier, klick hier). Wenn Sie keine Domain haben, können Sie FreeDomain ausprobieren ( https://www.freenom.com/ru/index.html), die Ihnen kostenlos einen Namen für Ihre öffentliche IP geben (vergessen Sie nicht, die Ports 80 und 443 über den Router weiterzuleiten, wenn die externe Adresse nur dort verfügbar ist). Wenn Sie gerade eine DNS-Domain erstellt haben, müssen Sie möglicherweise warten (15 Minuten bis 48 Stunden), bis alle Server aktualisiert sind. Nach Erfahrung mit einheimischen Providern liegt dies zwischen 1 Stunde und einem Tag.

Automatisierung der Installation

Auf GitHub wurde mit der Entwicklung eines Installers begonnen, um die Installation noch einfacher zu gestalten. Doch in der Theorie klingt alles gut — solange wir das alles manuell einrichten, wird klar, wer mit wem zusammenarbeitet, wo hinzugehen ist und wie man das debuggen kann. Ein Installer ist derzeit noch nicht verfügbar (

Docker

Wenn Sie eine schnelle Lösung ausprobieren möchten, gibt es die Möglichkeit mit Docker – ein Container schnell zu erstellen, Ports nach außen bereitzustellen, Konfigurationsdateien hinzuzufügen und zu testen (dies ist die Variante mit dem LetsEncrypt-Container; wenn das Zertifikat bereits vorhanden ist, muss einfach der Reverse Proxy auf den Webserver FreePBX umgeleitet werden (für den haben wir einen anderen Port – 88 festgelegt), LetsEncrypt im Docker-Kontext. dieses Artikels

Sie müssen die Datei im heruntergeladenen Projektordner (nach dem git clone) ausführen, aber zuvor in die Konfigurationen von Asterisk (Ordner asterisk) gehen und dort die Pfade zu den Aufzeichnungen und die URL Ihrer Website festlegen.

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 # für die 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 in der nginx/ssl_docker.conf nicht.

Andere Integrationen

Warum nicht ein paar CRM-Systeme in die Skripte integrieren, haben wir gedacht. Wir haben mehrere APIs anderer CRM-Systeme untersucht, insbesondere die kostenlose, die in einige Telefonanlagen 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 veröffentlichen werden.

Links

Haftungsausschluss: Alle Übereinstimmungen mit der Realität sind rein zufällig und das war nicht ich.

Quelle: habr.com

Zuverlässiges Webhosting mit DDoS-Schutz, VPS- und VDS-Server kaufen 🔥 Zuverlässiges Webhosting mit DDoS-Schutz, VPS- und VDS-Server kaufen | ProHoster