
Il existe différentes options pour intégrer IP-ATS Asterisk et CRM Bitrix24, mais nous avons finalement décidé d'écrire la nÎtre.
Les fonctionnalités sont standard :
- En cliquant sur le lien avec le numéro de téléphone du client dans Bitrix24, Asterisk connecte le numéro interne de l'utilisateur au nom duquel ce clic a été effectué, avec le numéro de téléphone du client. Une note de l'appel est enregistrée dans Bitrix24 et, à la fin de l'appel, l'enregistrement de la conversation est récupéré.
- Un appel arrive sur Asterisk - dans l'interface de Bitrix24, nous montrons la fiche du client à l'employé à qui cet appel est destiné.
S'il n'y a pas de client, nous ouvrirons la fiche pour créer un nouveau lead.
DÚs que l'appel est terminé, nous le reflétons dans la fiche et récupérons l'enregistrement de la conversation.
Je vous expliquerai comment tout configurer chez vous et je fournirai un lien vers github - oui, oui, prenez-le et utilisez-le !
Description générale
Nous avons nommé notre intégration CallMe. CallMe est une petite application web écrite en PHP.
Technologies et services utilisés
- PHP 5.6
- Composer
- Nginx + php-fpm
- supervisor
- AMI (Asterisk Manager Interface)
- Webhooks Bitrix (implémentation simplifiée de l'API REST)
Configuration préalable
Sur le serveur avec Asterisk, il est nécessaire d'installer un serveur web (nous avons nginx+php-fpm), supervisor et git.
Commande d'installation (CentOS) :
yum install nginx php-fpm supervisor gitAccédez au répertoire accessible au serveur web, tirez l'application de git et définissez les droits appropriés sur le dossier :
cd /var/www
git clone https://github.com/ViStepRU/callme.git
chown nginx. -R callme/
Ensuite, configurons nginx, notre fichier de configuration est situé dans
/etc/nginx/conf.d/pbx.vistep.ru.confserveur {
server_name www.pbx.vistep.ru pbx.vistep.ru;
listen *:80;
rewrite ^ https://pbx.vistep.ru$request_uri? permanent;
}
serveur {
# 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; # interdiction pour les fichiers cachés
}
location ~* \/(?:uploads|files)\/.*.php$ {
deny all; # interdiction pour les scripts chargés
}
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; # mise en cache de la statique
}
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;
}
}
Je vais laisser l'analyse de la configuration, les questions de sĂ©curitĂ©, l'obtention du certificat et mĂȘme le choix du serveur web en dehors de cet article â beaucoup en ont dĂ©jĂ parlĂ©. L'application n'a pas de restrictions, elle fonctionne Ă la fois en http et en https.
Nous avons un https, certificat let's encrypt.
Si vous avez tout fait correctement, vous devriez voir quelque chose comme cela en cliquant sur le lien.

Configuration de Bitrix24
Nous allons créer deux webhooks.
Webhook entrant.
Sous le compte administrateur (avec l'id 1), allez dans : Applications -> Webhooks -> Ajouter un webhook -> Webhook entrant

Remplissez les paramÚtres du webhook entrant comme sur les captures d'écran :


Et cliquez sur enregistrer.
AprÚs avoir enregistré, Bitrix24 vous fournira l'URL du webhook entrant, par exemple :

Conservez votre version de l'URL sans le \/profile\/ Ă la fin â elle sera utilisĂ©e dans l'application pour travailler avec les appels entrants.
Pour moi, cela est https://b24-xsynia.bitrix24.ru/rest/1/7eh61lh8pahw0fwt/
Webhook sortant.
Applications -> Webhooks -> Ajouter un webhook -> Webhook sortant
Les détails à nouveau sur les captures d'écran :


Enregistrez et obtenez le code d'autorisation

Pour moi, cela est xcrp2ylhzzd2v43cmfjqmkvrgrcbkni6. Il doit Ă©galement ĂȘtre copiĂ©, il est nĂ©cessaire pour passer des appels sortants.
Attention !
Un certificat SSL doit ĂȘtre configurĂ© sur le serveur Bitrix24 (vous pouvez utiliser letsencrypt), sinon l'API de Bitrix ne fonctionnera pas. Si vous avez la version cloud, pas de souci â SSL est dĂ©jĂ configurĂ©.
Attention !
Dans le champ « Adresse du gestionnaire », vous devez indiquer une adresse accessible depuis Internet !
Enfin, nous allons installer notre CallMeOut en tant qu'application de passation d'appels (pour que lors d'un clic sur le numéro, une commande soit envoyée à la PBX pour l'initiation de l'appel).
Dans le menu, sélectionnez : Autres -> Téléphonie -> Autres -> ParamÚtres, définissez dans « Numéro pour l'appel sortant par défaut » l'application : CallMeOut et cliquez sur « Enregistrer »

Configuration d'Asterisk
Pour assurer une interaction réussie entre Asterisk et Bitrix24, nous devons ajouter l'utilisateur AMI callme dans 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
Ensuite, il y a quelques astuces que nous devrons implémenter via le dialplan (dans notre cas, c'est extensions.ael).
Je présente le fichier complet, et ensuite je fournirai des explications :
globals {
WAV=\/var\/www\/pbx.vistep.fr\/callme\/records\/wav; \/\/Dossier temporaire pour les fichiers WAV
MP3=\/var\/www\/pbx.vistep.fr\/callme\/records\/mp3; \/\/Emplacement pour décharger les fichiers mp3
URLRECORDS=https:\/\/pbx.vistep.fr\/callme\/records\/mp3;
RECORDING=1; \/\/ Enregistrement, 1 - activé.
};
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()); \/\/ Mettre Ă jour l'identification de l'appelant si nous l'avons obtenue de 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 déjà été fixé ===));
}
}
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.fr\/CallMeOut.php --data action=sendcall2b24 --data call_id=${CallMeCALL_ID} --data-urlencode FullFname=${FullFname} --data CallIntNum=${CallIntNum} --data CallDuration=${CallMeDURATION} --data-urlencode CallDisposition=${CallMeDISPOSITION});
}
};
Commençons par le début : la directive globals.
Variable URLRECORDS contient l'URL des fichiers d'enregistrement des appels, que Bitrix24 utilisera pour les intégrer à la fiche de contact.
Ensuite, intéressons-nous au macro recording.
Ici, en plus de l'enregistrement des appels, nous allons définir la variable FullFname.
Set(FullFname=${URLRECORDS}\/${datedir}\/${fname}.mp3);Elle contient l'URL complÚte vers un fichier spécifique (le macro est appelé partout).
Analysons l'appel sortant :
_. => {
&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});
}
Supposons que nous appelions le 89991234567, nous commençons ici :
&recording(${CALLERID(number)},${EXTEN});c'est-à -dire qu'il appelle la macro d'enregistrement de l'appel et définit les variables nécessaires.
Ensuite
Set(__CallIntNum=${CALLERID(num)})
Set(CallStart=${STRFTIME(epoch,,%s)});
nous enregistrons qui a initié l'appel et notons l'heure de début de l'appel.
Et à sa fin, dans un contexte spécial 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});
}
nous dĂ©sactivons l'enregistrement dans la table CDR pour cet extension (pas besoin ici), nous fixons l'heure de fin d'appel, calculons la durĂ©e, si le rĂ©sultat de l'appel n'est pas connu â nous dĂ©finissons (la variable CallMeDISPOSITION) et, en dernier recours, nous envoyons tout Ă Bitrix via cURL.
Et un peu de magie â l'appel entrant :
888999 => {
&recording(${CALLERID(number)},${EXTEN});
Answer();
ExecIF(${CallMeCallerIDName}?Set(CALLERID(name)=${CallMeCallerIDName}):NoOp()); // nous définissons le CallerID si nous l'avons appris de Bitrix24
Set(CallStart=${STRFTIME(epoch,,%s)}); // nous commençons le chronomÚtre de l'appel
Queue(Q1,tT);
Set(CallMeDISPOSITION=${CDR(disposition)});
Hangup();
}
Ici, une seule ligne nous intéresse.
ExecIF(${CallMeCallerIDName}?Set(CALLERID(name)=${CallMeCallerIDName}):NoOp());Elle dit à l'ATS de définir CallerID(name) comme la variable CallMeCallerIDName.
La variable CallMeCallerIDName, Ă son tour, est dĂ©finie par l'application CallMe (s'il y a un nom pour le numĂ©ro appelĂ© dans Bitrix24 â nous le fixerons comme CallerID(name), sinon â nous ne ferons rien).
Configuration de l'application
Le fichier de configuration de l'application â /var/www/pbx.vistep.ru/config.php
Description des paramĂštres de l'application :
- CallMeDEBUG â si 1, alors tous les Ă©vĂ©nements traitĂ©s par l'application seront Ă©crits dans le fichier log, 0 â nous ne notons rien
- tech â SIP/PJSIP/IAX/etc
- authToken â jeton d'autorisation Bitrix24, code d'autorisation du webhook sortant
- bitrixApiUrl â URL du webhook entrant, sans profile/
- extensions â liste des numĂ©ros externes
- context â contexte pour l'origine de l'appel
- listener_timeout â vitesse de traitement des Ă©vĂ©nements d'Asterisk
- asterisk â tableau avec les paramĂštres de connexion Ă Asterisk :
- host â ip ou nom d'hĂŽte du serveur Asterisk
- scheme â schĂ©ma de connexion (tcp://, tls://)
- port â port
- username â nom d'utilisateur
- secret â mot de passe
- connect_timeout â dĂ©lai d'attente de connexion
- read_timeout â dĂ©lai d'attente de lecture
exemple de fichier de configuration :
1, // débogage des messages dans le journal : 1 - écriture, 0 - non-écriture
'tech' => 'SIP',
'authToken' => 'xcrp2ylhzzd2v43cmfjqmkvrgrcbkni6', // jeton d'autorisation de Bitrix
'bitrixApiUrl' => 'https://b24-xsynia.bitrix24.ru/rest/1/7eh61lh8pahw0fwt/', // URL de l'API Bitrix (webhook entrant)
'extensions' => array('888999'), // liste des numéros externes, séparés par des virgules
'context' => 'dial_out', // contexte sortant pour l'origine de l'appel
'asterisk' => array( // paramĂštres de connexion Ă 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, // vitesse de traitement des événements d'Asterisk
);Configuration du superviseur
Supervisor sert à exécuter le processus de gestion des événements CallMeIn.php d'Asterisk, qui surveille les appels entrants et interagit avec Bitrix24 (afficher la fiche, cacher la fiche, etc.).
Fichier de configuration à créer :
/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.logDémarrage et redémarrage de l'application :
supervisorctl start callme
supervisorctl restart callmevérification de l'état de l'application :
supervisorctl status callme
callme RUNNING pid 11729, uptime 17 jours, 16:58:07Conclusion
C'était assez compliqué, mais je suis sûr qu'un administrateur expérimenté pourra l'implémenter et ravir ses utilisateurs.
Comme promis, .
Questions, suggestions â veuillez laisser des commentaires. Si vous ĂȘtes Ă©galement intĂ©ressĂ© par le dĂ©veloppement de cette intĂ©gration, faites-le moi savoir, et dans un prochain article, j'essaierai de tout expliquer plus en dĂ©tail.
Source : habr.com
