Integración de Asterisk e Bitrix24

Integración de Asterisk e Bitrix24
Existen diferentes opcións para integrar a IP-PBX Asterisk e CRM Bitrix24 na rede, pero aínda así decidimos escribir a nosa.

En canto á funcionalidade, todo é estándar:

  • Ao facer clic nunha ligazón co número de teléfono dun cliente en Bitrix24, Asterisk conecta o número interno do usuario en cuxo nome se fixo o clic co número de teléfono do cliente. En Bitrix24, grávase un rexistro da chamada e, ao final da chamada, tírase unha gravación da conversa.
  • Asterisk recibe unha chamada desde fóra: na interface de Bitrix24 mostrámoslle a tarxeta do cliente ao empregado a cuxo número chegou esta chamada.
    Se non hai tal cliente, abriremos a tarxeta para crear un novo cliente potencial.
    En canto finaliza a chamada, reflectímolo na tarxeta e extraemos unha gravación da conversa.

Debaixo do corte vouche dicir como configuralo todo por ti mesmo e darche unha ligazón a github: si, si, tómao e úsao!

Descrición xeral

Chamamos a nosa integración CallMe. CallMe é unha pequena aplicación web escrita en PHP.

Tecnoloxías e servizos empregados

  • PHP 5.6
  • Biblioteca PHP AMI
  • compositor
  • Nginx + php-fpm
  • supervisor
  • AMI (Interface de Xestor de Asterisk)
  • Webhooks Bitrix (implementación de API REST simplificada)

Configuración previa

Nun servidor con Asterisk, cómpre instalar un servidor web (para nós é nginx+php-fpm), supervisor e git.

Comando de instalación (CentOS):

yum install nginx php-fpm supervisor git

Imos ao directorio accesible para o servidor web, tiramos da aplicación de Git e establecemos os dereitos necesarios para o cartafol:


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

A continuación, imos configurar nginx, a nosa configuración está situada en

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

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

server {
#        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; # запрет для скрытых файлов
        }

        location ~* /(?:uploads|files)/.*.php$ {
                deny all; # запрет для загруженных скриптов
        }

        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; # кеширование статики
        }

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

Vou deixar analizar a configuración, os problemas de seguridade, a obtención dun certificado e mesmo elixir un servidor web fóra do ámbito do artigo - escribiuse moito sobre isto. A aplicación non ten restricións, funciona tanto en http como en https.

Usamos https, imos cifrar o certificado.

Se fixeches todo correctamente, premendo na ligazón deberías ver algo así

Integración de Asterisk e Bitrix24

Configuración de Bitrix24

Imos crear dous webhooks.

Webhook entrante.

Baixo a conta de administrador (con id 1), siga o camiño: Aplicacións -> Webhooks -> Engadir webhook -> Webhook entrante

Integración de Asterisk e Bitrix24

Encha os parámetros do webhook entrante como nas capturas de pantalla:

Integración de Asterisk e Bitrix24

Integración de Asterisk e Bitrix24

E fai clic en gardar.

Despois de gardar, Bitrix24 proporcionará o URL do webhook entrante, por exemplo:

Integración de Asterisk e Bitrix24

Garda a túa versión do URL sen o /profile/ final: empregarase na aplicación para traballar coas chamadas entrantes.

Teño isto https://b24-xsynia.bitrix24.ru/rest/1/7eh61lh8pahw0fwt/

Webhook saínte.

Aplicacións -> Webhooks -> Engadir webhook -> Webhook de saída

Os detalles están de novo nas capturas de pantalla:

Integración de Asterisk e Bitrix24

Integración de Asterisk e Bitrix24

Garda e recibe o código de autorización

Integración de Asterisk e Bitrix24

Teño isto xcrp2ylhzzd2v43cmfjqmkvrgrcbkni6. Tamén debes copialo por ti mesmo; precisas para facer chamadas saíntes.

Importante!

Débese configurar un certificado SSL no servidor Bitrix24 (podes usar letsencrypt), se non, a API de Bitrix non funcionará. Se tes unha versión na nube, non te preocupes: xa ten ssl.

Importante!

O campo "Enderezo do procesador" debe conter un enderezo accesible desde Internet.

E como toque final, imos instalar o noso CallMeOut como unha aplicación para facer chamadas (de xeito que cando faga clic no número da central, o comando para orixinar a chamada vaia voando).

No menú, seleccione: Máis -> Telefonía -> Máis -> Configuración, configure "Número de chamada saínte predeterminado" Aplicación: CallMeOut e prema en "Gardar".

Integración de Asterisk e Bitrix24

Configurando asterisco

Para unha interacción exitosa entre Asterisk e Bitrix24, necesitamos engadir o usuario AMI callme a 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

A continuación, hai varios trucos que terán que ser implementados mediante dialplan (para nós isto é extensions.ael).

Proporcionarei o ficheiro completo e despois darei unha explicación:

globals {
    WAV=/var/www/pbx.vistep.ru/callme/records/wav; //Временный каталог с WAV
    MP3=/var/www/pbx.vistep.ru/callme/records/mp3; //Куда выгружать mp3 файлы
    URLRECORDS=https://pbx.vistep.ru/callme/records/mp3;
    RECORDING=1; // Запись, 1 - включена.
};

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()); // выставляем CallerID если узнали его у Битрикс24
        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 already was set ===));  
}

}


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

};

Comecemos polo principio: a directiva globais.

Variable URLRECORDS almacena o URL dos ficheiros de gravación da conversa, segundo o cal Bitrix24 os incorporará á tarxeta de contacto.

A continuación interésanos a macro macro gravación.

Aquí, ademais de gravar conversas, estableceremos a variable FullFname.

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

Almacena o URL completo nun ficheiro específico (a macro chámase en todas partes).

Analizamos a chamada saínte:

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

Digamos que chamamos ao 89991234567, antes de nada chegamos aquí:

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

aqueles. Chámase á macro de gravación da conversa e establécense as variables necesarias.

Máis

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

Gravamos quen iniciou a chamada e rexistramos a hora de inicio da chamada.

E ao seu remate, nun contexto especial 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});
}

desactivar a entrada na táboa CDR para esta extensión (non é necesaria alí), establecer a hora de finalización da chamada, calcular a duración, se non se coñece o resultado da chamada - establecer (variable CallMeDISPOSITION) e, o último paso, envía todo a Bitrix a través do curl do sistema.

E un pouco máis de maxia: unha chamada entrante:

888999 => {
	&recording(${CALLERID(number)},${EXTEN});
        Answer();
        ExecIF(${CallMeCallerIDName}?Set(CALLERID(name)=${CallMeCallerIDName}):NoOp()); // выставляем CallerID если узнали его у Битрикс24
        Set(CallStart=${STRFTIME(epoch,,%s)}); // начинаем отсчет времени звонка
        Queue(Q1,tT);
        Set(CallMeDISPOSITION=${CDR(disposition)}); 
        Hangup();
        }

Aquí só nos interesa unha liña.

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

Ela dille ao PBX que se instale ID de chamada(nome) igual a variable CallMeCallerIDName.

A propia variable CallMeCallerIDName, á súa vez, establécese pola aplicación CallMe (se Bitrix24 ten un nome completo para o número da persoa que chama, configúrao como ID de chamada(nome), non, non faremos nada).

Configuración da aplicación

Ficheiro de configuración da aplicación - /var/www/pbx.vistep.ru/config.php

Descrición dos parámetros de aplicación:

  • Chama aMeDEBUG — se é 1, todos os eventos procesados ​​pola aplicación escribiranse no ficheiro de rexistro, 0 — non escribimos nada
  • tecnoloxía - SIP/PJSIP/IAX/etc
  • authToken — Token de autorización Bitrix24, código de autorización de webhook saínte
  • bitrixApiUrl — URL do webhook entrante, sen perfil/
  • extensións - Lista de números externos
  • contexto - contexto para a orixe dunha chamada
  • listener_timeout — Velocidade de procesamento de eventos desde asterisco
  • asterisco — unha matriz con axustes para conectarse co asterisco:
  • anfitrión — ip ou nome de host do servidor asterisco
  • esquema - Diagrama de conexión (tcp://, tls://)
  • porto - Porto
  • nome de usuario - Nome de usuario
  • segredo - contrasinal
  • connect_timeout - tempo de espera da conexión
  • read_timeout - tempo de espera de lectura

exemplo de ficheiro de configuración:

 <?php
return array(

        'CallMeDEBUG' => 1, // дебаг сообщения в логе: 1 - пишем, 0 - не пишем
        'tech' => 'SIP',
        'authToken' => 'xcrp2ylhzzd2v43cmfjqmkvrgrcbkni6', //токен авторизации битрикса
        'bitrixApiUrl' => 'https://b24-xsynia.bitrix24.ru/rest/1/7eh61lh8pahw0fwt/', //url к api битрикса (входящий вебхук)
        'extentions' => array('888999'), // список внешних номеров, через запятую
        'context' => 'dial_out', //исходящий контекст для оригинации звонка
        'asterisk' => array( // настройки для подключения к астериску
                    'host' => '10.100.111.249',
                    'scheme' => 'tcp://',
                    'port' => 5038,
                    'username' => 'callme',
                    'secret' => 'JD3clEB8_f23r-3ry84gJ',
                    'connect_timeout' => 10000,
                    'read_timeout' => 10000
                ),
        'listener_timeout' => 300, //скорость обработки событий от asterisk

);

Configuración do supervisor

O supervisor úsase para iniciar o proceso de xestión de eventos desde Asterisk CallMeIn.php, que supervisa as chamadas entrantes e interactúa con Bitrix24 (mostrar tarxeta, ocultar tarxeta, etc.).

Ficheiro de configuración a crear:

/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

Inicie e reinicie a aplicación:

supervisorctl start callme
supervisorctl restart callme

Ver o estado operativo da aplicación:

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

Conclusión

Resultou bastante complicado, pero estou seguro de que un administrador experimentado poderá implementalo e agradar aos seus usuarios.

Como prometeu, ligazón a github.

Preguntas, suxestións: déixaas nos comentarios. Ademais, se estás interesado en como foi o desenvolvemento desta integración, escribe, e no próximo artigo tentarei desvelar todo con máis detalle.

Fonte: www.habr.com

Engadir un comentario