我们处理FreePBX并将其与Bitrix24集成在一起,不仅

Bitrix24是一个巨大的收割机,它结合了CRM,文档流,会计以及经理真正喜欢和IT员工真正不喜欢的许多其他东西。许多中小型公司都使用该门户,包括小型诊所,制造工人甚至美容院。经理“爱”的主要功能是电话和CRM的集成,当任何呼叫立即记录在CRM中时,创建了客户卡,在接听客户时显示了有关客户的信息,您可以立即看到他是谁,他能卖什么以及欠他多少钱。但是Bitrix24的电话及其与CRM的集成有时会花费很多钱。在本文中,我将告诉您与开放工具和流行的IP PBX FreePBX集成的经验,并考虑各个部分工作的逻辑

我在一家销售,配置和集成IP电话的公司中担任外包公司的工作。当询问我是否可以为这家公司和这家公司提供某种东西来将Bitrix24与客户拥有的PBX以及各种VDS公司上的虚拟PBX集成在一起时,我去了Google。而且,当然,他给了我指向Habr中的一篇文章的链接,该文章中有一个描述和github,一切似乎都正常。但是,当尝试使用此解决方案时,事实证明Bitrix24不再像以前那样,需要重做很多。另外,FreePBX对您而言并不是一个裸露的星号,在这里您需要考虑如何在配置文件中结合可用性和硬性拨号方案。

我们研究工作的逻辑

所以首先,它应该如何工作。当呼叫从外部打向PBX(来自提供商的SIP INVITE事件)时,开始进行拨号计划(拨号计划,拨号计划)的处理-处理呼叫的顺序和顺序的规则。从第一个程序包中可以获得很多信息,然后可以在规则中使用它们。sngrep分析器链接是研究SIP内部的绝佳工具,可以通过apt install / yum install等安装在流行的发行版中,但是您也可以从源代码构建它。让我们看看sngrep中的通话记录

以简化的形式,拨号计划仅处理第一个程序包,有时在通话过程中,将转移呼叫,按下按钮(DTMF),各种有趣的事情,例如FollowMe,RingGroup,IVR等。

邀请包中的内容

DID CallerID. DID - , CallerID - .

- (/ ) (Ring Group), IVR (, ... ...), (Phrases), (Time Conditions), (FollowMe, Forward). , .

"". Asterisk - , ( exten, exten=DID). - ( - Dial(), - Hangup()), (IF, ELSE, ExecIF ), (Goto, GotoIF), (Gosub, Macro). include _, . , include .

FreePBX include Gosub, Macro Handler. FreePBX

, (Macro), (Gosub) (Goto), , .

. DID, , - . 1 . hangupcall, , (hangup handler).

CRM, , CRM?

CRM? , . API, API HTTP REST. asterisk.

Asterisk :

AMI

Event: Newchannel Privilege: call,all Channel: PJSIP/VMS_pjsip-0000078b ChannelState: 4 ChannelStateDesc: Ring CallerIDNum: 111222 CallerIDName: 111222 ConnectedLineNum: ConnectedLineName: Language: en AccountCode: Context: from-pstn Exten: s Priority: 1 Uniqueid: 1599589046.5244 Linkedid: 1599589046.5244

ARI

{ "variable":"CallMeCallerIDName", "value":"111222", "type":"ChannelVarset", "timestamp":"2020-09-09T09:38:36.269+0000", "channel":{ "id":"1599644315.5334", "name":"PJSIP/VMSpjsip-000007b6", "state":"Ring", "caller":{ "name":"111222", "number":"111222" }, "connected":{ "name":"", "number":"" }, "accountcode":"", "dialplan":{ "context":"from-pstn", "exten":"s", "priority":2, "appname":"Stasis", "appdata":"hello-world" }, "creationtime":"2020-09-09T09:38:35.926+0000", "language":"ru" }, "asteriskid":"48:5b:aa:aa:aa:aa", "application":"hello-world" }

, API , . CRM :

  • , , CallerID, DID, , ( CRM)

  • , ,

  • ( ), ,

  • : CRM, FollowME ( CRM)

AMI ARI, ARI , , , AMI ( , , ). , - AMI ( ). ( , ) - ( ) PAMI. * ARI, .

, FreePBX AMI , , , , , - . PAMI -.

(s - , DID)

[ext-did-custom]

exten => s,1,Set(CallStart=${STRFTIME(epoch,,%s)})
AMI

Event: Newchannel

Privilege: call,all

Channel: PJSIP/VMS_pjsip-0000078b

ChannelState: 4

ChannelStateDesc: Ring

CallerIDNum: 111222

CallerIDName: 111222

ConnectedLineNum:

ConnectedLineName:

Language: en

AccountCode:

Context: from-pstn

Exten: s

Priority: 1

Uniqueid: 1599589046.5244

Linkedid: 1599589046.5244

Application: Set AppData:

CallStart=1599571046

FreePBX extention.conf extention_additional.conf, extention_custom.conf

extention_custom.conf
[globals]	
;;       -  asterisk     
;;    
WAV=/var/www/html/callme/records/wav 
MP3=/var/www/html/callme/records/mp3

;;        
URLRECORDS=https://www.host.ru/callmeplus/records/mp3

;;      
URLPHP=https://www.host.ru/callmeplus

;;   
RECORDING=1

;;        . 
;;     ,      - 
;;  
[recording]
exten => ~~s~~,1,Set(LOCAL(calling)=${ARG1})
exten => ~~s~~,2,Set(LOCAL(called)=${ARG2})
exten => ~~s~~,3,GotoIf($["${RECORDING}" = "1"]?4:14)
exten => ~~s~~,4,Set(fname=${UNIQUEID}-${STRFTIME(${EPOCH},,%Y-%m-%d-%H_%M)}-${calling}-${called})
exten => ~~s~~,5,Set(datedir=${STRFTIME(${EPOCH},,%Y/%m/%d)})
exten => ~~s~~,6,System(mkdir -p ${MP3}/${datedir})
exten => ~~s~~,7,System(mkdir -p ${WAV}/${datedir})
exten => ~~s~~,8,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")
exten => ~~s~~,9,Set(FullFname=${URLRECORDS}/${datedir}/${fname}.mp3)
exten => ~~s~~,10,Set(CDR(filename)=${fname}.mp3)
exten => ~~s~~,11,Set(CDR(recordingfile)=${fname}.wav)
exten => ~~s~~,12,Set(CDR(realdst)=${called})
exten => ~~s~~,13,MixMonitor(${WAV}/${datedir}/${fname}.wav,b,${monopt})
exten => ~~s~~,14,NoOp(Finish if_recording_1)
exten => ~~s~~,15,Return()


;;      
[ext-did-custom]

;;  ,     ,   -    '8'
exten =>  s,1,Set(CALLERID(num)=8${CALLERID(num)})

;;     
exten =>  s,n,Gosub(recording,~~s~~,1(${CALLERID(number)},${EXTEN}))
exten =>  s,n,ExecIF(${CallMeCallerIDName}?Set(CALLERID(name)=${CallMeCallerIDName}):NoOp())
exten =>  s,n,Set(CallStart=${STRFTIME(epoch,,%s)})
exten =>  s,n,Set(CallMeDISPOSITION=${CDR(disposition)})

;;  !   . 
;;      (exten=>h,1,)  FreePBX   - Macro(hangupcall,)  . 
;;   Hangup_Handler   
exten => s,n,Set(CHANNEL(hangup_handler_push)=sub-call-from-cid-ended,s,1(${CALLERID(num)},${EXTEN}))

;;    
[sub-call-from-cid-ended]

;;      
exten => s,1,Set(CDR_PROP(disable)=true)
exten => s,n,Set(CallStop=${STRFTIME(epoch,,%s)})
exten => s,n,Set(CallMeDURATION=${MATH(${CallStop}-${CallStart},int)})

;;   - ,  ...
exten => s,n,Set(CallMeDISPOSITION=${CDR(disposition)})
exten => s,n,Return


;;    -  
[outbound-allroutes-custom]

;; 
exten => _.,1,Gosub(recording,~~s~~,1(${CALLERID(number)},${EXTEN}))
;; 
exten => _.,n,Set(__CallIntNum=${CALLERID(num)})
exten => _.,n,Set(CallExtNum=${EXTEN})
exten => _.,n,Set(CallStart=${STRFTIME(epoch,,%s)})
exten => _.,n,Set(CallmeCALLID=${SIPCALLID})

;;  Hangup_Handler   
exten => _.,n,Set(CHANNEL(hangup_handler_push)=sub-call-internal-ended,s,1(${CALLERID(num)},${EXTEN}))

;;    
[sub-call-internal-ended]

;; 
exten => s,1,Set(CDR_PROP(disable)=true)
exten => s,n,Set(CallStop=${STRFTIME(epoch,,%s)})
exten => s,n,Set(CallMeDURATION=${MATH(${CallStop}-${CallStart},int)})
exten => s,n,Set(CallMeDISPOSITION=${CDR(disposition)})

;;  ,      CRM -  , 
;;     
exten => s,n,System(curl -s ${URLPHP}/CallMeOut.php --data action=sendcall2b24 --data ExtNum=${CallExtNum} --data call_id=${SIPCALLID} --data-urlencode FullFname='${FullFname}' --data CallIntNum=${CallIntNum} --data CallDuration=${CallMeDURATION} --data-urlencode CallDisposition='${CallMeDISPOSITION}')
exten => s,n,Return

-

  • .conf, FreePBX ( .ael, )

  • exten=>h hangup_handler, FreePBX

  • , ExtNum

  • _custom FreePBX - [ext-did-custom], [outbound-allroutes-custom]

  • -

AMI - FreePBX _custom

manager_custom.conf
;;   
[callmeplus]
;;  
secret = trampampamturlala
deny = 0.0.0.0/0.0.0.0

;;      -   ,    
permit = 127.0.0.1/255.255.255.255
read = system,call,log,verbose,agent,user,config,dtmf,reporting,cdr,dialplan
write = system,call,agent,log,verbose,user,config,command,reporting,originate

/etc/asterisk, ( )

# astrisk -rv
  Connected to Asterisk 16.6.2 currently running on freepbx (pid = 31629)
#freepbx*CLI> dialplan reload
     Dialplan reloaded.
#freepbx*CLI> exit

PHP

24, AMI , . AMI . , . , PAMI , , ..

, NewExten [from-pstn], . _custom CallMeCallerIDName CallStart

  1. UserID, , . ? , ( ) ? Fisrt Available, , .

  2. 24, CallID, . UserID

, (, , ), mp3 ( ).

CallMeIn.php , SystemD callme.service, /etc/systemd/system/callme.service

[Unit]
Description=CallMe

[Service]
WorkingDirectory=/var/www/html/callmeplus
ExecStart=/usr/bin/php /var/www/html/callmeplus/CallMeIn.php 2>&1 >>/var/log/callmeplus.log
ExecStop=/bin/kill -WINCH ${MAINPID}
KillSignal=SIGKILL

Restart=on-failure
RestartSec=10s

#  ,   
#User=www-data  #Ubuntu - debian
#User=nginx #Centos

[Install]
WantedBy=multi-user.target

systemctl service

# systemctl enable callme
# systemctl start callme

( ). , php ( FeePBX). ( https) .

. CallMeOut.php :

  • php ( "" ). , HTTP POST,

  • , . Asterisk [sub-call-internal-ended]

- ( HTTPS) CallMeOut.php. FreePBX, /var/www/html, .

(, , ). , FreeDomain( https://www.freenom.com/ru/index.html), IP ( 80, 443 , ). DNS , ( 15 48 ) . - 1 .

github , . - , , , . (

Docker

- Docker - , , ( LetsEncrypt , , FreePBX ( - 88), LetsEncrypt

( git clone), ( asterisk) URL

version: '3.3'
services:
  nginx:
    image: nginx:1.15-alpine
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./nginx/ssl_docker.conf:/etc/nginx/conf.d/ssl_docker.conf
  certbot:
    image: certbot/certbot
  freepbx:
    image: flaviostutz/freepbx
    ports:
      - 88:80 #  
      - 5060:5060/udp
      - 5160:5160/udp
      - 127.0.0.1:5038:5038 #  CallMeOut.php
#      - 3306:3306
      - 18000-18100:18000-18100/udp
    restart: always
    environment:
      - ADMIN_PASSWORD=admin123
    volumes:
      - backup:/backup
      - recordings:/var/spool/asterisk/monitor
      - ./callme:/var/www/html/callme
      - ./systemd/callme.service:/etc/systemd/system/callme.conf
      - ./asterisk/manager_custom.conf:/etc/asterisk/manager_custom.conf
      - ./asterisk/extensions_custom.conf:/etc/asterisk/extensions_custom.conf
#      - ./conf/startup.sh:/startup.sh

volumes:
  backup:
  recordings:

docker-compose.yaml,

docker-compose up -d

nginx , nginx/ssl_docker.conf

CRM , . API CRM, - ShugarCRM Vtiger, ! , . , .

: ,




All Articles