Integrering av Asterisk og Bitrix24

Integrering av Asterisk og Bitrix24
Det finnes ulike alternativer for integrering av IP-PBX Asterisk og CRM Bitrix24, men vi har likevel besluttet Ä utvikle vÄr egen.

Funksjonaliteten er ganske standard:

  • Ved Ă„ klikke pĂ„ linken med kundens telefonnummer i Bitrix24, kobler Asterisk brukerens interne nummer, som klikket ble gjort fra, med kundens telefonnummer. I Bitrix24 registreres samtalen, og samtalelogg hentes inn etter avsluttet samtale.
  • En samtale fra utsiden kommer til Asterisk — i Bitrix24 viser vi kundens kort til den ansatte som mottok samtalen.
    Hvis det ikke finnes en slik kunde, Äpner vi kortet for Ä opprette et nytt lead.
    SĂ„ snart samtalen er avsluttet, oppdaterer vi kortet og henter inn samtalelogg.

Under finner du hvordan du kan sette opp alt selv, samt en lenke til github — ja, ja, ta det med og bruk det!

Generell beskrivelse

Vi har kalt vÄr integrasjon CallMe. CallMe er en liten webapplikasjon skrevet i PHP.

Brukte teknologier og tjenester

  • PHP 5.6
  • PHP AMI-bibliotek
  • Composer
  • Nginx + php-fpm
  • supervisor
  • AMI (Asterisk Manager Interface)
  • Bitrix webhooks (forenklet REST API-implementering)

FĂžrste innstilling

PÄ serveren med Asterisk mÄ vi installere webserver (vi bruker nginx+php-fpm), supervisor og git.

Kommando for installasjon (CentOS):

yum install nginx php-fpm supervisor git

GÄ til mappen som er tilgjengelig for webserveren, hent applikasjonen fra git og sett de nÞdvendige rettighetene pÄ mappen:


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

Videre konfigurerer vi nginx, konfigurasjonen vÄr ligger i

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

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

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


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

    listen 443 ssl http2;
    server_name pbx.vistep.nn;
    resolver 8.8.8.8;
    ssl_stapling on;
    ssl on;
    ssl_certificate /etc/letsencrypt/live/pbx.vistep.nn/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/pbx.vistep.nn/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; # for hidden files
        }

        location ~* /(?:uploads|files)/.*.php$ {
                deny all; # for uploaded scripts
        }

        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; # static caching
        }

	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 kommer ikke til Ă„ dekke konfigurasjonsanalyse, sikkerhetsspĂžrsmĂ„l, sertifikatinnhenting eller valg av webserver — dette er mye skrevet om. Applikasjonen har ingen begrensninger, den fungerer bĂ„de med http og https.

Vi bruker https, let’s encrypt-sertifikatet.

Hvis du har gjort alt riktig, skal du se noe liknende nÄr du klikker pÄ lenken.

Integrering av Asterisk og Bitrix24

Innstilling av Bitrix24

Vi oppretter to webhooks.

InngÄende webhook.

Som administrator (med id 1) gÄr vi til: Applikasjoner -> Webhooks -> Legg til webhook -> InngÄende webhook

Integrering av Asterisk og Bitrix24

Fyll inn parameterne for den inngÄende webhooken som pÄ skjermbildene:

Integrering av Asterisk og Bitrix24

Integrering av Asterisk og Bitrix24

Og klikk pÄ lagre.

Etter lagring vil Bitrix24 gi deg URL-en for den inngÄende webhooken, for eksempel:

Integrering av Asterisk og Bitrix24

Lagre din versjon av URL-en uten den avsluttende /profile/ — den vil bli brukt i applikasjonen for Ă„ hĂ„ndtere inngĂ„ende samtaler.

Jeg har dette https://b24-xsynia.bitrix24.ru/rest/1/7eh61lh8pahw0fwt/

UtgÄende webhook.

Applikasjoner -> Webhooks -> Legg til webhook -> UtgÄende webhook

Detaljer igjen pÄ skjermbildene:

Integrering av Asterisk og Bitrix24

Integrering av Asterisk og Bitrix24

Lagre og fÄ autorisasjonskoden

Integrering av Asterisk og Bitrix24

Jeg har dette xcrp2ylhzzd2v43cmfjqmkvrgrcbkni6. Denne mÄ ogsÄ kopieres, da den er nÞdvendig for Ä foreta utgÄende samtaler.

Viktig!

PÄ Bitrix24-serveren mÄ SSL-sertifikatet vÊre konfigurert (letsencrypt kan brukes), ellers vil Bitrix API ikke fungere. Hvis du har skyversjonen, trenger du ikke Ä bekymre deg - den har allerede SSL.

Viktig!

I feltet «Adresse til behandler» mÄ en offentlig tilgjengelig adresse fra internett vÊre angitt!

Som det siste steget installerer vi CallMeOut som en app for Ä ringe (slik at det sendes en kommando for Ä initiere samtalen ved Ä klikke pÄ nummeret i PBX-en).

I menyen velger vi: Mer -> Telefoni -> Mer -> Innstillinger, og setter i «Nummer for standard utgÄende samtale» App: CallMeOut, og klikker «Lagre»

Integrering av Asterisk og Bitrix24

Konfigurere Asterisk

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

Videre er det flere triks som mÄ implementeres gjennom dialplan (vi bruker extensions.ael).

Her er hele filen, og deretter vil jeg gi ytterligere forklaringer:

globals {
    WAV=\/var\/www\/pbx.vistep.ru\/callme\/records\/wav; \/\/Midlertidig katalog med WAV
    MP3=\/var\/www\/pbx.vistep.ru\/callme\/records\/mp3; \/\/Hvor mp3 filer skal lastes opp
    URLRECORDS=https:\/\/pbx.vistep.ru\/callme\/records\/mp3;
    RECORDING=1; \/\/ Innspilling, 1 - aktivert.
};

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()); \/\/ setter CallerID hvis vi kjenner det fra 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 allerede var satt ===));  
}

}


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

};

Vi begynner fra begynnelsen: direktivet globals.

Variabelen URLRECORDS lagrer URL-en til samtaleregnskapene, som Bitrix24 vil hente inn i kontaktkortet.

Neste er vi interessert i makroen recording.

Her, i tillegg til Ă„ ta opp samtaler, setter vi variabelen FullFname.

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

Den lagrer den fullstendige URL-en til den spesifikke filen (makroen blir kalt overalt).

La oss se pÄ utgÄende anrop:

_. => {
	&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 til 89991234567, sÄ havner vi fÞrst her:

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

Det vil si at makroen for opptak av samtalen blir kalt og nĂždvendige variabler settes.

Deretter

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

Vi registrerer hvem som initierte samtalen og lagrer starttiden for samtalen.

Og ved avslutningen vil det skje i en spesialkontekst 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});
}

Vi deaktiverer oppfĂžringen i CDR-tabellen for denne ekstensionen (det er ikke nĂždvendig der), setter tidspunktet for samtalens avslutning, beregner varigheten, og hvis resultatet av samtalen er ukjent, setter vi (variabel CallMeDISPOSITION) og som siste steg sender vi alt til Bitrix via systemcurl.

Og litt magi til – innkommende samtale:

888999 => {
	&recording(${CALLERID(number)},${EXTEN});
        Answer();
        ExecIF(${CallMeCallerIDName}?Set(CALLERID(name)=${CallMeCallerIDName}):NoOp()); // Setter CallerID hvis vi kjenner det fra Bitrix24
        Set(CallStart=${STRFTIME(epoch,,%s)}); // Starter tidtakingen for samtalen
        Queue(Q1,tT);
        Set(CallMeDISPOSITION=${CDR(disposition)});
        Hangup();
        }

Her er vi bare interessert i én linje.

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

Den ber PBX-en om Ă„ sette CallerID(name) lik variabelen CallMeCallerIDName.

Selve variabelen CallMeCallerIDName settes av CallMe-applikasjonen (hvis det finnes navn for nummeret som ringer i Bitrix24 - setter vi som CallerID(name), hvis ikke - gjĂžr vi ingenting).

Innstillinger for applikasjonen

Konfigurasjonsfilen for applikasjonen – /var/www/pbx.vistep.ru/config.php

Beskrivelse av applikasjonsparametrene:

  • CallMeDEBUG – hvis 1, vil alle hendelser behandlet av applikasjonen bli skrevet til loggfilen, 0 – ingenting skrives
  • tech – SIP/PJSIP/IAX/etc.
  • authToken — autentiseringstoken for Bitrix24, autorisasjonskode for utgĂ„ende webhook
  • bitrixApiUrl — URL for innkommende webhook, uten profile/
  • extentions — liste over eksterne numre
  • context — kontekst for oppringing
  • listener_timeout — hastighet pĂ„ behandlingen av hendelser fra Asterisk
  • Asterisk — matrise med innstillinger for tilkobling til Asterisk:
  • host — IP eller vertsnavn for Asterisk-serveren
  • scheme — tilkoblingsskjema (tcp://, tls://)
  • port — port
  • username — brukernavn
  • secret — passord
  • connect_timeout — tilkoblingstimeout
  • read_timeout — lesetidtimeout

eksempel pÄ konfigurasjonsfil:

 1, // debugmeldinger i loggen: 1 - skriver, 0 - skriver ikke
        'tech' => 'SIP',
        'authToken' => 'xcrp2ylhzzd2v43cmfjqmkvrgrcbkni6', // autentiseringstoken for Bitrix
        'bitrixApiUrl' => 'https://b24-xsynia.bitrix24.ru/rest/1/7eh61lh8pahw0fwt/', // URL til Bitrix API (innkommende webhook)
        'extentions' => array('888999'), // liste over eksterne numre, separert med komma
        'context' => 'dial_out', // utgÄende kontekst for oppringing
        'Asterisk' => array( // innstillinger for tilkobling til 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, // hastighet pÄ behandlingen av hendelser fra Asterisk

);

Konfigurere supervisor

Supervisor brukes til Ä starte prosessen som hÄndterer hendelser fra Asterisk CallMeIn.php, som overvÄker innkommende samtaler og interagerer med Bitrix24 (viser kort, skjuler kort osv.).

Konfigurasjonsfilen som mÄ 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

Start og restart av applikasjonen:

supervisorctl start callme
supervisorctl restart callme

se statusen til applikasjonen:

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

Konklusjon

Det ble ganske komplisert, men jeg er sikker pÄ at en erfaren administrator vil kunne implementere dette og glede sine brukere.

Som lovet, link til GitHub.

SpĂžrsmĂ„l, Ăžnsker — vennligst legg igjen kommentarer. Hvis du er interessert i hvordan utviklingen av denne integrasjonen foregikk, skriv til meg, sĂ„ vil jeg i en kommende artikkel prĂžve Ă„ utdype alt mer detaljert.

Kilde: habr.com

KjĂžp pĂ„litelig hosting for nettsteder med DDoS-beskyttelse, VPS VDS-servere đŸ”„ KjĂžp pĂ„litelig hosting for nettsteder med DDoS-beskyttelse, VPS VDS-servere | ProHoster