Integrasjon av Asterisk og Bitrix24

Integrasjon av Asterisk og Bitrix24
Nettverket har forskjellige alternativer for å integrere IP-PBX Asterisk og CRM Bitrix24, men vi bestemte oss likevel for å skrive vår egen.

Funksjonelt er alt standard:

  • Ved å klikke på lenken med klientens telefonnummer i Bitrix24, kobler Asterisk det interne nummeret til brukeren som dette klikket ble gjort på vegne av, med klientens telefonnummer. I Bitrix24 blir en oversikt over samtalen tatt opp, og ved slutten av samtalen trekkes samtaleposten opp.
  • En samtale kommer til Asterisk utenfra - i Bitrix24-grensesnittet viser vi klientkortet til den ansatte som denne samtalen kom til.
    Hvis det ikke finnes en slik klient, åpner du kortet for å opprette en ny kundeemne.
    Så snart samtalen er fullført reflekterer vi dette i kortet og trekker opp opptaket av samtalen.

Under kuttet skal jeg fortelle deg hvordan du setter opp alt for deg selv og gir en lenke til github - ja, ja, ta den og bruk den!

Generell beskrivelse

Vi kalte vår integrasjon CallMe. CallMe er en liten nettapplikasjon skrevet i PHP.

Brukte teknologier og tjenester

  • PHP 5.6
  • PHP AMI-bibliotek
  • Komponer
  • nginx + php fpm
  • veileder
  • AMI (Asterisk Manager Interface)
  • Bitrix webhooks (forenklet implementering av REST API)

forhåndsinnstilling

På serveren med Asterisk må du installere en webserver (vi har nginx + php-fpm), supervisor og git.

Installasjonskommando (CentOS):

yum install nginx php-fpm supervisor git

Vi sender katalogen som er tilgjengelig til webserveren, trekker applikasjonen fra git og setter de nødvendige rettighetene til mappen:


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

Deretter konfigurerer du nginx, vår konfigurasjon ligger i

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

Jeg vil la analysen av konfigurasjonen, sikkerhetsproblemer, innhenting av et sertifikat og til og med valg av webserver ligge utenfor rammen av artikkelen - mye er skrevet om dette. Applikasjonen har ingen begrensninger, den fungerer på både http og https.

Vi har https, la oss kryptere sertifikatet.

Hvis du gjorde alt riktig, bør du se noe slikt ved å klikke på lenken

Integrasjon av Asterisk og Bitrix24

Konfigurere Bitrix24

La oss lage to webhooks.

Innkommende webhook.

Under administratorkontoen (med id 1) gå langs stien: Programmer -> Webhooks -> Legg til webhook -> Innkommende webhook

Integrasjon av Asterisk og Bitrix24

Fyll inn parametrene for den innkommende webhook som i skjermbildene:

Integrasjon av Asterisk og Bitrix24

Integrasjon av Asterisk og Bitrix24

Og klikk lagre.

Etter lagring vil Bitrix24 oppgi URL-en til den innkommende webhook, for eksempel:

Integrasjon av Asterisk og Bitrix24

Lagre din versjon av URL-en uten den etterfølgende /profilen/ - den vil bli brukt i applikasjonen for å jobbe med innkommende anrop.

jeg har det https://b24-xsynia.bitrix24.ru/rest/1/7eh61lh8pahw0fwt/

Utgående webhook.

Applikasjoner -> Webhooks -> Legg til Webhook -> Utgående Webhook

Detaljer er på skjermbildene:

Integrasjon av Asterisk og Bitrix24

Integrasjon av Asterisk og Bitrix24

Lagre og få autorisasjonskoden

Integrasjon av Asterisk og Bitrix24

jeg har det xcrp2ylhzzd2v43cmfjqmkvrgrcbkni6. Du må også kopiere det til deg selv, det er nødvendig for å foreta utgående anrop.

Viktig!

Et ssl-sertifikat må konfigureres på Bitrix24-serveren (du kan bruke letsencrypt), ellers vil ikke BitrixXNUMX-api fungere. Hvis du har en skyversjon, ikke bekymre deg - ssl er der allerede.

Viktig!

I feltet "Processor's address" skal en adresse som er tilgjengelig fra Internett angis!

Og med siste touch, la oss installere vår CallMeOut som et program for å ringe (slik at ved å klikke på nummeret på PBX, vil en kommando fly for å starte anropet).

I menyen velger du: Mer -> Telefoni -> Mer -> Innstillinger, sett til "Nummer for utgående samtaler som standard" Applikasjon: CallMeOut og klikk "Lagre"

Integrasjon av Asterisk og Bitrix24

stjerneoppsett

For vellykket interaksjon mellom Asterisk og Bitrix24, må vi legge til callme AMI-brukeren til 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

Deretter er det noen få triks som må implementeres ved hjelp av dialplan (vi har extensions.ael).

Jeg vil sitere hele filen, og så vil jeg gi forklaringer:

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

};

La oss starte fra begynnelsen: direktiv globals.

variabel URLRECORDS lagrer URL-en til samtaleopptaksfilene, i henhold til hvilken Bitrix24 vil trekke dem inn i kontaktkortet.

Deretter er vi interessert i makro makro innspilling.

Her vil vi i tillegg til å ta opp samtaler sette variabelen FullFname.

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

Den lagrer hele URL-en til en bestemt fil (makroen kalles overalt).

La oss analysere den utgående samtalen:

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

La oss si at vi ringer 89991234567, det første vi får her:

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

de. samtaleopptaksmakroen kalles og de nødvendige variablene settes.

Neste

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

vi registrerer hvem som startet samtalen og registrerer starttidspunktet for samtalen.

Og når den er ferdig, i en spesiell sammenheng 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});
}

slå av oppføringen i CDR-tabellen for denne utvidelsen (det er ikke nødvendig der), angi sluttid for samtalen, beregn varigheten, hvis resultatet av samtalen ikke er kjent - angi (variabel Kall meg DISPOSISJON) og, det siste trinnet, send alt til Bitrix gjennom systemkrøllen.

Og litt mer magi - en innkommende samtale:

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

Her er vi kun interessert i én linje.

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

Hun sier PBX installere Anrops-ID (navn) variabel CallMeCallerIDName.

Selve CallMeCallerIDName-variabelen settes på sin side av CallMe-applikasjonen (hvis Bitrix24 har et fullt navn for innringerens nummer, vil vi sette det som Anrops-ID (navn), nei - vi vil ikke gjøre noe).

Applikasjonsoppsett

Programinnstillingsfil - /var/www/pbx.vistep.ru/config.php

Beskrivelse av applikasjonsparametere:

  • CallMeDEBUG - hvis 1, vil alle hendelser som behandles av applikasjonen bli skrevet til loggfilen, 0 - vi skriver ikke noe
  • tech SIP/PJSIP/IAX/etc
  • authToken — Bitrix24-autorisasjonstoken, utgående webhook-autorisasjonskode
  • bitrixApiUrl — URL til den innkommende webhook, uten profil/
  • utvidelser — liste over eksterne numre
  • kontekst — kontekst for samtaleoriginering
  • listener_timeout - hendelsesbehandlingshastighet fra stjerne
  • stjernen - en matrise med tilkoblingsinnstillingene til stjernen:
  • vert - IP eller vertsnavn for stjerneserveren
  • ordningen — koblingsskjema (tcp://, tls://)
  • havn - havn
  • brukernavn - Brukernavn
  • hemmelig - passord
  • connect_timeout - tidsavbrudd for tilkobling
  • read_timeout - les timeout

eksempel innstillingsfil:

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

);

Oppsett av veileder

Supervisor brukes til å starte Asterisk CallMeIn.php hendelsesbehandlerprosessen, som overvåker innkommende anrop og samhandler med Bitrix24 (vis kortet, skjul kortet osv.).

Innstillingsfil som skal opprettes:

/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

Starte og starte programmet på nytt:

supervisorctl start callme
supervisorctl restart callme

se status for applikasjonen:

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

Konklusjon

Det viste seg ganske vanskelig, men jeg er sikker på at en erfaren administrator vil være i stand til å implementere og glede brukerne sine.

Som lovet, lenke til github.

Spørsmål, forslag - vennligst i kommentarene. Også, hvis du er interessert i hvordan utviklingen av denne integrasjonen gikk, skriv, og i neste artikkel vil jeg prøve å avsløre alt mer detaljert.

Kilde: www.habr.com

Legg til en kommentar