顶顶通呼叫中心中间件(mod_cti基于FreeSWITCH)-使用指南

本指南使用ccadmin工具作为配置工具,用户可以根据本指南掌握cti中间件的配置和用法,然后开发出自己的web配置界面。ccadmin的实现原理是通过操作redis来实现配置呼叫中心系统,开发web配置界面也是一样,只需要通过操作redis就可以完成呼叫中心系统的配置。

警告

运行在公网的FreeSWITCH服务器,每天都会接收到很多恶意的呼叫请求和注册请求,尝试盗打电话。大部分人都容易麻痹大意,千万不要麻痹大意,盗打会引起很严重的后果,请多看几遍 SIP安全 的说明,呼叫外线的拨号方案要谨慎启用。如果不需要分机拨打外线,千万不要启用呼叫外线的拨号方案,有分机拨打外线的需求时只能在internal路由启用呼叫外线的拨号方案(external路由千万不要启用)。启用了呼叫外线,要确定sip->internal->auth-calls 是勾选的,所有分机密码也要改成足够复杂的,并且要测试一下注册错误的情况下,直接拨号是否可以拨打出去,来验证配置准确无误。然后配置好fail2ban规则封杀攻击Ip。如果只有浏览器(wss)可以拨打外线,可以把sip->internal->sip-port 配置的 udp的sip端口防火墙封了去,只放开wss端口。

开始使用

启动fs

  • systemctl start freeswitch
  • 如果遇到启动问题,需要前台直接启动FreeSWITCH看输出日志 sudo freeswitch -u ddt

执行fs命令

  • FreeSWITCH 已经启动了,进入控制台命令 fs_cli

  • 在FreeSWITCH控制台可以执行FreeSWTICH的命令,比如下图就是执行status命令,退出控制台的方法时执行命令 /exit
    执行FreeSWTICH命令

  • 生产环境系统运行时会输出大量的日志,也可以不进入控制台在shell终端执行FreeSWTICH命令fs_cli -x "status",双引号里面的就是需要执行的命令。
    终端直接执行FreeSWITCH命令

停止fs

  • systemctl stop freeswitch

修改控制台输出日志

  • 调整控制台输出日志等级,在控制台执行 console loglevel 6 0-7,7是debug等级 0是console等级。快捷方法按F7直接设置为0,按F8设置为debug。
    设置控制台输出日志等级

查看fs的相关路径

  • 查看FreeSWTICH日志文件声音文件等路径 fs控制台执行 global_getvar会输出全部的全局变量

    • log_dir就是日志文件目录
    • recordings_dir录音文件目录
    • sounds_dir和sound_prefix放音文件目录(sound_prefix更优先)
    • conf_dir配置文件目录(cti.json在这个目录,cti.conf.xml在${conf_dir}/autoload_configs这个目录)
    • storage_dir是http缓存文件目录(cti的tts文件也会缓存到这个目录)
    • mod_dir模块文件目录(mod_cti.so就是在这个目录)。

    image-20220826184502273

查看cti模块状态

  • 输出cti模块的信息cti status

    • domain cti.conf.xml里面配置的域名,用来区分多个freeswitch
    • redis_ready 执行同步redis命令的连接是否就绪
    • redis_async 执行异步redis命令的连接是否就绪
    • redis_subscribe 接收redis订阅发布消息的连接是否就绪(redis配置的外呼任务,线路组,排队技能组等配置改变就是通过redis的订阅发布模式通知cti模块的。)
    • sad_ready 噪音人声模型是否加载成功

      image-20220826185457084

跟踪sip信令

  • 输出sip信令日志 在控制台执行 sofia global siptrace on,就会输出信令日志到控制台,关闭的方法是 sofia global siptrace off

  • 遇到复杂的媒体问题,比如通话没声音,需要tcpdump抓包 ,shell终端(不是fs控制台)执行 tcpdump -i 网卡 udp -w 1.pcap就会把网络数据抓包到1.pcap,可以在windows电脑安装Wireshark打开抓包文件进行分析。

基础配置

配置SIP端口

默认有2个sofia profile 分别为internal和external,internal主要用来注册分机(auth-calls 必须是勾选),external用来对接网关(网关配置为all)。如果需要修改sip端口,参照下图修改internal和external的sip-port端口。修改sip端口需要重启fs或者重载sofia模块才可以生效。sip端口同时支持tcp和udp,一般都是用UDP的,没特殊要求防火墙开放UDP端口就可以。

设置 sip port

配置公网IP

如果需要公网使用sip服务,需要配置公网IP,如果内网使用直接配置为本机内网IP。注意external_ip=1.1.1.1 这样的IP格式,不要后面有空格。

设置公网IP

设置RTP端口范围

rtp端口就是传输声音的端口,一个通话需要2个端口,一个是rtp一个是rtcp。端口范围必须是双数,默认16384到32768(UDP端口,不是TCP端口),如果需要设置其他范围可以按照下图所示修改。

image-20220826190308493

设置日志等级

开发阶段需要设置日志等级为debug,上线后可以改成其他等级。默认是打开了 console,info,notice,warning,err,crit,alert,如果需要打开debug日志修改为 debug,console,info,notice,warning,err,crit,alert 就可以。rollover一个日志文件最大多少字节,maximun-rotae 最大保留多少个日志文件。logfile设置日志文件目录。查看日志文件默认目录的方法 执行命令 global_getvar log_dir,修改日志配置生效的方法是执行命令reload mod_logfile

image-20220826181619764

查看sofia(SIP模块)状态

运维调试界面点一下sip,就会显示sip状态,如果显示不了说明sofia模块没加载成功,可以执行 fs命令 reload mod_sofia,看看输出什么错误。如果修改了sip配置需要重启fs或者重启sofia模块,才能生效。查看data里面的ip和端口是不是和设置的一致。

image-20220826191127238

CCAdmin执行fs命令

如果mod_cti模块和redis连接时正常的,就可以这样通过CCAdmin工具执行执行fs命令。

image-20220826191452915

CCAdmin监视fs日志

可以通过查看日志文件,或者进入fs控制台fs_cli监视fs日志,ccadmin也可以监视fs日志(生成环境建议只能通过tail -f freeswitch.log)来监视fs日志。

image-20220826192014937

IPPBX

这章节介绍ippbx场景下的配置方法

添加分机

CCAdmin创建分机

分机配置里面添加一个分机,密码要设置复杂点,添加分机是实时生效的。创建分机其实就是往redis写入一个数据。

image-20220826204735882

sip客户端注册分机

这里下载 sip客户端,http://down.ddrj.com/phone.zip

image-20220826205335228

主机地址 如果内网使用就是安装FreeSWITCH的服务器IP,如果外网使用就是服务器的外网IP。需要先做好端口映射,配置文件->var->external_ip 这个要先配置好,外网Ip配置修改了要重启fs, 在运维调试页面点一下sip,可以看到fs实际监听的IP和端口,具体可以看 faq.html#分机注册超时-408-Request-Timeout

如果显示注册成功说明分机配置正确了。如果出现注册超时408,就检测防火墙和云服务器的网络完全是否开放好了sip端口。

CCAdmin查看在线分机

CCAdmin的运维调试 SIP, internal的user点一下刷新,就可以显示已经注册的分机。

image-20220826205604298

通话测试

sip的internal默认是使用internal这个路由,internal路由启用放音测试,sip软电话呼叫echo,进行回音测试。电话接通后如果听到提示音,提示音之后可以听到自己说话的声音,说明rtp端口和redis连接都没问题了。(生产环境的路由需要根据业务情况启用,路由要小心配置,防止电话给盗打,不需要的拨号方案不要启用)。

image-20220826210026089

image-20220826205931273

image-20220826210259678

分机互打

再创建一个分机,sip客户端可以同时注册多个分机(同一个软件的2个分机互打),也可以再找个电脑,或者手机上安装一个sip软件(linphone) android https://download.linphone.org/releases/android/linphone-latest.apk ios在app store搜索 linphone安装。

linphone配置

点击 助手 -> 使用SIP账户 添加账户,然后账户高级设置里面 AVPF 取消勾选。就可以手机和电脑2个sip软件之间通话了。

image-20220826220628088image-20220826220642977

分机互打的路由和拨号方案设置

internal路由必须启用了呼叫分机,才可以分机互打。拨号方案呼叫分机通过 ${cti_extension_exists(${destination_number})} 判断被叫是否是分机号,如果是分机号,就执行下面的动作,并且不在执行后面的拨号方案。如果不是分机号,继续执行呼叫路由里面后续的拨号方案。

image-20220826221612716

image-20220826221652990

对接落地

有了落地,才可以呼叫到pstn网络,也就是拨打实际的电话。落地也称呼sip中继,大部分话批的落地都是用VOS搭建的,自建落地一般是使用语音网关,或者申请通讯运营商的IMS中继,E1等。注意:普通电话线如果不开反极性信号,是不能用于自动外呼业务的,因为没开通反极性信号,就获取不到对方应答信号。对接落地一般有1.网关对接(线路方提供sip中继的IP地址端口以及用户名密码,fs注册到sip中继),2.IP对接(线路方提供sip中继的IP地址端口,用户要把fs的IP地址和端口报给线路方,通过IP地址验证),3.反向注册(用自己购买了语音网关,语音网关注册到fs) 几种方式 ,详细配置请看下面的描述:

  • 网关对接,就是fs注册到落地SIP代理服务器。需要落地方提供sip代理服务器的IP端口,以及用户名密码,主叫号码和被叫前缀信息。

    • realm sip代理服务器IP和端口
    • username 注册的用户名
    • password 注册的密码
    • register 是否需要注册,如果是绑定IP的,不需要注册的,就不要勾选。这样的其实就是IP对接,也不需要用户名和密码。
    • destination-prefix 被叫前缀,如果落地没要求被叫前缀就不要配置。
    • 主叫号码 如果落地提供了多个主叫号码,这里不要配置,可以再外呼程序和拨号方案不同的业务设置不同的主叫。
      image-20220827105509116
  • ims 对接例子 (ims对接其实就是网关对接,只是ims注册需要填写很多参数)
    image-20220827111703172

  • 网关注册状态,可以在CCAdmin的运维调试 SIP external下面看到是否注册成功。

    image-20220827155445007

  • 反向注册对接,一般是FreeSWITCH有公网IP,和语音网关不在一个网络,语音网关在内网没公网IP,就需要语音网关注册到FreeSWITCH上面来,才可以通过语音网关外呼。

    • fs添加一个分机,如果需要支持呼入,呼叫路由最好改成external,分机默认路由是internal,改成external和网关对接呼入走一样的呼入路由。

      image-20220827112959797

      • 登录语音网关设备配置后台,设置sip参数(sip服务器就是fs的公网IP,端口就是sip->internal配置的sip-port,用户名密码就是添加用来注册对接的分机和密码)注册超时或者间隔设置60秒。 配置好后,可以在CCAdmin的运维调试 SIP, internal的user点一下刷新,如果看到这个分机的注册信息,就是注册成功了。
  • IP对接,把fs的公网IP地址报给线路方做白名单,如果还需要验证端口(sip->external配置的sip-por)把这个配置的端口和external-ip报给线路方。,fs直接添加线路串里面输入sofia/external/${destination_number}@落地IP:落地PORT

添加线路

线路是cti模块的一个虚拟概念,用来统一管理各种sip资源。一个分机,一个落地网关都可以是一个线路。线路配置通过拨号串来关联到实际的sip设备。配置修改了需要点更新才能生效。

  • 内线线路,比如分机就属于内线。sip分机一般就一个并发,并发设置为1,比如业务系统的示忙功能,就可以动态的把并发修改为0。拨号串选择user/分机号。坐席工号是用来给排队模块报工号用的。

    image-20220827114754775

  • 外线线路,比如网关就属于外线。通过网关对接的外线的拨号串写法是sofia/gateway/网关名/${destination_number},IP直接对接,不添加网关的拨号串写法是 sofia/external/${destination_number}@落地IP:落地PORT,反向注册对接的拨号串写法是user/分机号。cti模块外呼过程会把${destination_number}替换成实际的被叫号码,反向注册对接不需要${destination_number}这个变量,cti模块会自动处理。

    • 最大并发:落地支持的最大同时通话数量。
    • 休息时间:很多落地有CPS限制,就是1秒最多可以呼叫多少次。比如1秒可以呼叫20次,1000/20=50,那么休息时间就设置50。如果落地没限制,休息时间就可以不用设置。

image-20220827115218181image-20220827115329787

添加线路组

线路组可以把多个线路组合起来,实现线路的循环使用,和重拨策略,cti模块外呼必须使用线路组。默认有2个优先级,优先线路全忙时才会使用后备线路,同一个优先级可以配置多个线路。也可以通过修改线路组模板定义更多的优先级。配置修改了需要点更新才能生效。

  • 坐席组,多个内线线路可以组织成一个坐席组,用来实现呼入多个分机的循环接听。
  • 中继组,多个外线线路可以组织成一个中继组,用来实现呼出线路循环使用。如果只一个外呼线路也必须配置线路组。

image-20220827152840652

分机呼出

  • 呼叫路由 -> internal 启用 呼叫外线。

image-20220827075509695

  • 呼叫外线拨号方案说明
    • 第一步把被叫号码(${destination_number})和主叫号码(${caller_id_number})的关联关系写入redis(cti_hash_set callhistory@${cti_domain}),方便被叫回拨时转接给主叫,cti_hash_set callhistory@${cti_domain} ${cti_mid_string(${destination_number} -11)} ${caller_id_number}
    • 第二步 如果被叫号码时00开始直接挂断,防止呼叫国际长途
    • 第三步 如果被叫号码是数字的并且长度时8到12位,通过线路组default呼出。
      • export 设置变量,一个通话有2端,a端 分机拨打fs的,b端 fs呼叫手机的。export会设置变量到a端和b端,set只会设置变量到a端。比如需要设置主叫为999,可以再bridge之前设置一个变量 set effective_caller_id_number=999,比如要设置呼叫手机使用编码为PCMA,PCMU,G729就是再bridge前添加export data=”nolocal:absolute_codec_string=PCMA,PCMU,G729” ,只需要设置变量到b端,不要设置到a端,就是变量前面加上noload:l。
      • bridge:linegroup/default/$1 这个叫拨号串,$1对应正则表达式(里面捕获的内容)。如果通过网关直接呼出的拨号串是 sofia/gateway/网关名/$1,通过落地IP直接呼出的拨号串是 sofia/external/$1@落地ip:落地port,通过线路组呼出的拨号串写法是linegroup/线路组/$1

image-20220827075844216

外线呼入

  • 呼入路由

    默认是sip->external里面指定呼入路由,如果网关对接,也可以网关配置指定路由。

    image-20220827160245044
    反向注册对接,是分机配置里面指定路由,如果不指定就是使用sip->internal里面配置的呼叫路由了。

    image-20220827160508237

  • 呼入安全

    • 呼入路由(external)千万不要启用呼叫外线,这样会有非常严重的安全问题,电话有给盗打的风险。

    • 指定IP才可以呼入,sip->external->apply_inbound_acl 设置呼入ACL为inbound。配置文件->acl.conf->inboud的default配置为deny,默认拒绝所有IP的呼入。然后单独设置指定IP才可以呼入。下图例子是127.0.0.1这个IP才可以呼入,可以逗号隔开指定多个IP/32,/32是掩码,比如/24指定一个网段,也可以直接添加多条allow的cidr记录。sip修改了需要重启fs或者重启external这个profile才可以生效。acl.conf修改了需要执行cli命令reloadacl 才可以生效。

      image-20220827160752861

      image-20220827160853555

  • 根据最后的呼出记录回拨分机

    ${cti_mid_string(${caller_id_number} -11) 获取来电的前11位号码

    ${cti_hash_get(callhistory@${cti_domain} 来电} 从redis(callhistory@${cti_domain})读取来电关联的分机

    ${cti_extension_exists(分机)} 判断分机是否存在

    ${cti_extension_exists(${cti_hash_get(callhistory@${cti_domain} ${cti_mid_string(${caller_id_number} -11)})})}

    读取到的关联分机会存放在 ${cti_hash_get_last_result} 这个变量里面。

    如果读取到关联分机,就把来电转接给这个分机。

    image-20220827161525232

    image-20220827161609105

  • 可以根据业务规则配置呼叫路由和拨号方案,在大部分语音网关里面配置呼入有一个代拨号的配置,对应的就是fs里面的被叫一般也叫DID,对应fs的变量是${destination_number}。

  • 呼入排队,external 的路由里面启用进入排队,DID设置为排队名字就可以。

队列外呼

  • 线路组:外呼使用的线路组
  • 并发:最大同时保持多少个通话。
  • 呼叫速度:1秒最大发起多少个呼叫, 比如并发设置为100,当前存在的通话是0个,呼叫速度设置为10时,第一秒发起10个呼叫,第二秒再发起10个呼叫,以这样的速度发起呼叫,直到通话总数达到并发就停止发起新的呼叫。如果有电话挂断了,那么以1秒10个的速度继续发起新的呼叫,使通话总数达到并发设置的值。
  • 启动时间,停止时间,上班时间,工作日这几个必须设置。上班时间如果每天都一样的,星期设置为-1,如果每天需要不同的上班时间,就需要设置每天的上班时间。
  • 号码队列:存放外呼号码的list,也支持set。
  • 外呼接通后的流程 通过路由条件,拨号方案,和呼叫路由控制。
    • 呼叫路由:电话接通后使用哪个呼叫路由,比如外线呼入用的时external,分机呼出用的时internal,自动外呼这里指定呼叫路由。
    • 拨号方案 :CTI系统使用的都时XML拨号方案,如果用户自己对fs很熟悉,也可以用lua等其他脚本的拨号方案。
    • 路由条件:执行拨号方案时${destination_number} 这个变量的值,正常的呼入呼出这个变量是被叫,自动外呼时这里设置这个变量的值,用来匹配到拨号方案。

机器人接听的外呼任务

  • 先根据文档(http://www.ddrj.com/smartivr/robot.html )使用flowedit编辑好话术,然后ccadmin上传话术到redis,话术名不要.json后缀。

    image-20220828114321646

  • 机器人拨号方案

    • 执行 json话术引擎

      ${cti_robot_flow_exists(${destination_number})} 如果${destination_number}指向的话术脚本存在,则执行这个话术脚本。

      image-20220827212941284

    • 执行http话术接口(http://www.ddrj.com/callcenter/httpflow.html)

      如果${destination_number}等于httpflow,则这些这个拨号方案,可以自己设置拨号方案的匹配条件。

      http://127.0.0.1/flow.php?flow=${destination_number}&callid=${uuid}&callerid=${caller_id_number}http话术地址,可以根据业务需求传递的变量到http接口。

      image-20220827213403308

  • 机器人路由,按顺序执行

    1. 等待应答
    2. 通话录音
    3. 在通话过程播放一个舒适音,这个主要可以防止录音不同步的问题。
    4. 匹配机器人脚本
    5. 如果需要执行http话术,也可以启用http话术。

    image-20220827213925186

  • 创建机器人外呼任务,任务配置修改了需要点更新才能生效。

    线路组:外呼使用的线路组

    号码队列:获取外呼号码的队列名字

    路由条件:电话接通后需要执行的话术名字

    呼叫路由:电话接通后执行的呼叫路由

image-20220827201854497

  • 查看fs内部任务状态,如果任务配置好了,但是不外乎,就需要查看一下任务的状态。注意启用是个三态按键,需要打勾了,才是启用。

    执行fs命令 cti show queue_dialer 任务名

    1. 检查enable是否是true
    2. 检查call_limit是否大于1
    3. 检查start_time、stop_time、work_hour、work_weeks是否包含了当前时间
    4. 检查line_group的idle(可用并发)是否大于0
    5. 检查number_queue配置的队列里面是否有号码
    6. cps_last:最近1秒呼叫了多少个号码,call_count:当前通话(包含未接通)的总数

    image-20220827214717732

人工接听的外呼任务

  • 配置排队

    坐席线路组必须设置,就是用来接听排队中电话的坐席。

    image-20220828114622942

  • 配置拨号方案

    ${cti_acd_exists(${destination_number})}如果${destination_number}变量指向的是一个排队名,就进入排队。

    image-20220828115222681

  • 配置路由

    1. 等待应答
    2. 通话录音
    3. 进入排队

image-20220828115547635

  • 配置人工接听的外呼任务

    • 线路组:外呼使用的线路组
    • 并发:外呼的最大并发
    • 路由条件:接通后进入的排队
    • 呼叫路由:接通后执行的呼叫路由
    • 坐席线路组:根据坐席组空闲坐席数量来设置外呼并发
    • 呼叫倍数:外呼并发是空闲坐席乘以这个倍速。如果计算的结果大于任务配置的最大并发,就以最大并发为准。
    • 排队限制:排队中的呼叫大于座席总数乘以这个值就停止呼叫。可以设置为0-1之间。
    • 速度倍速:一个空闲座席一秒最多呼叫多少个号码,建议设置1-3。如果计算结果大于任务配置的最大呼叫速度,就以最大呼叫速度为准。

    image-20220828115727045