Integrácia Asterisk a Bitrix24

Integrácia Asterisk a Bitrix24
Existujú rôzne možnosti integrácie IP-PBX Asterisk a CRM Bitrix24 v sieti, ale aj tak sme sa rozhodli napísať si vlastnú.

Z hľadiska funkčnosti je všetko štandardné:

  • Kliknutím na odkaz s telefónnym číslom klienta v Bitrix24 Asterisk spojí interné číslo používateľa, v mene ktorého bolo kliknutie uskutočnené, s telefónnym číslom klienta. V Bitrix24 sa nahrá záznam hovoru a na konci hovoru sa vytiahne nahrávka konverzácie.
  • Asterisk prijme hovor zvonku - v rozhraní Bitrix24 ukážeme klientsku kartu zamestnancovi, na číslo ktorého tento hovor prišiel.
    Ak takýto klient neexistuje, otvoríme kartu na vytvorenie nového potenciálneho zákazníka.
    Akonáhle je hovor ukončený, premietneme to na kartu a vytiahneme záznam rozhovoru.

Pod strihom vám poviem, ako si všetko nastaviť pre seba, a dám vám odkaz na github - áno, áno, vezmite si ho a používajte ho!

Všeobecný opis

Našu integráciu sme nazvali CallMe. CallMe je malá webová aplikácia napísaná v PHP.

Použité technológie a služby

  • PHP 5.6
  • PHP knižnica AMI
  • Skladať
  • Nginx + php-fpm
  • vedúci
  • AMI (rozhranie správcu hviezdičky)
  • Webhooky Bitrix (zjednodušená implementácia REST API)

prednastavenie

Na server s Asteriskom potrebujete nainštalovať webový server (u nás je to nginx+php-fpm), supervízor a git.

Inštalačný príkaz (CentOS):

yum install nginx php-fpm supervisor git

Prejdeme do adresára prístupného pre webový server, stiahneme aplikáciu z Git a nastavíme potrebné práva na priečinok:


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

Ďalej nakonfigurujme nginx, v ktorom sa nachádza naša konfigurácia

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

Rozoberanie konfigurácie, bezpečnostné problémy, získanie certifikátu a dokonca výber webového servera ponechám mimo rozsahu článku - o tom sa už veľa napísalo. Aplikácia nemá žiadne obmedzenia, funguje cez http aj https.

Používame https, zašifrujeme certifikát.

Ak ste urobili všetko správne, kliknutím na odkaz by ste mali vidieť niečo také

Integrácia Asterisk a Bitrix24

Konfigurácia Bitrix24

Vytvorme dva webhooky.

Prichádzajúci webhook.

Pod účtom správcu (s ID 1) postupujte podľa cesty: Aplikácie -> Webhooky -> Pridať webhook -> Prichádzajúci webhook

Integrácia Asterisk a Bitrix24

Vyplňte parametre prichádzajúceho webhooku ako na snímkach obrazovky:

Integrácia Asterisk a Bitrix24

Integrácia Asterisk a Bitrix24

A kliknite na uložiť.

Po uložení Bitrix24 poskytne URL prichádzajúceho webhooku, napríklad:

Integrácia Asterisk a Bitrix24

Uložte si svoju verziu URL bez koncového /profilu/ – bude slúžiť v aplikácii na prácu s prichádzajúcimi hovormi.

mám toto https://b24-xsynia.bitrix24.ru/rest/1/7eh61lh8pahw0fwt/

Odchádzajúce webhook.

Aplikácie -> Webhooky -> Pridať webhook -> Odchádzajúci webhook

Podrobnosti sú opäť na snímkach obrazovky:

Integrácia Asterisk a Bitrix24

Integrácia Asterisk a Bitrix24

Uložte a prijmite autorizačný kód

Integrácia Asterisk a Bitrix24

mám toto xcrp2ylhzzd2v43cmfjqmkvrgrcbkni6. Musíte si ho skopírovať aj pre seba, potrebujete ho na uskutočňovanie odchádzajúcich hovorov.

Dôležité!

Certifikát SSL musí byť nakonfigurovaný na serveri Bitrix24 (môžete použiť letsencrypt), inak Bitrix api nebude fungovať. Ak máte cloudovú verziu, nebojte sa – už má ssl.

Dôležité!

Pole „Adresa procesora“ musí obsahovať adresu prístupnú z internetu!

A na záver si nainštalujte náš CallMeOut ako aplikáciu na telefonovanie (aby po kliknutí na číslo na PBX odletel príkaz na uskutočnenie hovoru).

V ponuke vyberte: Viac -> Telefonovanie -> Viac -> Nastavenia, nastavte v časti „Predvolené číslo pre odchádzajúci hovor“ Aplikácia: CallMeOut a kliknite na „Uložiť“

Integrácia Asterisk a Bitrix24

Nastavuje sa hviezdička

Pre úspešnú interakciu medzi Asteriskom a Bitrix24 musíme pridať AMI user 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

Ďalej je tu niekoľko trikov, ktoré bude potrebné implementovať cez dialplan (pre nás je to extensions.ael).

Poskytnem celý súbor a potom poskytnem vysvetlenie:

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

};

Začnime od začiatku: smernica globals.

Variabilné URLRECORDS ukladá URL k súborom so záznamom konverzácie, podľa ktorých ich Bitrix24 natiahne na kartu kontaktu.

Ďalej nás zaujíma makro makro záznam.

Tu okrem nahrávania rozhovorov nastavíme premennú FullFname.

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

Ukladá celú URL do konkrétneho súboru (makro sa volá všade).

Poďme analyzovať odchádzajúci 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});
}

Povedzme, že zavoláme na číslo 89991234567, najprv sa dostaneme sem:

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

tie. Zavolá sa makro nahrávania konverzácie a nastavia sa potrebné premenné.

Ďalšie

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

Zaznamenávame, kto inicioval hovor, a zaznamenávame čas začiatku hovoru.

A po jeho dokončení v osobitnom kontexte 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});
}

zakázať vstup do CDR tabuľky pre toto rozšírenie (tam to nie je potrebné), nastaviť čas ukončenia hovoru, vypočítať trvanie, ak výsledok hovoru nie je známy - nastaviť (premenná Zavolajte MeDISPOSITION) a v poslednom kroku odošlite všetko do Bitrixu cez systémový curl.

A ešte trochu kúzla - prichádzajúci hovor:

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

Tu nás zaujíma iba jeden riadok.

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

Povie PBX, aby sa nainštalovala ID volajúceho (meno) rovná sa premennej CallMeCallerIDName.

Samotnú premennú CallMeCallerIDName zase nastavuje aplikácia CallMe (ak má Bitrix24 celé meno pre číslo volajúceho, nastavte ho ako ID volajúceho (meno), nie - neurobíme nič).

Nastavenie aplikácie

Súbor s nastaveniami aplikácie - /var/www/pbx.vistep.ru/config.php

Popis parametrov aplikácie:

  • CallMeDEBUG — ak 1, všetky udalosti spracované aplikáciou sa zapíšu do log súboru, 0 — nezapisujeme nič
  • tech - SIP/PJSIP/IAX/atď
  • authToken — Autorizačný token Bitrix24, odchádzajúci autorizačný kód webhooku
  • bitrixApiUrl — URL prichádzajúceho webhooku, bez profilu/
  • rozšírenia — zoznam externých čísel
  • kontext — kontext pre začatie hovoru
  • listener_timeout — rýchlosť spracovania udalosti od hviezdičky
  • hviezdička — pole s nastaveniami na pripojenie k hviezdičke:
  • hostiteľ — IP alebo názov hostiteľa servera s hviezdičkou
  • systém — schéma pripojenia (tcp://, tls://)
  • prístav - prístav
  • meno - Používateľské meno
  • tajomstvo - heslo
  • connect_timeout - spojenie vypršalo
  • read_timeout - časový limit čítania

príklad súboru nastavení:

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

);

Nastavenie supervízora

Supervisor sa používa na spustenie procesu obsluhy udalostí z Asterisk CallMeIn.php, ktorý monitoruje prichádzajúce hovory a interaguje s Bitrix24 (zobraziť kartu, skryť kartu atď.).

Súbor nastavení, ktorý sa má vytvoriť:

/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

Spustite a reštartujte aplikáciu:

supervisorctl start callme
supervisorctl restart callme

Zobrazenie prevádzkového stavu aplikácie:

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

Záver

Ukázalo sa, že je to dosť komplikované, ale som si istý, že skúsený správca to dokáže implementovať a potešiť svojich používateľov.

Ako bolo sľúbené, odkaz na github.

Otázky, návrhy - nechajte ich v komentároch. Taktiež ak vás zaujíma, ako prebiehal vývoj tejto integrácie, napíšte a v ďalšom článku sa pokúsim všetko odhaliť podrobnejšie.

Zdroj: hab.com

Pridať komentár