Integration av Asterisk och Bitrix24

Integration av Asterisk och Bitrix24
Nätverket har olika alternativ för att integrera IP-PBX Asterisk och CRM Bitrix24, men vi bestämde oss ändå för att skriva vårt eget.

Funktionellt är allt standard:

  • Genom att klicka på länken med kundens telefonnummer i Bitrix24 kopplar Asterisk det interna numret till den användare på uppdrag av vilken detta klick gjordes med kundens telefonnummer. I Bitrix24 spelas en registrering av samtalet in, och i slutet av samtalet dras konversationsposten upp.
  • Ett samtal kommer till Asterisk utifrån - i Bitrix24-gränssnittet visar vi klientkortet för den anställde till vars nummer detta samtal kom.
    Om det inte finns någon sådan klient, öppna kortet för att skapa en ny potentiell kund.
    Så fort samtalet är klart speglar vi detta i kortet och drar upp inspelningen av samtalet.

Under klippet ska jag berätta hur du ställer in allt för dig själv och ger en länk till github - ja, ja, ta den och använd den!

Allmän beskrivning

Vi kallade vår integration CallMe. CallMe är en liten webbapplikation skriven i PHP.

Använd teknik och tjänster

  • PHP 5.6
  • PHP AMI-bibliotek
  • Samman
  • nginx + php fpm
  • handledare
  • AMI (Asterisk Manager Interface)
  • Bitrix webhooks (förenklad implementering av REST API)

förinställning

På servern med Asterisk behöver du installera en webbserver (vi har nginx + php-fpm), supervisor och git.

Installationskommando (CentOS):

yum install nginx php-fpm supervisor git

Vi skickar katalogen som är tillgänglig till webbservern, drar applikationen från git och ställer in nödvändiga rättigheter till mappen:


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

Konfigurera sedan nginx, vår konfiguration finns i

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

Jag kommer att lämna analysen av konfigurationen, säkerhetsproblem, att skaffa ett certifikat och till och med välja en webbserver utanför artikelns ram - mycket har skrivits om detta. Applikationen har inga begränsningar, den fungerar på både http och https.

Vi har https, låt oss kryptera certifikat.

Om du gjorde allt korrekt, så bör du se något liknande detta genom att klicka på länken

Integration av Asterisk och Bitrix24

Konfigurera Bitrix24

Låt oss skapa två webhooks.

Inkommande webhook.

Under administratörskontot (med id 1) gå längs sökvägen: Applications -> Webhooks -> Add webhook -> Incoming webhook

Integration av Asterisk och Bitrix24

Fyll i parametrarna för den inkommande webhook som i skärmdumparna:

Integration av Asterisk och Bitrix24

Integration av Asterisk och Bitrix24

Och klicka på spara.

Efter att ha sparat kommer Bitrix24 att tillhandahålla webbadressen till den inkommande webhook, till exempel:

Integration av Asterisk och Bitrix24

Spara din version av URL:en utan den efterföljande /profilen/ - den kommer att användas i applikationen för att arbeta med inkommande samtal.

jag har det https://b24-xsynia.bitrix24.ru/rest/1/7eh61lh8pahw0fwt/

Utgående webhook.

Applikationer -> Webhooks -> Lägg till Webhook -> Utgående Webhook

Detaljer finns på skärmdumparna:

Integration av Asterisk och Bitrix24

Integration av Asterisk och Bitrix24

Spara och hämta auktoriseringskoden

Integration av Asterisk och Bitrix24

jag har det xcrp2ylhzzd2v43cmfjqmkvrgrcbkni6. Du behöver också kopiera den till dig själv, den behövs för att ringa utgående samtal.

Viktigt!

Ett ssl-certifikat måste konfigureras på Bitrix24-servern (du kan använda letsencrypt), annars fungerar inte BitrixXNUMX-api. Om du har en molnversion, oroa dig inte - ssl finns redan där.

Viktigt!

I fältet "Processorns adress" måste en adress som är tillgänglig från Internet anges!

Och med sista handen, låt oss installera vår CallMeOut som en applikation för att ringa samtal (så att genom att klicka på numret på telefonväxeln, kommer ett kommando att flyga för att starta samtalet).

I menyn väljer du: Mer -> Telefoni -> Mer -> Inställningar, ställ in på "Nummer för utgående samtal som standard" Applikation: CallMeOut och klicka på "Spara"

Integration av Asterisk och Bitrix24

asterisk inställning

För framgångsrik interaktion mellan Asterisk och Bitrix24 måste vi lägga till callme AMI-användaren till 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ärefter finns det några knep som kommer att behöva implementeras med hjälp av dialplan (vi har extensions.ael).

Jag kommer att citera hela filen, och sedan kommer jag att ge förklaringar:

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

};

Låt oss börja från början: direktiv Globals.

Variabel URLRECORDS lagrar URL:en till konversationsinspelningsfilerna, enligt vilken Bitrix24 drar in dem i kontaktkortet.

Därefter är vi intresserade av makro makro inspelning.

Här kommer vi, förutom att spela in konversationer, att ställa in variabeln FullFname.

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

Den lagrar hela URL:en till en specifik fil (makrot anropas överallt).

Låt oss analysera det utgående samtalet:

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

Låt oss säga att vi ringer 89991234567, det första vi får här:

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

de där. samtalsinspelningsmakrot anropas och de nödvändiga variablerna ställs in.

Nästa

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

vi spelar in vem som initierade samtalet och spelar in starttiden för samtalet.

Och när den är färdig, i ett speciellt sammanhang 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});
}

stäng av posten i CDR-tabellen för denna anknytning (det behövs inte där), ställ in sluttiden för samtalet, beräkna varaktigheten, om resultatet av samtalet inte är känt - ställ in (variabel Kalla mig DISPOSITION) och, det sista steget, skicka allt till Bitrix genom systemcurlen.

Och lite mer magi - ett inkommande samtal:

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är är vi bara intresserade av en rad.

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

Hon säger PBX installera Nummerpresentation (namn) variabel CallMeCallerIDName.

Själva CallMeCallerIDName-variabeln ställs i sin tur in av CallMe-applikationen (om Bitrix24 har ett fullständigt namn för uppringarens nummer kommer vi att ställa in det som Nummerpresentation (namn), nej - vi kommer inte att göra någonting).

Applikationsinställningar

Programinställningsfil - /var/www/pbx.vistep.ru/config.php

Beskrivning av applikationsparametrar:

  • CallMeDEBUG - om 1, kommer alla händelser som behandlas av applikationen att skrivas till loggfilen, 0 - vi skriver ingenting
  • tech SIP/PJSIP/IAX/etc
  • authToken — Bitrix24-auktoriseringstoken, utgående webhook-auktoriseringskod
  • bitrixApiUrl — URL till den inkommande webhook, utan profil/
  • förlängningar — lista över externa nummer
  • sammanhang — sammanhang för samtalsuppkoppling
  • listener_timeout - Händelsebearbetningshastighet från asterisk
  • asterisk - en array med anslutningsinställningarna till asterisken:
  • värd - ip eller värdnamn för asteriskservern
  • ordningen — anslutningsschema (tcp://, tls://)
  • port - hamn
  • Användarnamn - Användarnamn
  • hemligt - Lösenord
  • connect_timeout - timeout för anslutning
  • read_timeout - läs timeout

exempel inställningsfil:

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

);

Arbetsledare inställning

Supervisor används för att starta händelsehanterarprocessen Asterisk CallMeIn.php, som övervakar inkommande samtal och interagerar med Bitrix24 (visa kortet, dölj kortet, etc.).

Inställningsfil att skapa:

/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

Starta och starta om programmet:

supervisorctl start callme
supervisorctl restart callme

se status för applikationen:

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

Slutsats

Det visade sig ganska svårt, men jag är säker på att en erfaren administratör kommer att kunna implementera och tillfredsställa sina användare.

Som utlovat, länk till github.

Frågor, förslag - vänligen i kommentarerna. Dessutom, om du är intresserad av hur utvecklingen av denna integration gick, skriv, och i nästa artikel kommer jag att försöka avslöja allt mer i detalj.

Källa: will.com

Lägg en kommentar