目前我们公司电话系统经过两年的发展,已经实现了两个异地办公室、上百部分机,三个机房节点,多家voip供应商的之间的互通与网络冗余,算的上一个小型的呼叫中心了,一直比较懒写这方面的文章。最近公司正好有做回拨的需求,随便写篇关于这方面的文章。
需求:客户通过网站前台提交电话号码,电话系统先呼叫指定客服分机或响铃组,客服摘机后系统呼叫客户电话号码,客户接听后开始与客服通话。

我们的电话系统用的是freePBX,系统自带回拨功能(callback)功能比较简单,商业模块(WebCallBack)可以实现web提交号码,但这两个模块都只能先呼叫客户,客户接通后才能呼叫客服,无法自定义呼叫顺序,不满足我们的需求,只能自己开发了。好在asterisk支持自动呼叫脚本(.call files),功能实现起来比较容易,先看一下脚本工作流程:

1. asterisk 启动时需加载pbx_spool.so 模块支持自动呼叫脚本,Freepbx是自动加载的
2. 按需求编写呼叫脚本,保存为扩展名为.call的文件
3. 将.call脚本移到到/var/spool/asterisk/outgoing/目录下
4. 系统检测到该脚本并自动执行呼叫流程

呼叫脚本语法:

发起呼叫的参数:
Channel: <channel>: 呼叫的通道,可以是分机,trunk,响铃组等等
CallerID: "name" <number>  主叫id,即显示的号码和名称
MaxRetries: <number> 呼叫失败后重试次数,不包括原始呼叫
RetryTime: <number>  等待多久重新尝试呼叫
WaitTime: <number>  等待接听超时的时间
Account: 使用的Accoud code,CDR计费方面会用到

呼叫接通后的参数:
Context: <context-name> 使用的拨号方案
Extension: <ext>  拨号方案的目标号码
Priority: <priority> 优先级
Set: 设置变量
Application: 要启动的应用
Data: 应用使用的数据参数
AlwaysDelete: Yes/No 更改时间为将来时,不会删除该文件
Archive: Yes/No  使否将执行过的脚本归档到outgoing_done

来写一个hello world脚本:

channel: SIP/801   ;我的分机号
Callerid: "call" <801>
Application: Playback
Data: hello-world

将脚本保存为helloworld.call,手动复制到/var/spool/asterisk/outgoing/,系统就会拨打分机801,播放hello world后挂机。
我的freepbx对接了很多的voip供应商,freepbx会生产默认拨号方案:outbound-allroutes,根据用户拨号自动选择呼出线路,如我的规则:使用呼出线路1来打10086的拨号为:1 86 75510086。下面在写一个呼叫脚本:

channel: SIP/801   ;分机
Callerid: "回拨" <801>
Context: outbound-allroutes
Extension: 18675510086

这个脚本个功能是先呼叫分机801,在分机801接听后,系统开始呼叫10086,10086接听后801就可以与10086通话了。
这个脚本中分机801接听后,系统大概需要5秒才能接通10086,之间没有任何提示,freepbx的系统自带了一些提示,编写一个拨号方案加入提示,编辑:etc/asterisk/extensions_custom.conf,加入:

[saylast4num]
exten = _XX.,1,NoOp(say last 4 number of client number works) 
exten = _XX.,n,Wait(1)
exten = _XX.,n,Playback(calling)   ;系统提示音 calling
exten = _XX.,n,SayDigits(${EXTEN:-4}) ;读拨打号码的后4位
exten = _XX.,n,Goto(autocall_out,${EXTEN},1) ;跳转到自动呼出的拨号方案
[autocall_out]
include => outbound-allroutes

修改上面的呼叫脚本为:

channel: SIP/801   ;分机
;channel: Local/400@from-internal  ;本地响铃组400
Callerid: "回拨" <801>
Context: saylast4num
Extension: 18675510086

执行一下,801分机接听后系统会提示“calling 0086”,然后呼叫075510086,以这个脚本为模版,将18675510086替换为客户的号码,在用python封装成web api,就可以实现从web接收号码,写相应call脚本到/var/spool/asterisk/outgoing/,实现我们所需的回拨功能,python +flask写几十行代码就可以搞定

其实不使用呼叫脚本,使用originate也能实现,一个简单的shell脚本:

#!/bin/bash
asterisk -x "channel originate SIP/$1 extension $2@outbound-allroutes"

保存为call.sh ,用法: call.sh 801 18675510086
先呼叫客户在接通内部分机的情况,最方便的是直接花50刀买webcallback模块,这个我不多说了

参考文章:

http://www.voip-info.org/wiki/view/Asterisk+auto-dial+out