Integracija Asterisk in Bitrix24

Integracija Asterisk in Bitrix24
V omrežju obstajajo različne možnosti integracije IP-ATK Asterisk in CRM Bitrix24, vendar smo se vseeno odločili napisati svojo.

Funkcionalnost je povsem standardna:

  • S klikom na povezavo s telefonsko številko stranke v Bitrix24, Asterisk poveže notranjo številko uporabnika, s katerega je bil ta klik izveden, s telefonsko številko stranke. V Bitrix24 se zabeleži zapis o klicu in ob koncu klica se prikliče zapis pogovora.
  • Na Asterisk prejme klic od zunaj – v vmesniku Bitrix24 prikažemo kartico stranke tistemu zaposlenemu, na katerega številko je ta klic prišel.
    Če takšne stranke ni, odpremo kartico za ustvarjanje novega lead-a.
    Ko je klic končan, to odražamo na kartici in prikličejo se zapisi pogovora.

Podrobneje bom opisal, kako vse nastaviti pri sebi in dal povezavo na github – da-da, vzemite in uporabljajte!

Splošni opis

Svojo integracijo smo poimenovali CallMe. CallMe je majhna spletna aplikacija, napisana v PHP.

Uporabljene tehnologije in storitve

  • PHP 5.6
  • PHP AMI knjižnica
  • Composer
  • Nginx + php-fpm
  • supervisor
  • AMI (Asterisk Manager Interface)
  • Bitrix Webhooki (poenostavljena realizacija REST API)

Predhodna nastavitev

Na strežniku z Asterisk je potrebno namestiti spletni strežnik (pri nas je to nginx+php-fpm), supervisor in git.

Ukaz za namestitev (CentOS):

yum install nginx php-fpm supervisor git

Premaknemo se v direktorij, ki je dostopen spletnemu strežniku, potegnemo iz gita aplikacijo in postavimo ustrezna dovoljenja za mapo:


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

Nato nastavimo nginx, naš konfiguracijski datoteka se nahaja v

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

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

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


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

    listen 443 ssl http2;
    server_name pbx.vistep.si;
    resolver 8.8.8.8;
    ssl_stapling on;
    ssl on;
    ssl_certificate /etc/letsencrypt/live/pbx.vistep.si/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/pbx.vistep.si/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; # prepovedano za skrite datoteke
        }

        location ~* /(?:uploads|files)/.*.php$ {
                deny all; # prepovedano za naložene skripte
        }

        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; # predpomnjenje statike
        }

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

Razlaga konfiguracije, vprašanja varnosti, pridobitev certifikata in celo izbira spletnega strežnika ostajajo zunaj okvira tega članka — o tem je že veliko napisanega. Aplikacija nima omejitev, deluje tako po http kot po https.

Imamo https, certifikat Let's Encrypt.

Če ste vse pravilno naredili, bi ob prehodu na povezavo morali videti nekaj podobnega.

Integracija Asterisk in Bitrix24

Nastavitev Bitrix24.

Ustvarimo dva spletna vhoda.

Vhodni spletni vhod.

Pod uporabniškim računom skrbnika (s id 1) gremo po poti: Aplikacije -> Spletni vhodi -> Dodaj spletni vhod -> Vhodni spletni vhod.

Integracija Asterisk in Bitrix24

Izpolnimo parametre vhodnega spletnega vhoda, kot je prikazano na screenih:

Integracija Asterisk in Bitrix24

Integracija Asterisk in Bitrix24

In pritisnemo shraniti.

Po shranjevanju bo Bitrix24 zagotovil URL vhodnega spletnega vhoda, na primer:

Integracija Asterisk in Bitrix24

Shrani si različico URL brez zaključnega /profile/ — ta se bo uporabljala v aplikaciji za delo z vhodnimi klici.

To je moje. https://b24-xsynia.bitrix24.ru/rest/1/7eh61lh8pahw0fwt/

Izhodni spletni vhod.

Aplikacije -> Spletni vhodi -> Dodaj spletni vhod -> Izhodni spletni vhod.

Podrobnosti znova na screenih:

Integracija Asterisk in Bitrix24

Integracija Asterisk in Bitrix24

Shranjujemo in pridobimo avtentikacijsko kodo.

Integracija Asterisk in Bitrix24

To je moje. xcrp2ylhzzd2v43cmfjqmkvrgrcbkni6. To je treba prav tako kopirati, potrebna bo za izvajanje odhodnih klicev.

Důležité!

Na strežniku Bitrix24 mora biti nastavljen ssl-certifikat (lahko uporabite letsencrypt), sicer API Bitrixa ne bo deloval. Če imate oblačno različico, se lahko ne obremenjujete — tam je že ssl.

Důležité!

V polju „Naslov obdelovalca“ mora biti naveden naslov, dostopen iz interneta!

In kot zadnji korak bomo naš CallMeOut nastavili kot aplikacijo za klicanje (da ob kliknjenju na številko pošlje ukaz za izvor klica na ATE).

V meniju izberite: Več -> Telefonija -> Več -> Nastavitve, v „Številka za odhodni klic po privzetku“ izberite Aplikacija: CallMeOut in pritisnite „Shrani“

Integracija Asterisk in Bitrix24

Nastavitev asteriska

Za uspešno sodelovanje Asteriska in Bitrix24 moramo dodati AMI-uporabnika callme v 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

Nato je nekaj zvijač, ki jih bo treba uvesti preko dialplana (to so pri nas extensions.ael).

Pripravljen je celoten datoteka, nato pa bom dal razlago:

globals {
    WAV=\/var\/www\/pbx.vistep.ru\/callme\/records\/wav; \/\/Začasni katalog sa WAV
    MP3=\/var\/www\/pbx.vistep.ru\/callme\/records\/mp3; \/\/Kamo se izvoze mp3 datoteke
    URLRECORDS=https:\/\/pbx.vistep.ru\/callme\/records\/mp3;
    RECORDING=1; \/\/ Snimanje, 1 - uključeno.
};

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()); \/\/ postavljamo CallerID ako smo ga saznali iz 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 već je postavljen ===));  
}

}


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

};

Počnimo od samog početka: direktiva globals.

Promenljiva URLRECORDS sadrži URL do datoteka sa snimcima razgovora, na kojem će Bitrix24 povlačiti u karticu kontakta.

Zatim nam je zanimljiv makro recording.

Ovde, osim snimanja razgovora, postavićemo promenljivu FullFname.

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

Ona čuva pun URL do konkretne datoteke (makro se poziva svuda).

Analizirajmo odlazni poziv:

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

Recimo, če kličemo na 89991234567, najprej prispemo sem:

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

t.j. aktiviramo makro za snemanje klica in nastavimo potrebne spremenljivke.

Naprej

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

zabeležemo, kdo je iniciiral klic in zabeležemo čas začetka klica.

In ob njegovem zaključku, v posebnem kontekstu 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});
}

izklopimo snemanje v CDR tabeli za to ekstenzijo (ne potrebujemo ga tam), nastavimo čas zaključka klica, izračunamo trajanje, če je rezultat klica neznan — nastavimo (spremenljivka CallMeDISPOSITION) in, zadnji korak, pošljemo vse bitrixu preko sistemskega curl.

In še malo magije — prihajajoči klic:

888999 => {
	&recording(${CALLERID(number)},${EXTEN});
        Answer();
        ExecIF(${CallMeCallerIDName}?Set(CALLERID(name)=${CallMeCallerIDName}):NoOp()); // nastavimo CallerID, če smo ga izvedeli iz Bitrix24
        Set(CallStart=${STRFTIME(epoch,,%s)}); // začnemo meriti čas klica
        Queue(Q1,tT);
        Set(CallMeDISPOSITION=${CDR(disposition)}); 
        Hangup();
        }

Tukaj nas zanima le ena vrstica.

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

To pravi ATS-u, da nastavi CallerID(name) na spremenljivko CallMeCallerIDName.

Sama spremenljivka CallMeCallerIDName se nastavitev z aplikacijo CallMe (če je v Bitrix24 zapisano ime in priimek za številko klicatelja — nastavimo kot CallerID(name), če ne — ne bomo naredili nič).

Nastavitev aplikacije

Datoteka s configurarcia aplikacije — /var/www/pbx.vistep.ru/config.php

Opis parametrov aplikacije:

  • CallMeDEBUG — če je 1, se v dnevnik zapisujejo vsi dogodki, ki jih obdeluje aplikacija, 0 — nič ne pišemo
  • tech — SIP/PJSIP/IAX/itd.
  • authToken — Bitrix24 authorization token, outgoing webhook authorization code
  • bitrixApiUrl — Incoming webhook URL, without profile/
  • extentions — List of external numbers
  • context — Context for call origination
  • listener_timeout — Event processing speed from Asterisk
  • asterisk — Array with connection settings for Asterisk:
  • host — IP or hostname of the Asterisk server
  • scheme — Connection scheme (tcp://, tls://)
  • port — Port
  • username — Username
  • secret — Password
  • connect_timeout — Connection timeout
  • read_timeout — Read timeout

Example of configuration file:

 1, // Debug messages in the log: 1 - write, 0 - do not write
        'tech' => 'SIP',
        'authToken' => 'xcrp2ylhzzd2v43cmfjqmkvrgrcbkni6', // Bitrix authorization token
        'bitrixApiUrl' => 'https://b24-xsynia.bitrix24.ru/rest/1/7eh61lh8pahw0fwt/', // API URL of Bitrix (incoming webhook)
        'extentions' => array('888999'), // List of external numbers, comma separated
        'context' => 'dial_out', // Outgoing context for call origination
        'asterisk' => array( // Settings for Asterisk connection
                    'host' => '10.100.111.249',
                    'scheme' => 'tcp://',
                    'port' => 5038,
                    'username' => 'callme',
                    'secret' => 'JD3clEB8_f23r-3ry84gJ',
                    'connect_timeout' => 10000,
                    'read_timeout' => 10000
                ),
        'listener_timeout' => 300, // Event processing speed from Asterisk

);

Configuring Supervisor

Supervisor is used to run the event handler process CallMeIn.php, which monitors incoming calls and interacts with Bitrix24 (show card, hide card, etc.).

Configuration file to be created:

/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

Starting and restarting the application:

supervisorctl start callme
supervisorctl restart callme

Viewing application status:

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

Zaključek

It has become quite challenging, but I am sure — an experienced administrator will be able to implement this and delight their users.

As promised, link to GitHub.

Questions, suggestions — please leave a comment. Also, if you're interested in how the development of this integration went, write to me, and in the next article, I will try to reveal everything in more detail.

Izvor: habr.com

Kupite zanesljivo gostovanje za spletne strani z zaščito pred DDoS, VPS VDS strežniki 🔥 Kupite zanesljivo gostovanje za spletne strani z zaščito pred DDoS, VPS VDS strežniki | ProHoster