FreeSWITCH及VOIP,Openser,电话机器人等产品中文技术资讯、交流、沟通、培训、咨询、服务一体化网络。QQ群:293697898
FSGUI6.1.2动态座席组及推送事件的接口
`////////////////////////////////////////////////////////////////////////////////////////////////////////////////////`
```
`CREATE SEQUENCE public.ext_group_id_seq`
`INCREMENT 1`
`MINVALUE 1`
`MAXVALUE 9223372036854775807`
`START 4`
`CACHE 1;`
`ALTER TABLE public.ext_group_id_seq`
`OWNER TO postgres;`
`CREATE SEQUENCE public.ext_group_map_id_seq`
`INCREMENT 1`
`MINVALUE 1`
`MAXVALUE 9223372036854775807`
`START 1`
`CACHE 1;`
`ALTER TABLE public.ext_group_map_id_seq`
`OWNER TO postgres;`
`CREATE TABLE public.ext_group`
`(`
`id bigint NOT NULL DEFAULT nextval('ext_group_id_seq'::regclass),`
`group_name character varying(100), -- 组或座席组名`
`group_number character varying(50) NOT NULL, -- 座席组短号`
`current_ext_number character varying(50), -- 当前组里接听时找到的分机,如果找不到,则再从头开始`
`group_call_mode integer DEFAULT 5, -- 呼叫模式 ...`
`group_callout_timeout integer DEFAULT 15, -- 呼叫到每个号码时的超时时长,默认15秒`
`transfer_ring character varying(255) DEFAULT '::character varying,`
`black_list_ring character varying(255) DEFAULT '::character varying,`
`busy_ring character varying(255) DEFAULT '::character varying,`
`CONSTRAINT "PK_GROUP_NUMBER" PRIMARY KEY (group_number)`
`)`
`WITH (`
`OIDS=FALSE`
`);`
`ALTER TABLE public.ext_group`
`OWNER TO postgres;`
`COMMENT ON TABLE public.ext_group`
`IS '分机座席分组,面向110业务';`
`COMMENT ON COLUMN public.ext_group.group_name IS '组或座席组名';`
`COMMENT ON COLUMN public.ext_group.group_number IS '座席组短号';`
`COMMENT ON COLUMN public.ext_group.current_ext_number IS '当前组里接听时找到的分机,如果找不到,则再从头开始';`
`COMMENT ON COLUMN public.ext_group.group_call_mode IS '呼叫模式
0 顺序`
`1 随机`
`2 循环`
`3 记忆优先+ 0`
`4 记忆优先+1`
`5 记忆优先+2';`
`COMMENT ON COLUMN public.ext_group.group_callout_timeout IS '呼叫到每个号码时的超时时长,默认15秒';`
`CREATE TABLE public.ext_group_map`
`(`
`id bigint NOT NULL DEFAULT nextval('ext_group_map_id_seq'::regclass),`
`ext_group_id bigint, -- 分机组id`
`ext_group_number character varying(50), -- 座席组号码`
`ext character varying(50) -- 分机`
`)`
`WITH (`
`OIDS=FALSE`
`);`
`ALTER TABLE public.ext_group_map`
`OWNER TO postgres;`
`COMMENT ON COLUMN public.ext_group_map.ext_group_id IS '分机组id';`
`COMMENT ON COLUMN public.ext_group_map.ext_group_number IS '座席组号码';`
`COMMENT ON COLUMN public.ext_group_map.ext IS '分机';
```
`////////////////////////////////////////////////////////////////////////////////////////////////////////////////////`
到2020-7实现的座席组逻辑如下:
a. 在系统中预定几个组,如 110,12345,12320120,等
B. 接着由座席上线时,指定上线了哪几个组
c. 我们在路由中配置了,如 85733555是进到12320这个组,则配操作符为 16,明细是 12320这个组号
d. 优先进行和组配套的黑名单,如果是处于黑名单就挂 机或放音
e. 接着查询历史沟通记录,如果记忆中的座席空闲,那么就由该座席来处理,否则找空闲座席处理
f. 如果没有历史沟通,就直接找该组空闲座席
g. 如果没空闲座席了,则判断是vip还是普通用户来电,有一定时器,不断优先判断vip的来电,接着判断普通的来电,在查找到有空闲座席的情况下,转给该空闲座席.
h. 不同的客户,需求有所不同,在有关挂 机的要求,有的要求放音几次后挂 ,有的是,客户不挂 机,我们不主动挂 机,按实际来配.
返回值: "token":"token code"
非正常返回值: "Not Authorized"
curl -d '{"username": "admin", "password": "admin"}' -H "Content-Type:application/json" http://ip:8085/api/login
让座席分机为上线或下线,即up or down
//up为上线
//down为下线
里边的组,可以为多个如: "12345,12320"
curl -H "Content-Type: application/json" -d '{"Extension":"1002","Groups":"12345,110"}' -H "Authorization:Nway token " http://ip:8085/api/agent_up
下线
curl -H "Content-Type: application/json" -d '{"Extension":"1002"}' -H "Authorization:Nway token " http://ip:8085/api/agent_down
让座席分机置忙或置闲 ,这里和设置呼叫状态,在不同的客户需求时,需要进行分开,否则可能只用呼叫状态一项处理不了
//ready or rest
置闲
curl -H "Content-Type: application/json" -d '{"Extension":"1002"}' -H "Authorization:Nway token " http://ip:8085/api/agent_ready
置忙
curl -H "Content-Type: application/json" -d '{"Extension":"1002"}' -H "Authorization:Nway token " http://ip:8085/api/agent_busy
//ring,talking,ivr,ready,typing,no_answer, no_ready
//ready是等待电话-置闲
//talking是正在通话中
//typing 整理态,接完电话后在整理,默认5分钟
//no_answer 久不应答,即响铃后座席未接
//busy 置忙
//rest 小休
curl -H "Content-Type: application/json" -d '{"Extension":"1002","Value":"ready" }' -H "Authorization:Nway token " http://ip:8085/api/extension_callstate
按以下的信息返回排队中的电话信息
Uuid string //呼入的channel的uuid
Number string //呼入的号码
RealCallinNumber string //实际呼入的号码
Group string //进入的组
Level string //保留用于normal,vip
CallinTime time.Time //呼入时间
bash
curl -H "Authorization:Nway token " http://ip:8085/api/queues
按以下的信息返回所有的分机状态信息
go
Extension string
RegStatus string
AgentState string
CallState string
LastStatusChangeTime string
curl -H "Authorization:Nway token " http://ip:8085/api/get_extensions
我们使用redis的pub/sub或rabbitmq模式推送如来电,挂 机等事件,以及来电排队等事件,以及cdr
需要psubscribe event_*
就会将所有的event事件推过来
模式如下:
evt_name,callin_number, dest_number, domain, dtmf, gateway, originate_number, direction, auuid, buuid, origination_dest_number
其中evt_name为以下项:
EVENT_CALLIN EVENT_NAME = 1 + iota //呼入
EVENT_CALLOUT //呼出
EVENT_RING //回铃
EVNET_ALERT //振铃
EVENT_ANSWER //应答
EVENT_HANGUP //座席
EVENT_DTMF //按键
EVENT_PLAYRING //开始放音
EVENT_PLAYSTOP //放音结束
EVENT_PARK //park掉
EVENT_UNPARK //解决park
EVENT_HOLD //hold掉
EVENT_UNHOLD //unhold
EVENT_BRIDGED //已桥接
EVENT_DESTORY //已完全释放
EVENT_TALKING //正在通话中
EVENT_DA //回铃检测
Callin_number为呼入号码,或称为主叫号码
dest_number 目标号码
domain 域,先不用考虑
dtmf, 如果是按键,则这里有值
gateway, 如果是呼出,则这是呼出的gateway名称
originate_number, 原主叫号码
direction, 呼入还是呼出
auuid, 这条通道的uuid
buuid, 关联通道的uuid
origination_dest_number 原始被叫号码
如果是mq,则类似于以下
pushstr := "{\"type\":\"event\"," +
"\"event_name\":\"" + strStatus + "\"," +
"\"aleg_uuid\":\"" + auuid + "\"," +
"\"bleg_uuid\":\"" + buuid + "\"," +
"\"callin_number\":\"" + callin_number + "\"," +
"\"dest_number\":\"" + dest_number + "\"," +
"\"domain\":\"" + domain + "\"," +
"\"dtmf\":\"" + dtmf + "\"," +
"\"gateway\":\"" + gateway + "\"," +
"\"originate_number\":\"" + originate_number + "\"," +
"\"direction\":\"" + direction + "\"," +
"\"origination_dest_number\":\"" + origination_dest_number + "\"}"
面向座席,则只需要监视以下消息
呼给座席
{
"type":"event",
"method":"callout",
"cti_ip":"10.1.213.29",
"uuid":"7ba750aa-c138-11eb-8bdf-fd851cbd5dad",
"number":"18638737767",
"group":"120",
"extension":"1018",
"level":"normal",
"callin_time":"2021-05-30 17:00:02"
}
座席无应答
{
"type":"event",
"method":"noanswer",
"cti_ip":"10.1.213.29",
"uuid":"7ba750aa-c138-11eb-8bdf-fd851cbd5dad",
"number":"18638737767",
"group":"120",
"extension":"1018",
"level":"normal",
"callin_time":"2021-05-30 17:00:02"
}
座席应答
{
"type":"event",
"method":"answered",
"cti_ip":"10.1.213.29",
"uuid":"7ba750aa-c138-11eb-8bdf-fd851cbd5dad",
"number":"18638737767",
"group":"120",
"extension":"1018",
"level":"normal",
"callin_time":"2021-05-30 17:00:02"
}
座席挂断
{
"type":"event",
"method":"hangup",
"cti_ip":"10.1.213.29",
"uuid":"7ba750aa-c138-11eb-8bdf-fd851cbd5dad",
"number":"18638737767",
"group":"120",
"extension":"1018",
"level":"normal",
"callin_time":"2021-05-30 17:00:02"
}
以前采用http推送模式,虽然也没什么影 响,但后来还是采用redis或进一步放个大点的mq等的来完成推送消息的过程
psubscribe cdr_*
其中,主叫,被叫,如果是呼入到座席,那么中间经过了几个没有回应或转接的信息都一起推送过来,如代码:
arr := []string{strings.Trim(uuid, " "), //唯 一标识符
strings.Trim(a_caller_id_number, " "), //a路的主叫号码
strings.Trim(a_destination_number, " "), //呼叫的目标号码,如119
strings.Trim(a_start_stamp, " "), //开始时间
strings.Trim(a_answer_stamp, " "), //应答时间
strings.Trim(a_end_stamp, " "), 结束时间
strings.Trim(a_duration, " "), 总持续时长
strings.Trim(a_billsec, " "), 实际通话时间
strings.Trim(a_sip_hangup_disposition, " "), 哪边挂边
strings.Trim(a_record_file, " "), 录音文件
strings.Trim(str_no_answer_agents, " "), 没有应答的座席号码
strings.Trim(destination_number, " "), 座席号码
strings.Trim(start_stamp, " "), 开始呼叫座席的时间
strings.Trim(answer_stamp, " "), 座席应答的时间
strings.Trim(end_stamp, " "), 座席挂机时间
strings.Trim(duration, " "), 座席
strings.Trim(billsec, " ")}
if len(no_answer_agents) > 0 {
var tmpstr string
tmpstr = "{"
for _, v := range no_answer_agents {
tmpstr += v + ","
}
tmpstr = tmpstr[:len(tmpstr)-1]
tmpstr += "}"
arr = append(arr, tmpstr)
} else {
arr = append(arr, "")
}
如果是mq,则类似于
mqstr := "{\"type\":\"cdr\"," +
"\"uuid\":\"" + strings.Trim(uuid, " ") + "\"," +
"\"a_caller_id_number\":\"" + strings.Trim(a_caller_id_number, " ") + "\"," +
"\"a_destination_number\":\"" + strings.Trim(a_destination_number, " ") + "\"," +
"\"a_start_stamp\":\"" + strings.Trim(a_start_stamp, " ") + "\"," +
"\"a_answer_stamp\":\"" + strings.Trim(a_answer_stamp, " ") + "\"," +
"\"a_end_stamp\":\"" + strings.Trim(a_end_stamp, " ") + "\"," +
"\"a_duration\":\"" + strings.Trim(a_duration, " ") + "\"," +
"\"a_billsec\":\"" + strings.Trim(a_billsec, " ") + "\"," +
"\"a_sip_hangup_disposition\":\"" + strings.Trim(a_sip_hangup_disposition, " ") + "\"," +
"\"a_record_file\":\"" + strings.Trim(a_record_file, " ") + "\"," +
"\"str_no_answer_agents\":\"" + strings.Trim(str_no_answer_agents, " ") + "\"," +
"\"destination_number\":\"" + strings.Trim(destination_number, " ") + "\"," +
"\"start_stamp\":\"" + strings.Trim(start_stamp, " ") + "\"," +
"\"answer_stamp\":\"" + strings.Trim(answer_stamp, " ") + "\"," +
"\"end_stamp\":\"" + strings.Trim(end_stamp, " ") + "\"," +
"\"duration\":\"" + strings.Trim(duration, " ") + "\"," +
"\"billsec\":\"" + strings.Trim(billsec, " ") + "\"}"
即:
{
"type":"cdr",
"cti_ip":"10.1.213.29",
"uuid":"7ba750aa-c138-11eb-8bdf-fd851cbd5dad",
"is_callout":"false",
"a_caller_id_number":"130****8217",
"a_destination_number":"120",
"a_start_stamp":"2021-05-30 16:57:10",
"a_answer_stamp":"2021-05-30 16:57:10",
"a_end_stamp":"2021-05-30 16:57:29",
"a_duration":"19",
"a_billsec":"19",
"a_sip_hangup_disposition":"recv_bye",
"a_record_file":"2021/May/30/18939657757_04ee30b8-c125-11eb-bb04-9180ac6fa0de.wav",
"str_no_answer_agents":"1011",
"destination_number":"1011",
"start_stamp":"2021-05-30 16:57:11",
"answer_stamp":"",
"end_stamp":"2021-05-30 16:57:29",
"duration":"18",
"flag":"单座席无应答",
"billsec":"0"
}
psubscripe queue_*
其大概信息如下:
method, uuid, number, group, level, callin_time
如果是非redis而是mq,则推送如下消息
RedisString := "{\"type\":\"queue\"," +
"\"method\":\"" + method + "\"," +
"\"uuid\":\"" + uuid + "\"," +
"\"number\":\"" + number + "\"," +
"\"group\":\"" + group + "\"," +
"\"level\":\"" + level + "\"," +
"\"callin_time\":\"" + callin_time + "\"}"
入队:
{
"type":"queue",
"method":"nway_queue_add",
"cti_ip":"10.1.213.29",
"uuid":"7ba750aa-c138-11eb-8bdf-fd851cbd5dad",
"number":"130****8217",
"group":"120",
"level":"normal",
"callin_time":"2021-05-30 17:00:01"
}
出队:
{
"type":"queue",
"method":"nway_queue_remove",
"uuid":"7ba750aa-c138-11eb-8bdf-fd851cbd5dad",
"number":"130****8217",
"group":"120",
"level":"normal",
"callin_time":"2021-05-30 19:16:30"
}
psubscripe agent_*
其大概信息如下:
number, status, time
如果是mq,则类似于以下:
RedisString := "{\"type\":\"agent\"," +
"\"number\":\"" + number + "\"," +
"\"status\":\"" + status + "\"," +
"\"time\":\"" + nway_time + "\"}"
#为了减少代码量,所以使用了和监听一样的名称
#EvdedPhone 正在通话的号码
#EvdPhone 要转出的号码
#EvdGateway 如果是外线号码,则需要指定网关
curl -H "Content-Type: application/json" -d '{"EvdedPhone":"100
2","EvdPhone":"1003","EvdGateway":""}' -H "Authorization:Nway
token" http://ip:8085/api/transfer
curl -H "Authorization:Nway token" http://ip:8085/api/answer/1002
curl -H "Authorization:Nway token" http://ip:8085/api/hangup/1002
EvdedPhone 被监听的号码
EvdPhone 由哪个号码监听
EvdGateway 如果是外线号码进行监听,则需要指定网关
curl -H "Content-Type: application/json" -d '{"EvdedPhone":
"1002","EvdPhone":"1003","EvdGateway":""}' -H "Authorization:N
way token " http://ip:8085/api/eavesdrop
为了减少代码量,所以使用了和监听一样的名称
EvdedPhone 邀请加入多方通话的的号码
EvdPhone 邀请加入的多方通话里有哪个号码在通话
EvdGateway 如果是外线号码,则需要指定网关
curl -H "Content-Type: application/json" -d '{"EvdedPhone
":"1002","EvdPhone":"1003","EvdGateway":""}' -H "Authorizatio
n:Nway token " http://192.168.1.115:8085/api/threeway
curl -H "Authorization:Nway token" http://ip:8085/api/hold/1002
bash
curl -H "Authorization:Nway token" http://ip:8085/api/unhold/1002
bash
curl -H "Authorization:Nway token" http://ip:8085/api/phone_hold/1002
bash
curl -H "Authorization:Nway token" http://ip:8085/api/phone_unhold/1002
新建一条路由,比如我们是要呼转给120
进入到路由明细
添加路由明细
但是在添加明细前,需要先添加一个动态组
这里的组id为4
那么这样就配好了一个路由,当有电话呼入时,就走该路由了,按照动态注册上来的座席号进行分配了
接口为:curl -H "Authorization:Nway Token" http://192.168.1.115:8085/api/extension_info/1002
返回说明:
reg_state : 分机是不是注册在线:reged 在线,unreg 不在线
seat_status:座席状态:idle是空闲, busy是置忙
call_state:呼叫状态, ready 是可以接听,talking是正在通话,ring是振铃
配置项
对应的调用接口
call ,直接呼叫 http://127.0.0.1:8899/?method=call&phone=018621575908
hangup,直接挂断
http://127.0.0.1:8899/?method=hangup
answer ,直接接通 http://127.0.0.1:8899/?method=answer
在nwayacd模块中,支持大量的esl配置操作,从而避免还要去操作操作界面等,这样方便相关的开发使用。
freeswitch@internal> show modules mod_nwayacd
type,name,ikey,filename
api,nway_add_ext,mod_nwayacd,/usr/local/freeswitch/mod/mod_nwayacd.so
api,nway_add_group,mod_nwayacd,/usr/local/freeswitch/mod/mod_nwayacd.so
api,nway_busy,mod_nwayacd,/usr/local/freeswitch/mod/mod_nwayacd.so
api,nway_list_exts,mod_nwayacd,/usr/local/freeswitch/mod/mod_nwayacd.so
api,nway_list_groups,mod_nwayacd,/usr/local/freeswitch/mod/mod_nwayacd.so
api,nway_login,mod_nwayacd,/usr/local/freeswitch/mod/mod_nwayacd.so
api,nway_logout,mod_nwayacd,/usr/local/freeswitch/mod/mod_nwayacd.so
api,nway_ready,mod_nwayacd,/usr/local/freeswitch/mod/mod_nwayacd.so
api,nway_rm_ext,mod_nwayacd,/usr/local/freeswitch/mod/mod_nwayacd.so
api,nway_rm_group,mod_nwayacd,/usr/local/freeswitch/mod/mod_nwayacd.so
api,nway_set_ext_jobnumber,mod_nwayacd,/usr/local/freeswitch/mod/mod_nwayacd.so
api,nway_set_reged_ext,mod_nwayacd,/usr/local/freeswitch/mod/mod_nwayacd.so
api,nway_set_ring_group,mod_nwayacd,/usr/local/freeswitch/mod/mod_nwayacd.so
api,nway_set_unreg_ext,mod_nwayacd,/usr/local/freeswitch/mod/mod_nwayacd.so
api,nway_threeway,mod_nwayacd,/usr/local/freeswitch/mod/mod_nwayacd.so
api,nway_uuid_hold,mod_nwayacd,/usr/local/freeswitch/mod/mod_nwayacd.so
api,nway_uuid_unhold,mod_nwayacd,/usr/local/freeswitch/mod/mod_nwayacd.so
api,nwayacd,mod_nwayacd,/usr/local/freeswitch/mod/mod_nwayacd.so
api,nwayacd_transfer,mod_nwayacd,/usr/local/freeswitch/mod/mod_nwayacd.so
api,nwayacd_version,mod_nwayacd,/usr/local/freeswitch/mod/mod_nwayacd.so
application,nway_bridge,mod_nwayacd,/usr/local/freeswitch/mod/mod_nwayacd.so
application,nwayacd,mod_nwayacd,/usr/local/freeswitch/mod/mod_nwayacd.so
application,nwaycallout,mod_nwayacd,/usr/local/freeswitch/mod/mod_nwayacd.so
23 total.
bgapi nway_add_ext 1000 1234
bgapi nway_set_ext_jobnumber 1000 1234 true //最后一项为true或false,代表是否启用,1000为分机,1234为工号
bgapi nway_rm_ext 1000
bgapi nway_set_reged_ext 1000
bgapi nway_set_unreg_ext 1000
bgapi nway_add_group group mode
Usage:bgapi nway_add_group 110 4
mode选项:0,sequence;1,random;2,crycle;3,remember+0;4,remember+1;5,remember+2;
nway_rm_group 110
bgapi nway_set_ring_group group welcome_ring blacklist_ring busy_ring transfer_ring
Usage:bgapi nway_set_ring_group 110 /nway/welcome.wav /nway/black.wav /nway/busy.wav /nway/transfer.wav
bgapi nway_list_exts
列出所有分组
bgapi nway_list_groups
让某分机上线并加入多个组中
bgapi nway_login extension group_list
Usage:bgapi nway_login 1000 120,119,110
让某分机登出,并中止和各组的关联关系
bgapi nway_logout extension
Usage: bgapi nway_logout 1000
呼叫转移
bgapi nwayacd_transfer [uuid] [extension]
Usage: bgapi nwayacd_transfer uuid 1002
将座席置忙
bgapi nway_busy extension
Usage:bgapi nway_busy 1000
将座席置闲
bgapi nway_ready extension
Usage:bgapi nway_ready 1000
输出排队模块的版本
bgapi nwayacd_version
将通话unHold
bgapi nway_uuid_unhold [uuid]
Usage: bgapi nway_uuid_unhold uuid
将通话hold
bgapi nway_uuid_hold [uuid]
三方通话
bgapi nway_threeway [uuid] phone gateway Usage:bgapi nway_uuid_hold ex009-4333444-988kk 018621575908 gw1
nwaycallout
Usage:nwaycallout 18621575908 gw1 110
xml中配置
<action application="nwaycallout" data="$0 test 110"/>
nwayacd
Usage:nwayacd 110
xml中配置
<action application="nwayacd" data="110"/>