
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
- 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 gitGÄ 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.confserver {
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.

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

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


Og klikk pÄ lagre.
Etter lagring vil Bitrix24 gi deg URL-en for den inngÄende webhooken, for eksempel:

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:


Lagre og fÄ autorisasjonskoden

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»

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.logStart og restart av applikasjonen:
supervisorctl start callme
supervisorctl restart callmese statusen til applikasjonen:
supervisorctl status callme
callme RUNNING pid 11729, uptime 17 days, 16:58:07Konklusjon
Det ble ganske komplisert, men jeg er sikker pÄ at en erfaren administrator vil kunne implementere dette og glede sine brukere.
Som lovet, .
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
