Integratie van Asterisk en Bitrix24

Integratie van Asterisk en Bitrix24
Het netwerk heeft verschillende opties voor de integratie van IP-PBX Asterisk en CRM Bitrix24, maar we hebben toch besloten om er zelf een te schrijven.

Functioneel is alles standaard:

  • Door in Bitrix24 op de link met het telefoonnummer van de klant te klikken, verbindt Asterisk het interne nummer van de gebruiker namens wie deze klik is gemaakt met het telefoonnummer van de klant. In Bitrix24 wordt een record van het gesprek opgenomen en aan het einde van het gesprek wordt het gespreksrecord opgehaald.
  • Er komt een oproep binnen bij Asterisk van buitenaf - in de Bitrix24-interface laten we de klantkaart zien aan de medewerker op wiens nummer deze oproep is binnengekomen.
    Als er geen dergelijke klant is, opent u de kaart om een ​​nieuwe lead aan te maken.
    Zodra het gesprek is afgerond, reflecteren we dit op de kaart en halen we de opname van het gesprek tevoorschijn.

Onder de snit zal ik je vertellen hoe je alles voor jezelf kunt instellen en een link naar github geven - ja, ja, neem het en gebruik het!

Algemene beschrijving

We noemden onze integratie CallMe. CallMe is een kleine webapplicatie geschreven in PHP.

Gebruikte technologieën en diensten

  • PHP 5.6
  • PHP AMI-bibliotheek
  • Componist
  • nginx + php fpm
  • opzichter
  • AMI (Asterisk Manager-interface)
  • Bitrix-webhooks (vereenvoudigde REST API-implementatie)

Voorinstelling

Op de server met Asterisk moet je een webserver installeren (we hebben nginx + php-fpm), supervisor en git.

Installatieopdracht (CentOS):

yum install nginx php-fpm supervisor git

We geven de beschikbare map door aan de webserver, halen de applicatie uit de git en stellen de benodigde rechten in op de map:


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

Configureer vervolgens nginx, onze configuratie bevindt zich in

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

Ik zal de analyse van de configuratie, beveiligingsproblemen, het verkrijgen van een certificaat en zelfs het kiezen van een webserver buiten het bestek van het artikel laten - hier is veel over geschreven. De applicatie heeft geen beperkingen, het werkt op zowel http als https.

We hebben https, laten we het certificaat versleutelen.

Als je alles goed hebt gedaan, zou je door op de link te klikken zoiets als dit moeten zien

Integratie van Asterisk en Bitrix24

Bitrix24 instellen

Laten we twee webhooks maken.

Inkomende webhook.

Ga onder het beheerdersaccount (met id 1) naar het pad: Toepassingen -> Webhooks -> Webhook toevoegen -> Inkomende webhook

Integratie van Asterisk en Bitrix24

Vul de parameters van de inkomende webhook in zoals in de screenshots:

Integratie van Asterisk en Bitrix24

Integratie van Asterisk en Bitrix24

En klik op opslaan.

Na het opslaan geeft Bitrix24 de URL van de inkomende webhook, bijvoorbeeld:

Integratie van Asterisk en Bitrix24

Sla uw versie van de URL op zonder de /profile/ erna - deze wordt in de toepassing gebruikt om met inkomende oproepen te werken.

ik heb het https://b24-xsynia.bitrix24.ru/rest/1/7eh61lh8pahw0fwt/

Uitgaande webhook.

Toepassingen -> Webhooks -> Webhook toevoegen -> Uitgaande webhook

Details staan ​​op de screenshots:

Integratie van Asterisk en Bitrix24

Integratie van Asterisk en Bitrix24

Sla op en ontvang de autorisatiecode

Integratie van Asterisk en Bitrix24

ik heb het xcrp2ylhzzd2v43cmfjqmkvrgrcbkni6. Je moet het ook naar jezelf kopiëren, het is nodig om uitgaande gesprekken te voeren.

Belangrijk!

Er moet een ssl-certificaat worden geconfigureerd op de Bitrix24-server (u kunt letsencrypt gebruiken), anders werkt de BitrixXNUMX-api niet. Maak je geen zorgen als je een cloudversie hebt: ssl is er al.

Belangrijk!

In het veld "Adres van de processor" moet een adres worden opgegeven dat toegankelijk is via internet!

En als finishing touch, laten we onze CallMeOut installeren als een applicatie om te bellen (zodat door op het nummer op de PBX te klikken, er een commando zal vliegen om de oproep tot stand te brengen).

Selecteer in het menu: Meer -> Telefonie -> Meer -> Instellingen, stel in op "Nummer voor uitgaande oproepen standaard" Toepassing: CallMeOut en klik op "Opslaan"

Integratie van Asterisk en Bitrix24

sterretje instellen

Voor een succesvolle interactie tussen Asterisk en Bitrix24 moeten we de callme AMI-gebruiker toevoegen aan 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

Vervolgens zijn er een paar trucs die geïmplementeerd moeten worden met behulp van dialplan (we hebben extensions.ael).

Ik zal het hele bestand citeren, en dan zal ik uitleg geven:

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

};

Laten we bij het begin beginnen: directief globals.

Variabel URLRECORDS slaat de URL op naar de gespreksopnamebestanden, volgens welke Bitrix24 ze naar de contactkaart zal halen.

Vervolgens zijn we geïnteresseerd in macromacro opname.

Hier zullen we, naast het opnemen van gesprekken, de variabele instellen VolledigeFnaam.

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

Het slaat de volledige URL op naar een specifiek bestand (de macro wordt overal aangeroepen).

Laten we het uitgaande gesprek analyseren:

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

Laten we zeggen dat we 89991234567 bellen, het eerste wat we hier krijgen:

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

die. de oproepopnamemacro wordt aangeroepen en de benodigde variabelen worden ingesteld.

Volgende

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

we registreren wie het gesprek heeft gestart en registreren de starttijd van het gesprek.

En bij voltooiing, in een bijzondere context 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});
}

schakel de invoer in de CDR-tabel voor deze extensie uit (het is daar niet nodig), stel de eindtijd van het gesprek in, bereken de duur, als het resultaat van het gesprek niet bekend is - stel in (variabel Noem me AARDIGHEID) en stuur als laatste stap alles naar Bitrix via de systeemkrul.

En een beetje meer magie - een inkomende oproep:

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

Hier zijn we alleen geïnteresseerd in één regel.

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

Ze zegt PBX installeren BellerID(naam) variabel CallMeCallerIDNaam.

De variabele CallMeCallerIDName zelf wordt op zijn beurt ingesteld door de CallMe-toepassing (als Bitrix24 een volledige naam heeft voor het nummer van de beller, stellen we deze in als BellerID(naam), nee - we zullen niets doen).

Het instellen van de applicatie

Applicatie-instellingenbestand - /var/www/pbx.vistep.ru/config.php

Beschrijving van toepassingsparameters:

  • Bel MeDEBUG - indien 1, dan worden alle door de toepassing verwerkte gebeurtenissen naar het logbestand geschreven, 0 - we schrijven niets
  • tech SIP/PJSIP/IAX/enz
  • authToken — Bitrix24-autorisatietoken, uitgaande webhook-autorisatiecode
  • bitrixApiUrl — URL van de inkomende webhook, zonder profiel/
  • uitbreidingen — lijst met externe nummers
  • verband — context voor gespreksopbouw
  • luisteraar_timeout - verwerkingssnelheid van gebeurtenissen vanaf sterretje
  • asterisk - een array met de verbindingsinstellingen naar de asterisk:
  • gastheer - ip of hostnaam van de asterisk-server
  • schema — aansluitschema (tcp://, tls://)
  • port - poort
  • gebruikersnaam - Gebruikersnaam
  • geheim - wachtwoord
  • connect_time-out - time-out verbinding
  • lees_time-out - lees time-out

voorbeeld instellingenbestand:

 <?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

);

Opstelling supervisor

Supervisor wordt gebruikt om het gebeurtenishandlerproces Asterisk CallMeIn.php te starten, dat inkomende oproepen controleert en communiceert met Bitrix24 (toon de kaart, verberg de kaart, enz.).

Instellingenbestand om te maken:

/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

Starten en herstarten van de applicatie:

supervisorctl start callme
supervisorctl restart callme

bekijk de status van de aanvraag:

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

Conclusie

Het bleek vrij moeilijk, maar ik weet zeker dat een ervaren beheerder zijn gebruikers kan implementeren en behagen.

Zoals beloofd, link naar github.

Vragen, suggesties - graag in de comments. Als je geïnteresseerd bent in hoe de ontwikkeling van deze integratie is verlopen, schrijf dan en in het volgende artikel zal ik proberen alles in meer detail te onthullen.

Bron: www.habr.com

Voeg een reactie