Integrace Asterisk a Bitrix24

Integrace Asterisk a Bitrix24
Na internetu existuje několik variant integrace IP-ATC Asterisk a CRM Bitrix24, ale my jsme se i tak rozhodli napsat vlastní.

Funkcionalita je standardní:

  • Kliknutím na odkaz s telefonním číslem zákazníka v Bitrix24 Asterisk připojí interní číslo uživatele, jehož jménem bylo kliknutí provedeno, s telefonním číslem zákazníka. V Bitrix24 se zaznamená záznam o hovoru a po skončení hovoru se načte záznam konverzace.
  • Na Asterisk přijde hovor zvenčí — v rozhraní Bitrix24 zobrazíme kartu zákazníka tomu zaměstnanci, na jehož číslo tento hovor přišel.
    Pokud takový zákazník neexistuje, otevřeme kartu pro vytvoření nového leadu.
    Jakmile je hovor ukončen, odrazíme to v kartě a načteme záznam konverzace.

Pod článkem vysvětlím, jak vše nastavit a poskytnu odkaz na github — ano, vezměte si to a používejte!

Obecný popis

Naši integraci jsme nazvali CallMe. CallMe je malá webová aplikace napsaná v PHP.

Použité technologie a služby

  • PHP 5.6
  • PHP AMI-knihovna
  • Composer
  • Nginx + php-fpm
  • supervisor
  • AMI (Asterisk Manager Interface)
  • Webhooky Bitrix (zjednodušená implementace REST API)

Předběžné nastavení

Na serveru s Asterisk je potřeba nainstalovat webový server (u nás nginx+php-fpm), supervisor a git.

Příkaz pro instalaci (CentOS):

yum install nginx php-fpm supervisor git

Přejdeme do adresáře dostupného webovému serveru, stáhneme aplikaci z gitu a nastavíme potřebná práva na složku:


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

Poté nakonfigurujeme nginx, náš konfigurační soubor se nachází v

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

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

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


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

    listen 443 ssl http2;
    server_name pbx.vistep.cz;
    resolver 8.8.8.8;
    ssl_stapling on;
    ssl on;
    ssl_certificate /etc/letsencrypt/live/pbx.vistep.cz/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/pbx.vistep.cz/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; # zákaz skrytých souborů
        }

        location ~* /(?:uploads|files)/.*.php$ {
                deny all; # zákaz nahraných skriptů
        }

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

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

Analýzu konfigurace, otázky zabezpečení, získání certifikátu a dokonce výběr webového serveru ponechám stranou článku — o tom bylo napsáno mnoho. Aplikace nemá žádná omezení, funguje jak po http, tak po https.

Máme https, certifikát let’s encrypt.

Pokud jste vše udělali správně, přechodem na odkaz byste měli vidět něco podobného

Integrace Asterisk a Bitrix24

Nastavení Bitrix24

Vytvoříme dva webhooks.

Příchozí webhook.

Pod uživatelským účtem administrátora (s id 1) jdeme cestou: Aplikace -> Webhooky -> Přidat webhook -> Příchozí webhook

Integrace Asterisk a Bitrix24

Vyplňujeme parametry příchozího webhooku podle snímků:

Integrace Asterisk a Bitrix24

Integrace Asterisk a Bitrix24

A klikneme na uložit.

Po uložení Bitrix24 poskytne URL příchozího webhooku, například:

Integrace Asterisk a Bitrix24

Uložte si svůj variant URL bez koncového /profile/ — bude použit v aplikaci pro práci s příchozími hovory.

Mně to je https://b24-xsynia.bitrix24.ru/rest/1/7eh61lh8pahw0fwt/

Odchozí webhook.

Aplikace -> Webhooky -> Přidat webhook -> Odchozí webhook

Podrobnosti znovu na snímcích:

Integrace Asterisk a Bitrix24

Integrace Asterisk a Bitrix24

Uložíme a získáme autorizační kód

Integrace Asterisk a Bitrix24

Mně to je xcrp2ylhzzd2v43cmfjqmkvrgrcbkni6. Jeho také musíte zkopírovat, je potřeba k uskutečnění odchozích hovorů.

Důležité!

Na serveru Bitrix24 by měl být nastaven ssl-certifikát (můžete použít letsencrypt), jinak API Bitrixu nebude fungovat. Pokud máte cloudovou verzi, nemusíte se obávat — tam už ssl je.

Důležité!

V poli „Adresa handlera“ musí být uvedena adresa přístupná z internetu!

A jako poslední krok nastavíme naši aplikaci CallMeOut pro uskutečňování hovorů (aby při kliknutí na číslo na PBX byla odeslána zpráva pro iniciaci hovoru).

V menu vybíráme: Další -> Telefonie -> Další -> Nastavení, v „Čísle pro odchozí hovor podle předvoleného nastavení“ vybíráme Aplikaci: CallMeOut a klikneme na „Uložit“

Integrace Asterisk a Bitrix24

Nastavení Asterisk

Pro úspěšnou interakci mezi Asteriskem a Bitrix24 musíme přidat uživatele AMI 'callme' do 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

Dále existuje několik triků, které bude třeba implementovat prostřednictvím dialplanu (u nás to je extensions.ael).

Uvádím celý soubor a poté poskytnu vysvětlení:

globals {
    WAV=\/var\/www\/pbx.vistep.ru\/callme\/records\/wav; \/\/Dočasný adresář pro WAV
    MP3=\/var\/www\/pbx.vistep.ru\/callme\/records\/mp3; \/\/Kde ukládat mp3 soubory
    URLRECORDS=https:\/\/pbx.vistep.ru\/callme\/records\/mp3;
    RECORDING=1; \/\/ Nahrávání, 1 - zapnuto.
};

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()); \/\/ nastavujeme CallerID pokud jsme ho zjistili z 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 již byla nastavena ===));  
}

}


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

};

Začneme od začátku: direktiva globals.

Proměnná URLRECORDS uchovává URL k souborům záznamů hovorů, podle které je Bitrix24 načte do karty kontaktu.

Dále nás zajímá makro recording.

Zde, kromě nahrávání hovorů, nastavíme proměnnou FullFname.

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

Ukládá plné URL k konkrétnímu souboru (makro je voláno všude).

Analyzujme odchozí hovor:

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

Předpokládejme, že voláme na 89991234567, nejprve se dostaneme sem:

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

t.j. vyvolá se makro pro nahrávání hovoru a nastaví se potřebné proměnné.

Dále

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

Zaznamenáváme, kdo inicioval hovor a zaznamenáváme čas zahájení hovoru.

A po jeho dokončení v speciálním kontextu 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});
}

Vypínáme zápis do tabulky CDR pro tento rozšíření (není to potřeba), nastavíme čas ukončení hovoru, vypočítáme dobu trvání, pokud není výsledkem hovoru známo — nastavíme (proměnná CallMeDISPOSITION) a jako poslední krok posíláme všechno Bitrixu přes systémový curl.

A ještě trochu magie — příchozí hovor:

888999 => {
	&recording(${CALLERID(number)},${EXTEN});
        Answer();
        ExecIF(${CallMeCallerIDName}?Set(CALLERID(name)=${CallMeCallerIDName}):NoOp()); // nastavíme CallerID, pokud jsme ho zjistili v Bitrix24
        Set(CallStart=${STRFTIME(epoch,,%s)}); // začínáme odpočítávání času hovoru
        Queue(Q1,tT);
        Set(CallMeDISPOSITION=${CDR(disposition)}); 
        Hangup();
        }

Zde nás zajímá pouze jeden řádek.

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

Ona říká AÚS nastavit CallerID(name) rovnající se proměnné CallMeCallerIDName.

Samotná proměnná CallMeCallerIDName se na druhou stranu nastavuje aplikací CallMe (pokud je v Bitrix24 známo jméno pro číslo volajícího — nastavíme to jako CallerID(name), pokud ne — nic nebudeme dělat).

Nastavení aplikace

Nastavení souboru aplikace — /var/www/pbx.vistep.ru/config.php

Popis parametrů aplikace:

  • CallMeDEBUG — pokud 1, pak se do log souboru zapíší všechny události zpracovávané aplikací, 0 — nic nepíšeme
  • tech — SIP/PJSIP/IAX/atd.
  • authToken — autorizační token Bitrix24, kód autorizace odchozího webhooku
  • bitrixApiUrl — URL příchozího webhooku, bez profile/
  • extentions — seznam externích čísel
  • context — kontext pro initiaci hovoru
  • listener_timeout — rychlost zpracování událostí od Asterisku
  • asterisk — pole s nastavením připojení k Asterisk:
  • host — ip nebo hostname serveru Asterisk
  • scheme — schéma připojení (tcp://, tls://)
  • port — port
  • uživatelské jméno — uživatelské jméno
  • secret — heslo
  • connect_timeout — časový limit připojení
  • read_timeout — časový limit pro čtení

příklad konfiguračního souboru:

 1, // debug zprávy v logu: 1 - zapisujeme, 0 - nezapisujeme
        'tech' => 'SIP',
        'authToken' => 'xcrp2ylhzzd2v43cmfjqmkvrgrcbkni6', // autorizační token Bitrixu
        'bitrixApiUrl' => 'https://b24-xsynia.bitrix24.ru/rest/1/7eh61lh8pahw0fwt/', //url k api Bitrixu (příchozí webhook)
        'extentions' => array('888999'), // seznam externích čísel, oddělených čárkou
        'context' => 'dial_out', // odchozí kontext pro initiaci hovoru
        'asterisk' => array( // nastavení pro připojení k Asterisku
                    'host' => '10.100.111.249',
                    'scheme' => 'tcp://',
                    'port' => 5038,
                    'username' => 'callme',
                    'secret' => 'JD3clEB8_f23r-3ry84gJ',
                    'connect_timeout' => 10000,
                    'read_timeout' => 10000
                ),
        'listener_timeout' => 300, // rychlost zpracování událostí od Asterisku

);

Nastavení supervisor

Supervisor slouží k spuštění procesu zpracovatele událostí z Asterisk CallMeIn.php, který sleduje příchozí hovory a interaguje s Bitrix24 (zobrazení karty, skrytí karty atd.).

Konfigurační soubor, který je třeba vytvořit:

/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

Spuštění a restart aplikace:

supervisorctl start callme
supervisorctl restart callme

kontrola stavu aplikace:

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

Závěr

Stalo se to dost složité, ale jsem si jistý, že zkušený administrátor to dokáže implementovat a potěšit své uživatele.

Jak jsem slíbil, odkaz na GitHub.

Dotazy, přání — prosím do komentářů. Také pokud vás zajímá, jak probíhal vývoj této integrace, dejte vědět, a v příštím článku se pokusím vše podrobněji rozebrat.

Zdroj: habr.com

Koupit spolehlivý hosting pro webové stránky s ochranou proti DDoS, VPS VDS servery 🔥 Koupit spolehlivý hosting pro webové stránky s ochranou proti DDoS, VPS VDS servery | ProHoster