Integrarea Asterisk și Bitrix24

Integrarea Asterisk și Bitrix24
Există diferite opțiuni pentru integrarea IP-ATC Asterisk și CRM Bitrix24, dar, totuși, am decis să ne scriem propriul nostru.

Funcționalitatea este standard:

  • Facem clic pe linkul cu numărul de telefon al clientului în Bitrix24, Asterisk conectează numărul intern al utilizatorului, în numele căruia a fost făcut clic, cu numărul de telefon al clientului. În Bitrix24 se înregistrează un raport al apelului, iar la finalizarea apelului se extrage înregistrarea conversației.
  • Asterisk primește un apel din exterior — în interfața Bitrix24 arătăm fisa clientului angajatului la care a fost direcționat acest apel.
    Dacă nu există un astfel de client, vom deschide fisa pentru crearea unui nou lead.
    Imediat ce apelul s-a încheiat, reflectăm acest lucru în fisa și extragem înregistrarea conversației.

Voi explica mai jos cum să configurezi totul la tine și îți voi oferi un link către github — da, da, ia-l și folosește-l!

Descriere generală

Integrarea noastră se numește CallMe. CallMe — este o mică aplicație web, scrisă în PHP.

Tehnologii și servicii utilizate

  • PHP 5.6
  • Biblioteca PHP AMI
  • Composer
  • Nginx + php-fpm
  • supervisor
  • AMI (Asterisk Manager Interface)
  • Webhook-urile Bitrix (implementare simplificată API REST)

Configurare preliminară

Pe serverul cu Asterisk, trebuie să instalăm un server web (la noi este nginx+php-fpm), supervisor și git.

Comanda pentru instalare (CentOS):

yum install nginx php-fpm supervisor git

Ne mutăm în directorul accesibil serverului web, tragem aplicația din git și setăm permisiunile necesare pe folder:


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

Apoi vom configura nginx, configurația noastră se află în

/etc/nginx/conf.d/pbx.vistep.ru.conf

server {
	server_name www.pbx.vistep.ro pbx.vistep.ro;
	listen *:80;
	rewrite ^  https://pbx.vistep.ro$request_uri? permanent;
}

server {
#        listen *:80;
#	server_name pbx.vistep.ro;


	access_log /var/log/nginx/pbx.vistep.ro.access.log main;
        error_log /var/log/nginx/pbx.vistep.ro.error.log;

    listen 443 ssl http2;
    server_name pbx.vistep.ro;
    resolver 8.8.8.8;
    ssl_stapling on;
    ssl on;
    ssl_certificate /etc/letsencrypt/live/pbx.vistep.ro/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/pbx.vistep.ro/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; # interzicere pentru fișiere ascunse
        }

        location ~* \/(?:uploads|files)\/.*.php$ {
                deny all; # interzicere pentru scripturile încărcate
        }

        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; # cache pentru statice
        }

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

Analiza configurării, întrebările de securitate, obținerea certificatului și chiar alegerea serverului web le voi lăsa deoparte — s-au scris multe despre acestea. Aplicația nu are restricții, funcționează atât pe http, cât și pe https.

Noi folosim https, certificat Let’s Encrypt.

Dacă ați făcut totul corect, atunci accesând linkul ar trebui să vedeți ceva asemănător

Integrarea Asterisk și Bitrix24

Configurarea Bitrix24

Să creăm două webhooks.

Webhook de intrare.

Sub contul de administrator (cu id 1) mergem la: Aplicații -> Webhooks -> Adăugați webhook -> Webhook de intrare

Integrarea Asterisk și Bitrix24

Completați parametrii webhook-ului de intrare conform capturilor de ecran:

Integrarea Asterisk și Bitrix24

Integrarea Asterisk și Bitrix24

Și apăsați salvați.

După salvare, Bitrix24 va oferi URL-ul webhook-ului de intrare, de exemplu:

Integrarea Asterisk și Bitrix24

Salvați URL-ul dumneavoastră fără încheierea /profile/ — acesta va fi folosit în aplicație pentru a gestiona apelurile de intrare.

În cazul meu, acesta este https://b24-xsynia.bitrix24.ru/rest/1/7eh61lh8pahw0fwt/

Webhook de ieșire.

Aplicații -> Webhooks -> Adăugați webhook -> Webhook de ieșire

Detalii din nou în capturile de ecran:

Integrarea Asterisk și Bitrix24

Integrarea Asterisk și Bitrix24

Salvăm și obținem codul de autorizare

Integrarea Asterisk și Bitrix24

În cazul meu, acesta este xcrp2ylhzzd2v43cmfjqmkvrgrcbkni6. Acesta trebuie, de asemenea, să fie salvat, este necesar pentru a efectua apeluri de ieșire.

Important!

Pe serverul Bitrix24 trebuie să fie configurat un certificat ssl (se poate utiliza letsencrypt), altfel API-ul Bitrix nu va funcționa. Dacă aveți versiunea cloud, nu trebuie să vă faceți griji — deja există ssl.

Important!

În câmpul „Adresa handler-ului” trebuie să fie specificată o adresă accesibilă din rețeaua Internet!

Și ca ultim detaliu, să instalăm CallMeOut ca aplicație pentru efectuarea apelurilor (astfel încât, la click pe număr, să fie trimisă o comandă către ATS pentru a iniția apelul).

În meniu alegem: Alte -> Telefonie -> Alte -> Setări, punem în „Numărul pentru apelul de ieșire implicit” Aplicația: CallMeOut și apăsăm „Salvează”

Integrarea Asterisk și Bitrix24

Configurarea asterisk

Pentru interacțiunea reușită între Asterisk și Bitrix24, trebuie să adăugăm utilizatorul AMI callme în 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

Apoi sunt câteva trucuri pe care va trebui să le implementați prin intermediul dialplan-ului (la noi este extensions.ael).

Vă prezint întregul fișier, după care voi oferi explicații:

globals {
    WAV=\/var\/www\/pbx.vistep.ro\/callme\/records\/wav; \/\/Catalog temporar pentru WAV
    MP3=\/var\/www\/pbx.vistep.ro\/callme\/records\/mp3; \/\/Unde să se descarce fișierele mp3
    URLRECORDS=https:\/\/pbx.vistep.ro\/callme\/records\/mp3;
    RECORDING=1; \/\/ Înregistrare, 1 - activată.
};

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()); \/\/ setează CallerID dacă l-am identificat din 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 deja a fost setat ===));  
}

}


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.ro\/CallMeOut.php --data action=sendcall2b24 --data call_id=${CallMeCALL_ID} --data-urlencode FullFname=${FullFname} --data CallIntNum=${CallIntNum} --data CallDuration=${CallMeDURATION} --data-urlencode CallDisposition=${CallMeDISPOSITION});
}

};

Să începem cu începutul: directivele globals.

Variabilă URLRECORDS stochează URL-ul fișierelor de înregistrare a apelurilor, prin care Bitrix24 le va adăuga în fișa de contact.

Apoi, ne interesează macro-ul recording.

Aici, pe lângă înregistrarea apelurilor, vom seta variabila FullFname.

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

Aceasta stochează URL-ul complet către fișierul specific (macro-ul este apelat pretutindeni).

Să analizăm apelul ieșit:

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

Să presupunem că sunăm la 89991234567, întâi ajungem aici:

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

adică se apelează macro-ul pentru înregistrarea apelului și se stabilesc variabilele necesare.

Următorul

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

înregistrăm cine a inițiat apelul și fixăm timpul de start al apelului.

Și la finalizarea acestuia, în contextul special 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});
}

deactivăm înregistrarea în tabela CDR pentru acest extensie (nu este necesară), setăm timpul de finalizare a apelului, calculăm durata, dacă rezultatul apelului nu este cunoscut — setăm (variabila CallMeDISPOSITION) și, în ultimul pas, trimitem totul către Bitrix prin sistemul curl.

Și puțină magie — apel incoming:

888999 =< {
	&recording(${CALLERID(number)},${EXTEN});
        Answer();
        ExecIF(${CallMeCallerIDName}?Set(CALLERID(name)=${CallMeCallerIDName}):NoOp()); // stabilim CallerID dacă l-am știut de la Bitrix24
        Set(CallStart=${STRFTIME(epoch,,%s)}); // începem să calculăm timpul apelului
        Queue(Q1,tT);
        Set(CallMeDISPOSITION=${CDR(disposition)});
        Hangup();
        }

Aici ne interesează doar o singură linie.

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

Aceasta spune centralei să seteze CallerID(name) egal cu variabila CallMeCallerIDName.

Însă variabila CallMeCallerIDName, la rândul său, este setată de aplicația CallMe (dacă în Bitrix24 există numele pentru numărul apelantului — îl vom seta ca CallerID(name), dacă nu — nu vom face nimic).

Configurarea aplicației

Fișierul de configurare pentru aplicație — /var/www/pbx.vistep.ru/config.php

Descrierea parametrilor aplicației:

  • CallMeDEBUG — dacă este 1, toate evenimentele procesate de aplicație vor fi scrise în fișierul de log, 0 — nu scriem nimic
  • tech — SIP/PJSIP/IAX/etc
  • authToken — token de autorizare Bitrix24, cod de autorizare webhook-ului de ieșire
  • bitrixApiUrl — URL-ul webhook-ului de intrare, fără profile/
  • extentions — lista numerelor externe
  • context — contextul pentru originea apelului
  • listener_timeout — viteza de procesare a evenimentelor de la Asterisk
  • asterisk — array cu setările de conectare la Asterisk:
  • host — ip sau hostname-ul serverului Asterisk
  • scheme — schema de conectare (tcp://, tls://)
  • port — port
  • username — numele utilizatorului
  • secret — parola
  • connect_timeout — timeout pentru conectare
  • read_timeout — timeout pentru citire

exemplu de fișier de setări:

 1, // mesaj de debug în jurnal: 1 - scriem, 0 - nu scriem
        'tech' => 'SIP',
        'authToken' => 'xcrp2ylhzzd2v43cmfjqmkvrgrcbkni6', // token de autorizare Bitrix
        'bitrixApiUrl' => 'https://b24-xsynia.bitrix24.ru/rest/1/7eh61lh8pahw0fwt/', // url către API-ul Bitrix (webhook de intrare)
        'extentions' => array('888999'), // lista numerelor externe, separate prin virgule
        'context' => 'dial_out', // contextul de ieșire pentru originea apelului
        'asterisk' => array( // setări pentru conectarea la 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, // viteza de procesare a evenimentelor de la Asterisk

);

Setarea supervisor-ului

Supervisorul este responsabil pentru pornirea procesului de manipulare a evenimentelor din Asterisk CallMeIn.php, care urmărește apelurile de intrare și interacționează cu Bitrix24 (afișează cardul, ascunde cardul etc.).

Fișierul de setări care trebuie creat:

/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

Lansarea și repornirea aplicației:

supervisorctl start callme
supervisorctl restart callme

verificarea stării de funcționare a aplicației:

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

Concluzie

A fost destul de complicat, dar sunt sigur că un administrator experimentat va reuși să implementeze aceasta și să-și bucure utilizatorii.

Așa cum am promis, link-ul de pe GitHub.

Întrebări, sugestii — vă rog în comentarii. De asemenea, dacă sunteți interesați de cum a decurs dezvoltarea acestei integrări, scrieți-mi, iar în următorul articol voi încerca să detaliez toate aceste aspecte.

Sursa: habr.com

Cumpără un hosting fiabil pentru site-uri cu protecție DDoS, servere VPS VDS 🔥 Cumpără un hosting fiabil pentru site-uri cu protecție DDoS, servere VPS VDS | ProHoster