Callcenter API
WebSocket 接口使用说明
认证接口
简介
推荐使用分机 token 进行认证。
参数介绍
- login: 用户名,格式是
号码@域名
,如1000@192.168.1.141
。 - passwd: 密码,如果有 token 且认证通过,则不会验证该参数的准确性。
- xui_sessid:分机 token,该参数认证通过,则不会验证密码参数准确性。
- sessid:代表客户端的唯一 ID,使用该 ID 进行身份认证。认证通过之后,使用接口都可以携带上该值即可免认证。
例子:
websocket.send(' \ [{ \ "jsonrpc": "2.0", \ "method": "login", \ "id": 1, \ "params": { \ "login": "1001@xswitch.cn", \ "passwd": "x", \ "loginParams": { \ "xui_sessid": "e35b168e-80a9-4c2b-97c8-6f0044e7302b" \ }, \ "sessid": "0a17169a-cb66-453c-9a5e-c405b59d9bbf" \ } \ }] \ ')
返回值
成功
- 返回值:
[{ "jsonrpc": "2.0", "id": 1, "result": { "message": "logged in" } }]
失败
返回以下结果:
[{"jsonrpc":"2.0","id":1,"error":{"code":code,"message":some reason}}]
如
[ { "jsonrpc": "2.0", "id": 1, "error": { "code": -32001, "message": "Authentication Failure" } } ]
坐席签入接口
接口通过调用 FreeSWITCH 的 JSON API,最终功能由 ccc.lua 实现
参数介绍
- agent: 坐席的工号,如 10001,如果有对应的组,则是<组名>.<工号>,如果 default.1000
- queue: 队列编号,如 11101
- extn:对应的分机号
- func:ccLogin
例子:
websocket.send(' \ [{ \ "jsonrpc": "2.0", \ "method": "jsapi", \ "params": { \ "command": "lua", \ "data": { \ "method": "ccc", \ "func": "ccLogin", \ "data": { \ "agent": "default.10001", \ "queue": "default", \ "extn": "1001" \ } \ }, \ "sessid": "0a17169a-cb66-453c-9a5e-c405b59d9bbf" \ }, \ "id": 16 \ }] \ ')
触发事件
签入及示忙事件,表示坐席已经签入成功。注意如果有个多个队列,会收到多个签入事件,客户端需要进行处理。
签入事件:
{ "eventChannel": "vcc.default.10001" "eventType": "agentStatus", "data": { "action": "login", "queueID": "default", "state": "LOGIN", "extn": "1001", "agentID": "10001", "groupID": "default" }, }
示忙事件:
{ "eventType": "agentStatus", "eventChannel": "vcc.default.10001", "data": { "state": "UNREADY", "callState": "IDLE", "timestamp": "1579342154958618", "agentID": "10001", "groupID": "default" } }
返回值
成功
- 返回值:
[{ "jsonrpc": "2.0", "id": 1, "result": { "code": 200, "message": "+OK\\n" } }]
失败
返回以下结果:
[{"jsonrpc":"2.0","id":1,"result":{"code":code,"message":some reason}}]
如,缺少参数:
[ { "jsonrpc": "2.0", "id": 1, "result": { "code": 500, "reason": "missing required param: agent" } } ]
坐席签出接口
参数介绍
- agent: 坐席的工号,如 10001,如果有对应的组,则是<组名>.<工号>,如果 default.10001
- queue: 队列编号,可选参数
- func:ccLogout
例子:
websocket.send( ' \ [{ \ "jsonrpc": "2.0", \ "method": "jsapi", \ "params": { \ "command": "lua", \ "data": { \ "method": "ccc", \ "func": "ccLogout", \ "data": { \ "agent": "default.10001", \ "queue": "default" \ } \ }, \ "sessid": "0a17169a-cb66-453c-9a5e-c405b59d9bbf" \ }, \ "id": 16 \ }] \ ' );
触发事件
签出成功会触发事件,注意由于可能有多个队列,只有签出最后一个队列,才会收到该事件
{ "eventChannel": "vcc.default.10001", "eventType": "agentStatus", "data": { "action": "logout", "agentID": "10001", "state": "LOGOUT", "queueID": "default", "groupID": "default" } }
返回值
成功
- 返回值:
[{ "jsonrpc": "2.0", "id": 1, "result": { "code": 200, "message": "+OK\\n" } }]
失败
返回以下结果:
[{"jsonrpc":"2.0","id":1,"result":{"code":code,"message":some reason}}]
如,缺少参数:
[ { "jsonrpc": "2.0", "id": 1, "result": { "code": 500, "reason": "missing required param: agent" } } ]
坐席示忙接口
参数介绍
- agent: 坐席的工号,如 10001,如果有对应的组,则是<组名>.<工号>,如果 default.10001
- func:ccGoBreak
- reason:示忙的原因
例子:
websocket.send( ' \ [{ \ "jsonrpc": "2.0", \ "method": "jsapi", \ "params": { \ "command": "lua", \ "data": { \ "method": "ccc", \ "func": "ccGoBreak", \ "data": { \ "agent": "default.10001", \ "reason": "have lunch" \ } \ }, \ "sessid": "0a17169a-cb66-453c-9a5e-c405b59d9bbf" \ }, \ "id": 16 \ }] \ ' );
触发事件
{ "eventType": "agentStatus", "eventChannel": "vcc.default.10001", "data": { "callState": "IDLE", "state": "UNREADY", "groupID": "default", "timestamp": "1579357628815409", "agentID": "10001" } }
返回值
成功
- 返回值:
[{ "jsonrpc": "2.0", "id": 1, "result": { "code": 200, "message": "+OK\\n" } }]
失败
返回以下结果:
[{"jsonrpc":"2.0","id":1,"result":{"code":code,"message":some reason}}]
如,缺少参数:
[ { "jsonrpc": "2.0", "id": 1, "result": { "code": 500, "reason": "missing required param: agent" } } ]
坐席示闲接口
参数介绍
- agent: 坐席的工号,如 10001,如果有对应的组,则是<组名>.<工号>,如果 default.10001
- func:ccGoReady
例子:
websocket.send( ' \ [{ \ "jsonrpc": "2.0", \ "method": "jsapi", \ "params": { \ "command": "lua", \ "data": { \ "method": "ccc", \ "func": "ccGoReady", \ "data": { \ "agent": "default.10001" \ } \ }, \ "sessid": "0a17169a-cb66-453c-9a5e-c405b59d9bbf" \ }, \ "id": 16 \ }] \ ' );
触发事件
{ "eventChannel": "vcc.default.10001", "eventType": "agentStatus", "data": { "state": "READY", "groupID": "default", "timestamp": "1579357823737261", "callState": "IDLE", "agentID": "10001" } }
返回值
成功
- 返回值:
[{ "jsonrpc": "2.0", "id": 1, "result": { "code": 200, "message": "+OK\\n" } }]
失败
返回以下结果:
[{"jsonrpc":"2.0","id":1,"result":{"code":code,"message":some reason}}]
如,缺少参数:
[{"jsonrpc":"2.0","id":1,"result":{"code":500,"reason":"missing required param: agent"}}]
保持/解保持
坐席 A 和客户 B 通话中,坐席 A 调用接口进行保持或解除保持。
参数介绍
- agent: 坐席的工号,如 10001,如果有对应的组,则是组名.坐席工号,如 default.10001
- callID:当前通话的坐席的 channel UUID,通过订阅通话事件可以获取
例子:
websocket.send( ' \ [{ \ "jsonrpc": "2.0", \ "method": "jsapi", \ "id": 1, \ "params": { \ "command": "lua", \ "data": { \ "method": "ccc", \ "func": "ccHold/ccUnHold", \ "data": { \ "agent": "default.10001", \ "callID": "e2482af6-99fb-4974-a882-2eecdef7eda1" \ } \ }, \ "sessid": "0a17169a-cb66-453c-9a5e-c405b59d9bbf" \ } \ }] \ ' );
触发事件
{ "eventChannel": "vcc.default.10001", "eventType": "agentStatus", "data": { "agentID": "10001", "partnerUUID": "d169ac24-ad8c-4f93-a895-509c64a45ad5", "queueID": "default", "groupID": "default", "cidNumber": "1011", "cidName": "1011", "timestamp": "1579361785278271", "callDirection": "inbound", "state": "BUSY", "agentUUID": "9df303b5-cf8d-4d56-b0ad-2622ca5be235", "callState": "HOLD" } }
返回值
成功
- 返回值:
[{ "jsonrpc": "2.0", "id": 1, "result": { "code": 200, "message": "success" } }]
失败
返回以下结果:
[{"jsonrpc":"2.0","id":1,"result":{"code":code,"message":some reason}}]
强拆接口
坐席 A 和客户 B 通话中,坐席 C 调用接口将该通话挂断,需要控制相应权限。
参数介绍
- destUUID:被强拆的通话 channel UUID
例子:
websocket.send( ' \ [{ \ "jsonrpc": "2.0", \ "method": "jsapi", \ "id": 1, \ "params": { \ "command": "lua", \ "data": { \ "method": "ccc", \ "func": "ccKill", \ "data": { \ "destUUID": "1516ae2d-30e9-4605-8e57-33b40eaa8849" \ } \ }, \ "sessid": "0a17169a-cb66-453c-9a5e-c405b59d9bbf" \ } \ }] \ ' );
触发事件
通话挂断后,坐席状态会由 BUSY 估计场景变成 READY/UNREADY/ACW
返回值
成功
- 返回值:
[{ "jsonrpc": "2.0", "id": 1, "result": { "code": 200, "message": "success" } }]
失败
返回以下结果:
[{"jsonrpc":"2.0","id":1,"result":{"code":code,"message":some reason}}]
接听接口
用于坐席客户端及 SIP 终端分离的场景,方便远程接听
参数介绍
- destUUID:通话的坐席 channel UUID
例子:
websocket.send( ' \ [{ \ "jsonrpc": "2.0", \ "method": "jsapi", \ "id": 1, \ "params": { \ "command": "lua", \ "data": { \ "method": "ccc", \ "func": "ccAnswer", \ "data": { \ "destUUID": "1516ae2d-30e9-4605-8e57-33b40eaa8849" \ } \ }, \ "sessid": "0a17169a-cb66-453c-9a5e-c405b59d9bbf" \ } \ }] \ ' );
触发事件
{ "eventChannel": "vcc.default.10001", "eventType": "agentStatus", "data": { "agentID": "10001", "partnerUUID": "d169ac24-ad8c-4f93-a895-509c64a45ad5", "queueID": "default", "groupID": "default", "cidNumber": "1011", "cidName": "1011", "timestamp": "1579361785278271", "callDirection": "inbound", "state": "BUSY", "agentUUID": "9df303b5-cf8d-4d56-b0ad-2622ca5be235", "callState": "ANSWERED" } }
返回值
成功
- 返回值:
[{ "jsonrpc": "2.0", "id": 1, "result": { "code": 200, "message": "success" } }]
失败
返回以下结果:
[{"jsonrpc":"2.0","id":1,"result":{"code":code,"message":some reason}}]
挂断接口
坐席 A 调用接口将该通话挂断,需要控制相应权限。
参数介绍
- destUUID:坐席的通话 channel UUID
例子:
websocket.send( ' \ [{ \ "jsonrpc": "2.0", \ "method": "jsapi", \ "id": 1, \ "params": { \ "command": "lua", \ "data": { \ "method": "ccc", \ "func": "ccKill", \ "data": { \ "destUUID": "1516ae2d-30e9-4605-8e57-33b40eaa8849" \ } \ }, \ "sessid": "0a17169a-cb66-453c-9a5e-c405b59d9bbf" \ } \ }] \ ' );
触发事件
通话挂断后,坐席状态会由 BUSY 估计场景变成 READY/UNREADY/ACW
返回值
成功
- 返回值:
[{ "jsonrpc": "2.0", "id": 1, "result": { "code": 200, "message": "success" } }]
失败
返回以下结果:
[{"jsonrpc":"2.0","id":1,"result":{"code":code,"message": "some reason"}}]
呼叫接口
当坐席客户端嵌入软电话功能时,只需要使用软电话的呼叫功能即可。但需要增加扩展参数 cc_agent 用于跟踪坐席状态(待测试及验证)。
单独使用坐席客户端及电话功能时,如单独使用 SIP 硬件话机,则需要使用回呼方式进行呼叫。
回呼模式下,客户端点击号码进行呼叫,系统会先回呼客户端,客户端接通之后呼叫目的号码。
参数介绍
- agent: 坐席的工号,如 10001,如果有对应的组,则是组名.坐席工号,如 default.10001
- extn: 分机号码
- callerNumber:呼出显示的主叫号码
- callerName:呼出显示的主叫名
- destNumber:被叫号码
- auto_answer:话机是否自动应答
- earlyMedia: true/false, 是否使用早期媒体,默认是 false,表示忽略早期媒体
例子:
websocket.send( ' \ [{ \ "jsonrpc": "2.0", \ "method": "jsapi", \ "id": 1, \ "params": { \ "command": "lua", \ "data": { \ "method": "ccc", \ "func": "ccDial", \ "data": { \ "agent": "default.10001", \ "extn": "1001", \ "callerNumber": "10001", \ "calledNumber": "17602112345", \ "destNumber": "17602186644", \ "auto_answer: true \ } \ }, \ "sessid": "0a17169a-cb66-453c-9a5e-c405b59d9bbf" \ } \ }] \ ' );
返回值
成功
- 返回值:
[{ "jsonrpc": "2.0", "id": 1, "result": { "code": 200, "message": "success" } }]
失败
返回以下结果:
[{"jsonrpc":"2.0","id":1,"result":{"code":code,"message":some reason}}]
转接接口
将当前通话转接到另一个坐席或队列或外线号码或评价 IVR。
参数介绍
- agent: 坐席的工号,如 10001,如果有对应的组,则是组名.坐席工号,如 default.10001
- callID:一般传客户端侧的 channel UUID
- callerNumber:呼出显示的主叫号码
- destNumber:目标号码
- type:AGENT/QUEUE/APPRAISAL
- earlyMedia: true/false, 是否使用早期媒体,默认是 false,表示忽略早期媒体
例子:
websocket.send( ' \ [{ \ "jsonrpc": "2.0", \ "method": "jsapi", \ "id": 1, \ "params": { \ "command": "lua", \ "data": { \ "method": "ccc", \ "func": "ccTransfer", \ "data": { \ "agent": "default.10001", \ "callID": "bca1781b-af8b-461e-b31f-02dbd0c37eac", \ "callerNumber": "02131187912", \ "type": "QUEUE", \ "destNumber": "17602112345" \ } \ }, \ "sessid": "0a17169a-cb66-453c-9a5e-c405b59d9bbf" \ } \ }] \ ' );
返回值
成功
- 返回值:
[{ "jsonrpc": "2.0", "id": 1, "result": { "code": 200, "message": "success" } }]
失败
返回以下结果:
[{"jsonrpc":"2.0","id":1,"result":{"code":code,"message":some reason}}]
三方通话接口
简介
坐席 A 和客户 B 通话中,坐席 A 调用接口将空闲的坐席 C 加入,形成三方通话。
参数介绍
- agent: 坐席的工号,如 10001,如果有对应的组,则是组名.坐席工号,如 default.10001
- destExtn:坐席 C 的分机号,如 1002
- destAgent:坐席 C 的工号,如 10002,如果有对应的组,则是组名.坐席工号,如 default.10002
- destPhone:非坐席的 C 的号码,如 15666099898
- callID:当前通话的 channel UUID
- callerNumber:显示的主叫号码
- callerName:显示的主叫名称
如果第三方为坐席则填写 destExtn 和 destAgent,如果第三方为非坐席人员,则使用 destPhone
例子:
第三方为同组坐席人员,如下:
websocket.send( ' \ [{ \ "jsonrpc": "2.0", \ "method": "jsapi", \ "id": 1, \ "params": { \ "command": "lua", \ "data": { \ "method": "ccc", \ "func": "ccThreeWay", \ "data": { \ "destAgent": "default.10002", \ "destExtn": "1002", \ "callID":"1b596086-ab3c-44c2-8d9c-7e4d951385e0", \ "agent": "default.10001" \ } \ }, \ "sessid": "0a17169a-cb66-453c-9a5e-c405b59d9bbf" \ } \ }] \ ' );
第三方为非坐席人员,如手机号码,示例如下:
websocket.send( ' \ [{ \ "jsonrpc": "2.0", \ "method": "jsapi", \ "id": 1, \ "params": { \ "command": "lua", \ "data": { \ "method": "ccc", \ "func": "ccThreeWay", \ "data": { \ "destPhone": "15666099898", \ "callID":"1b596086-ab3c-44c2-8d9c-7e4d951385e0", \ "agent": "default.10001" \ } \ }, \ "sessid": "0a17169a-cb66-453c-9a5e-c405b59d9bbf" \ } \ }] \ ' );
返回值
成功
- 返回值:
[{ "jsonrpc": "2.0", "id": 1, "result": { "code": 200, "message": "success" } }]
失败
返回以下结果:
[{"jsonrpc":"2.0","id":1,"result":{"code":code,"message":some reason}}]
状态说明
如果 A 客户与 B 坐席通话,B 坐席拉 C 坐席进行三方通话。此时 B 调用三方通话接口后,可通过状态判断通话进行的程度。
- threeway-calling:表示三方正在进行中
- threeway-start:三方成功,并开始
- threeway-end:表示三方结束
- threeway-fail:表示三方未成功并结束
如下所示:
{ "eventChannel": "vcc.default.1005", "eventType": "agentStatus", "data": { "cidName": "1005", "state": "BUSY", "agentID": "1005", "timestamp": "2021-01-23 14:22:14", "cidNumber": "1007", "callStateData": "threeway-start", "callDirection": "outbound", "agentUUID": "268a85a4-cafd-4bc5-92bb-872990f6de31", "groupID": "default", "partnerUUID": "268d3049-e014-4ba4-91e2-95630b3d74f5", "callState": "ANSWERED" }
上述仅对第三方为坐席时可获取,如果第三方非坐席,则没有上述事件。
监听接口
坐席 A 和客户 B 通话中,坐席 C 调用接口监听该通话,需要相应权限。
参数介绍
- agent: 坐席 C 的工号,如 10002,如果有对应的组,则是组名.坐席工号,如 default.10002
- extn: 坐席 C 的分机号,如 1002
- destAgent:坐席 A 的工号,如 10001,如果有对应的组,则是组名.坐席工号,如 default.10001
- destUUID:需要监听通话的 channel UUID
例子:
websocket.send( ' \ [{ \ "jsonrpc": "2.0", \ "method": "jsapi", \ "id": 1, \ "params": { \ "command": "lua", \ "data": { \ "method": "ccc", \ "func": "ccMonitor", \ "data": { \ "destAgent": "default.10001", \ "destUUID": "f1abc9b5-eab7-48fb-837e-3d2ebfcb04e3", \ "agent": "default.10002", \ "extn": "1002" \ } \ }, \ "sessid": "0a17169a-cb66-453c-9a5e-c405b59d9bbf" \ } \ }] \ ' );
返回值
成功
- 返回值:
[{ "jsonrpc": "2.0", "id": 1, "result": { "code": 200, "message": "success" } }]
失败
返回以下结果:
[{"jsonrpc":"2.0","id":1,"result":{"code":code,"message":some reason}}]
强插(抢话)
坐席 A 和客户 B 通话中,坐席 C 调用接口直接与客户 B 通话,坐席 A 挂,注意权限控制。
参数介绍
** agent: 坐席 C 的工号,如 10002,如果有对应的组,则是组名.坐席工号,如 default.10002 ** extn: 坐席 C 的分机号,如 1002
- destAgent:坐席 A 的工号,如 10001,如果有对应的组,则是组名.坐席工号,如 default.10001
- destUUID:需要监听通话的 channel UUID
例子:
websocket.send( ' \ [{ \ "jsonrpc": "2.0", \ "method": "jsapi", \ "id": 1, \ "params": { \ "command": "lua", \ "data": { \ "method": "ccc", \ "func": "ccIntercept", \ "data": { \ "destAgent": "default.10001", \ "destUUID": "f1abc9b5-eab7-48fb-837e-3d2ebfcb04e3", \ "agent": "default.10002", \ "extn": "1002" \ } \ }, \ "sessid": "0a17169a-cb66-453c-9a5e-c405b59d9bbf" \ } \ }] \ ' );
返回值
成功
- 返回值:
[{ "jsonrpc": "2.0", "id": 1, "result": { "code": 200, "message": "success" } }]
失败
返回以下结果:
[{"jsonrpc":"2.0","id":1,"result":{"code":code,"message":some reason}}]
询问
坐席 A 和客户 B 通话中,调用此接口客户 B 处于播放等待音乐,此时坐席 A 与坐席 C 通话,咨询是否方便通话,方便则坐席 A 挂断,坐席 C 直接与客户 B 通话,不方便坐席 C 挂断,则坐席 A 继续与客户 B 通话。
参数介绍
** agent: 坐席 A 的工号,如 1002,如果有对应的组,则是组名.坐席工号,如 default.1002 ** destExtn: 坐席 C 的分机号,如 1003
- destAgent:坐席 C 的工号,如 1003,如果有对应的组,则是组名.坐席工号,如 default.10001
- callID:坐席 A 通话的 channel UUID
例子:
websocket.send( ' \ [{ \ "jsonrpc": "2.0", \ "method": "jsapi", \ "id": 1, \ "params": { \ "command": "lua", \ "data": { \ "method": "ccc", \ "func": "ccConsult", \ "data": { \ "destAgent":"1003", \ "callID":"f2f30dc1-b4ff-48d6-b016-32469e537226", \ "agent":"1002", \ "destExtn":"1003" \ } \ }, \ "sessid": "0a17169a-cb66-453c-9a5e-c405b59d9bbf" \ } \ }] \ ' );
返回值
成功
- 返回值:
[{ "jsonrpc": "2.0", "id": 1, "result": { "code": 200, "message": "success" } }]
失败
返回以下结果:
[{"jsonrpc":"2.0","id":1,"result":{"code":code,"message":some reason}}]
取消询问
坐席 A 和客户 B 通话中,调用此接口客户 B 处于播放等待音乐,此时坐席 A 与坐席 C 通话,咨询是否方便通话。调用此接口则表示不方便通话,坐席 A 继续与客户通话。
参数介绍
- callID:坐席 A 通话的 channel UUID
例子:
websocket.send( ' \ [{ \ "jsonrpc": "2.0", \ "method": "jsapi", \ "id": 1, \ "params": { \ "command": "lua", \ "data": { \ "method": "ccc", \ "func": "ccCancelConsult", \ "data": { \ "callID":"f2f30dc1-b4ff-48d6-b016-32469e537226" \ } \ }, \ "sessid": "0a17169a-cb66-453c-9a5e-c405b59d9bbf" \ } \ }] \ ' );
返回值
成功
- 返回值:
[{ "jsonrpc": "2.0", "id": 1, "result": { "code": 200, "message": "success" } }]
失败
返回以下结果:
[{"jsonrpc":"2.0","id":1,"result":{"code":code,"message":some reason}}]
询问转
坐席 A 和客户 B 通话中,调用此接口客户 B 处于播放等待音乐,此时坐席 A 与坐席 C 通话,咨询是否方便通话。调用此接口则表示方便通话,确定转到坐席 C 上。
参数介绍
- callID:坐席 A 通话的 channel UUID
例子:
websocket.send( ' \ [{ \ "jsonrpc": "2.0", \ "method": "jsapi", \ "id": 1, \ "params": { \ "command": "lua", \ "data": { \ "method": "ccc", \ "func": "ccTransferConsult", \ "data": { \ "callID":"f2f30dc1-b4ff-48d6-b016-32469e537226" \ } \ }, \ "sessid": "0a17169a-cb66-453c-9a5e-c405b59d9bbf" \ } \ }] \ ' );
返回值
成功
- 返回值:
[{ "jsonrpc": "2.0", "id": 1, "result": { "code": 200, "message": "success" } }]
失败
返回以下结果:
[{"jsonrpc":"2.0","id":1,"result":{"code":code,"message":some reason}}]
状态说明
咨询转:A 客户与 B 坐席通话,B 坐席咨询 C 坐席,C 坐席同意的情况下,可以将 A 转给 C。
- consult-calling:表示正在呼叫 C 坐席
- consult-bridge:C 坐席接通
- consult-start:A 与 C 坐席接通(暂无)
- consult-cancel:咨询转取消,一般是 C 接通后,挂断
- consult-end:咨询转正常结束,A 与 C 已经通话后,C 正常挂断(暂无)
- consult-fail:咨询转未成功并结束,一般是呼叫 C 无人接听或拒接
简介
一次性呼叫多个外线号码,接通后转到相应队列中或号码执行路由
TODO ...
订阅事件类接口
通过订阅事件可以实时获取坐席的状态,注意需要控制权限,普通坐席只能订阅自己相关的事件,而班长坐席可以订阅以组为单位的所有事件。
参数
- eventChannel: 订阅的事件类型,如:呼叫中心事件固定以 vcc 开头,如 vcc 则是订阅所有的坐席事件, vcc.组编号 是订阅对应的组的所有的坐席事件,vcc.组编号.坐席工号是订阅对应 ID 的事件。
其他事件如需订阅,则根据需求填写相应的事件名即可。
channel 事件说明:
系统有来话或去话时,将生成一个新的 Channel,并产生 channel_create 事件,该事件包含 Channel 的 UUID,主叫号码、被叫号码、Channel 的创建时间等信息。
如果通话正常进行,则会产生 channel_progress 事件(如,收到对方的 100 或 180 消息),如果应答前收到 183 消息,则产生 channel_progress_media 事件。
如果通话被应答,则产生 channel_answer 事件。
如果一个 channel 与另一个 channel bridge 成功则产生 channel_bridge 事件。
如果通话结束挂机,则产生 channel_hangup 和 channel_hangup_complete 事件。其中 channel_hangup_complete 事件内容更丰富,带有 variable_duration(通话时长)以及 variable_billsec(计费时长)等信息。
订阅通话事件
来电创建事件
websocket.send( ' \ [{ \ "jsonrpc": "2.0", \ "method": "verto.subscribe", \ "params": { \ "eventChannel": "FSevent.channel_create", \ "sessid": "0a17169a-cb66-453c-9a5e-c405b59d9bbf" \ }, \ "id": 14 \ }] \ ' );
事件如下:
Event-Name: CHANNEL_CREATE Core-UUID: 9fd155f9-021a-40a8-bb36-6f1d551cd56e FreeSWITCH-Hostname: 9af9c1f04cd6 FreeSWITCH-Switchname: 9af9c1f04cd6 FreeSWITCH-IPv4: 172.24.0.3 FreeSWITCH-IPv6: ::1 Event-Date-Local: 2021-01-08 14:06:19 Event-Date-GMT: Fri, 08 Jan 2021 06:06:19 GMT Event-Date-Timestamp: 1610085979718087 Event-Calling-File: switch_core_state_machine.c Event-Calling-Function: switch_core_session_run Event-Calling-Line-Number: 630 Event-Sequence: 66336 Channel-State: CS_INIT Channel-Call-State: DOWN Channel-State-Number: 2 Channel-Name: sofia/default/1002@gaofei.local Unique-ID: 9fff4556-08f4-4189-bf6e-f4057952fa33 Call-Direction: inbound Presence-Call-Direction: inbound Channel-HIT-Dialplan: true Channel-Presence-ID: 1002@gaofei.local Channel-Call-UUID: 9fff4556-08f4-4189-bf6e-f4057952fa33 Answer-State: ringing // 振铃中状态 Caller-Direction: inbound Caller-Logical-Direction: inbound Caller-Username: 1002 Caller-Dialplan: XML Caller-Caller-ID-Name: 1002 Caller-Caller-ID-Number: 1002 //主叫号码 Caller-Orig-Caller-ID-Name: 1002 Caller-Orig-Caller-ID-Number: 1002 Caller-Network-Addr: 172.24.0.1 Caller-ANI: 1002 Caller-Destination-Number: 9196 //被叫号码 Caller-Unique-ID: 9fff4556-08f4-4189-bf6e-f4057952fa33 Caller-Source: mod_sofia Caller-Context: default Caller-Channel-Name: sofia/default/1002@gaofei.local Caller-Profile-Index: 1 device_id: 1002 Caller-Profile-Created-Time: 1610085979678288 Caller-Channel-Created-Time: 1610085979678288 //通话开始时间 Caller-Channel-Answered-Time: 0 Caller-Channel-Progress-Time: 0 Caller-Channel-Progress-Media-Time: 0 Caller-Channel-Hangup-Time: 0 Caller-Channel-Transfer-Time: 0 Caller-Channel-Resurrect-Time: 0 Caller-Channel-Bridged-Time: 0 Caller-Channel-Last-Hold: 0 Caller-Channel-Hold-Accum: 0 Caller-Screen-Bit: true Caller-Privacy-Hide-Name: false Caller-Privacy-Hide-Number: false variable_direction: inbound variable_uuid: 9fff4556-08f4-4189-bf6e-f4057952fa33 variable_call_uuid: 9fff4556-08f4-4189-bf6e-f4057952fa33 variable_session_id: 115 variable_sip_from_user: 1002 variable_sip_from_uri: 1002@gaofei.local variable_sip_from_host: gaofei.local variable_video_media_flow: disabled variable_audio_media_flow: disabled variable_text_media_flow: disabled variable_channel_name: sofia/default/1002@gaofei.local variable_sip_call_id: 117462431-6079-260@BJC.BGI.D.BEB variable_sip_local_network_addr: 192.168.3.144 variable_sip_network_ip: 172.24.0.1 variable_sip_network_port: 44552 variable_sip_invite_stamp: 1610085979618123 variable_sip_received_ip: 172.24.0.1 variable_sip_received_port: 44552 variable_sip_via_protocol: udp variable_sip_authorized: true variable_Event-Name: REQUEST_PARAMS variable_Core-UUID: 9fd155f9-021a-40a8-bb36-6f1d551cd56e variable_FreeSWITCH-Hostname: 9af9c1f04cd6 variable_FreeSWITCH-Switchname: 9af9c1f04cd6 variable_FreeSWITCH-IPv4: 172.24.0.3 variable_FreeSWITCH-IPv6: ::1 variable_Event-Date-Local: 2021-01-08 14:06:19 variable_Event-Date-GMT: Fri, 08 Jan 2021 06:06:19 GMT variable_Event-Date-Timestamp: 1610085979618123 variable_Event-Calling-File: sofia.c variable_Event-Calling-Function: sofia_handle_sip_i_invite variable_Event-Calling-Line-Number: 10593 variable_Event-Sequence: 66331 variable_sip_number_alias: 1002 variable_sip_auth_username: 1002 variable_sip_auth_realm: gaofei.local variable_number_alias: 1002 variable_requested_user_name: 1002 variable_requested_domain_name: gaofei.local variable_record_stereo: true variable_transfer_fallback_extension: operator variable_toll_allow: domestic,international,local variable_outbound_caller_id_name: FSXUI variable_outbound_caller_id_number: 0000000 variable_callgroup: techsupport variable_user_context: default variable_accountcode: 1002 variable_caller_id_name: 1002 variable_effective_caller_id_name: 1002 variable_xdomain: gaofei.local variable_x_xui_audio_record: false variable_effective_caller_id_number: 1002 variable_user_name: 1002
来电响铃中
websocket.send( ' \ [{ \ "jsonrpc": "2.0", \ "method": "verto.subscribe", \ "params": { \ "eventChannel": "FSevent.channel_progress", \ "sessid": "0a17169a-cb66-453c-9a5e-c405b59d9bbf" \ }, \ "id": 14 \ }] \ ' );
应答
websocket.send( ' \ [{ \ "jsonrpc": "2.0", \ "method": "verto.subscribe", \ "params": { \ "eventChannel": "FSevent.channel_answer", \ "sessid": "0a17169a-cb66-453c-9a5e-c405b59d9bbf" \ }, \ "id": 14 \ }] \ ' );
桥接 bridge
websocket.send( ' \ [{ \ "jsonrpc": "2.0", \ "method": "verto.subscribe", \ "params": { \ "eventChannel": "FSevent.channel_answer", \ "sessid": "0a17169a-cb66-453c-9a5e-c405b59d9bbf" \ }, \ "id": 14 \ }] \ ' );
通话结束
websocket.send( ' \ [{ \ "jsonrpc": "2.0", \ "method": "verto.subscribe", \ "params": { \ "eventChannel": "FSevent.channel_hangup_complete", \ "sessid": "0a17169a-cb66-453c-9a5e-c405b59d9bbf" \ }, \ "id": 14 \ }] \ ' );
事件信息
Event-Name: CHANNEL_HANGUP_COMPLETE Core-UUID: 9fd155f9-021a-40a8-bb36-6f1d551cd56e FreeSWITCH-Hostname: 9af9c1f04cd6 FreeSWITCH-Switchname: 9af9c1f04cd6 FreeSWITCH-IPv4: 172.24.0.3 FreeSWITCH-IPv6: ::1 Event-Date-Local: 2021-01-08 14:56:57 Event-Date-GMT: Fri, 08 Jan 2021 06:56:57 GMT Event-Date-Timestamp: 1610089017198198 Event-Calling-File: switch_core_state_machine.c Event-Calling-Function: switch_core_session_reporting_state Event-Calling-Line-Number: 947 Event-Sequence: 68486 Hangup-Cause: NORMAL_CLEARING Channel-State: CS_REPORTING Channel-Call-State: HANGUP Channel-State-Number: 11 Channel-Name: sofia/default/1007@192.168.3.144:59925 Unique-ID: 0a768e64-ca6c-44dc-ab5c-347587ad8ea4 Call-Direction: outbound Presence-Call-Direction: outbound Channel-HIT-Dialplan: false Channel-Presence-ID: 1007@gaofei.local Channel-Call-UUID: 0a768e64-ca6c-44dc-ab5c-347587ad8ea4 Answer-State: hangup Hangup-Cause: NORMAL_CLEARING Channel-Read-Codec-Name: G722 Channel-Read-Codec-Rate: 16000 Channel-Read-Codec-Bit-Rate: 64000 Channel-Write-Codec-Name: G722 Channel-Write-Codec-Rate: 16000 Channel-Write-Codec-Bit-Rate: 64000 Caller-Direction: outbound Caller-Logical-Direction: outbound Caller-Caller-ID-Name: 1002 //主叫名称 Caller-Caller-ID-Number: 1002 //主叫号码 Caller-Orig-Caller-ID-Name: 1002 Caller-Orig-Caller-ID-Number: 1002 Caller-Callee-ID-Name: Outbound Call Caller-Callee-ID-Number: 1007 Caller-Network-Addr: 192.168.3.144 Caller-ANI: 1002 Caller-Destination-Number: 1007 Caller-Unique-ID: 0a768e64-ca6c-44dc-ab5c-347587ad8ea4 Caller-Source: src/switch_ivr_originate.c Caller-Transfer-Source: 1610089015:be977ebb-b591-4a21-824f-04ceb87e321d:uuid_br:88a543f7-d184-4868-a8b8-42642fc27351 Caller-Context: default Caller-Channel-Name: sofia/default/1007@192.168.3.144:59925 Caller-Profile-Index: 2 Caller-Profile-Created-Time: 1610089015119185 Caller-Channel-Created-Time: 1610089013758148 Caller-Channel-Answered-Time: 1610089015098191 Caller-Channel-Progress-Time: 1610089013838225 variable_sip_term_status: 200 variable_proto_specific_hangup_cause: sip:200 variable_sip_term_cause: 16 variable_last_bridge_role: originator variable_sip_user_agent: Grandstream GXP1610 1.0.4.128 variable_sip_hangup_disposition: recv_bye variable_bridge_hangup_cause: NORMAL_CLEARING variable_record_file_size: 174124 variable_record_samples: 43520 variable_record_seconds: 5 variable_record_ms: 5440 variable_record_completion_cause: success-silence variable_hangup_cause: NORMAL_CLEARING variable_hangup_cause_q850: 16 variable_digits_dialed: none variable_start_stamp: 2021-01-08 14:56:51 //开始时间 variable_profile_start_stamp: 2021-01-08 14:56:55 variable_answer_stamp: 2021-01-08 14:56:51 //应答时间 variable_bridge_stamp: 2021-01-08 14:56:55 //坐席应答时间 variable_progress_media_stamp: 2021-01-08 14:56:51 variable_end_stamp: 2021-01-08 14:56:57 //结束时间 variable_last_hold_epoch: 0 variable_last_hold_uepoch: 0 variable_hold_accum_seconds: 0 variable_hold_accum_usec: 0 variable_hold_accum_ms: 0 variable_resurrect_epoch: 0 variable_resurrect_uepoch: 0 variable_progress_epoch: 0 variable_progress_uepoch: 0 variable_progress_media_epoch: 1610089011 variable_progress_media_uepoch: 1610089011558359 variable_end_epoch: 1610089017 variable_end_uepoch: 1610089017058232 variable_last_app: callcenter variable_last_arg: yangyang variable_caller_id: "1002" <1002> variable_duration: 6 //通话时长 variable_billsec: 6 // 计费时长 variable_cc_queue: yangyang variable_cc_first_queue: yangyang variable_cc_serving_agent: default.1007 variable_original_destination_number: 9196 //应答后才会这些信息 variable_original_caller_id_name: 1002 variable_original_caller_id_number: 1002
订阅坐席事件例子
websocket.send( ' \ [{ \ "jsonrpc": "2.0", \ "method": "verto.subscribe", \ "params": { \ "eventChannel": "vcc.default.10001", \ "sessid": "0a17169a-cb66-453c-9a5e-c405b59d9bbf" \ }, \ "id": 14 \ }] \ ' );
返回值
成功
[ { jsonrpc: "2.0", id: 14, result: { subscribedChannels: ["vcc.default.10001"], sessid: "0a17169a-cb66-453c-9a5e-c405b59d9bbf", }, }, ];
失败
[ { "jsonrpc": "2.0", "id": 14, "error": "reason ..." } ]
坐席状态
- LOGIN:坐席签入
- LOGOUT:坐席签出
- UNREADY:不可用状态,呼叫失败或坐席主动示忙时会转到该状态
- READY:坐席准备就绪,可以接电话
- BUSY:坐席通话或者响铃中
- ACW:坐席接听完电话后,记录客户信息的状态
坐席通话状态
- CALLING 呼叫中
- RINGING 振铃/新来电
- ANSWERED 正在通话
- IDLE 空闲
坐席状态事件
- eventChannel:格式为 vcc.组编号.坐席工号
- eventType:事件类型,固定为 agentStatus
- state:状态,LOGIN/LOGOUT/READY/UNREADY/BUSY/ACW
- callState:状态,RINGING/CALLCING/ANSWERED/IDLE
- agentID:坐席工号
- extn:坐席分机
- queueID:队列编号
- groupID:组编号
- cidName:主叫名称
- cidNumber:主叫号码
- agentUUID:通话时坐席侧 channel UUID
- partnerUUID:通话时对端侧 channel UUID
- timestamp:时间戳
- callDirection:呼叫方向 //inbound,outbound 均是针对 fs 来说,因此,从坐席方来说,outbound 为呼入,inbound 为呼出
格式为 JSON,如:
{ "eventChannel": "vcc.default.10001", "eventType": "agentStatus", "data": { "state": "BUSY", "callState": "RINGING", "agentID": "10001", "extn": "1001", "queueID": "xyt", "groupID": "default", "cidName": "", "cidNumber": "", "partnerUUID": "72e4889d-e1e3-4ee0-b226-52af4d200ea0", "agentUUID": "7b9eb6c0-13e2-459e-8f06-f13ff48e75c7", "timestamp": "1579357823737261", "callDirection": "outbound" } }
队列呼叫相关事件
当呼叫进入到队列之后产生的呼叫事件,订阅方式如下:
websocket.send( ' \ [{ \ "jsonrpc": "2.0", \ "method": "verto.subscribe", \ "params": { \ "eventChannel": "FSevent.custom::callcenter::info", \ "sessid": "0a17169a-cb66-453c-9a5e-c405b59d9bbf" \ }, \ "id": 14 \ }] \ ' );
callcenter::info 类事件说明如下
一个座席有两个状态标志,分别是 Status 和 States。
Status 是一个座席逻辑上的状态,它有以下几种取值:
- Logged Out:退出服务状态;
- Available:可用状态,可以接电话;
- Available (On Demand):一种特殊的可用状态;
- On Break:座席已登录,但不可以接电话。
States 是跟电话呼叫有关的状态,它有以下几种取值:
- Idle:空闲;
- Waiting:等待接受呼叫;
- Receiving:正在接受呼叫,响铃;
- In a queue call:当前正在一个队列呼叫中。
- Reserved:被分配
事件中 CC-Action 表明事件所属的动作,部分说明如下:
- agent-status-change:当坐席的逻辑状态 status 改变时候对应的事件
- agent-state-change:当坐席的电话呼叫有关状态 state 改变的时候对应的事件
- agent-offering:将坐席分配给队里中的某个来电成员,坐席还没接听时候的事件
- bridge-agent-start:来电成员连接坐席成功
- bridge-agent-end:来电成员和坐席连接断开
- bridge-agent-fail:呼叫坐席失败时产生的事件
- members-count:有通话(主叫来电者)进入或者离开队列时产生的事件,即:排队数。
- member-queue-start:有通话(主叫来电者)呼入加入队列事件
- member-queue-end:有通话(主叫来电者)离开队列事件
参考事件如下:
agent-status-change
{ Event-Subclass: callcenter::info Event-Name: CUSTOM CC-Agent: 1000@default CC-Action: agent-status-change CC-Agent-Status: Available }
agent-state-change
{ Event-Subclass: callcenter::info Event-Name: CUSTOM CC-Agent: 1000@default CC-Action: agent-state-change CC-Agent-State: Receiving }
agent-offering
{ Event-Subclass: callcenter::info Event-Name: CUSTOM CC-Queue: support@default CC-Agent: AgentNameHere CC-Action: agent-offering CC-Agent-System: single_box CC-Member-UUID: 453324f8-3424-4322-4242362fd23d CC-Member-Session-UUID: 600165a4-f748-11df-afdd-b386769690cd CC-Member-CID-Name: CHOUINARD MO CC-Member-CID-Number: 4385551212 }
bridge-agent-start
{ Event-Subclass: callcenter::info Event-Name: CUSTOM CC-Queue: support@default CC-Action: bridge-agent-start CC-Agent: AgentNameHere CC-Agent-System: single_box CC-Agent-UUID: 7acfecd3-ab50-470b-8875-d37aba0429ba CC-Agent-Called-Time: 10000 CC-Agent-Answered-Time: 10009 CC-Member-Joined-Time: 9000 CC-Member-UUID: 453324f8-3424-4322-4242362fd23d CC-Member-Session-UUID: c6360976-231c-43c6-bda7-7ac4c7d1c125 CC-Member-CID-Name: Their Name CC-Member-CID-Number: 555-555-5555 }
bridge-agent-end
{ Event-Subclass: callcenter::info Event-Name: CUSTOM CC-Queue: support@default CC-Action: bridge-agent-end CC-Agent: AgentNameHere CC-Agent-System: single_box CC-Agent-UUID: 7acfecd3-ab50-470b-8875-d37aba0429ba CC-Agent-Called-Time: 10000 CC-Agent-Answered-Time: 10009 CC-Bridge-Terminated-Time: 10500 CC-Member-Joined-Time: 9000 CC-Member-UUID: 453324f8-3424-4322-4242362fd23d CC-Member-Session-UUID: c6360976-231c-43c6-bda7-7ac4c7d1c125 CC-Member-CID-Name: Their Name CC-Member-CID-Number: 555-555-5555 }
bridge-agent-fail
{ Event-Subclass: callcenter::info Event-Name: CUSTOM CC-Queue: support@default CC-Action: bridge-agent-fail CC-Hangup-Cause: CHECK FS HANGUP CAUSE CC-Agent: AgentNameHere CC-Agent-System: single_box CC-Member-UUID: 453324f8-3424-4322-4242362fd23d CC-Member-Session-UUID: c6360976-231c-43c6-bda7-7ac4c7d1c125 CC-Member-CID-Name: Their Name CC-Member-CID-Number: 555-555-5555 }
members-count
{ Event-Subclass: callcenter::info Event-Name: CUSTOM CC-Queue: support@default CC-Action: members-count CC-Count: 1 CC-Selection: Single-Queue }
member-queue-start
{ Event-Subclass: callcenter::info Event-Name: CUSTOM CC-Queue: support@default CC-Action: member-queue-start CC-Member-UUID: 453324f8-3424-4322-4242362fd23d CC-Member-Session-UUID: b77c49c2-a732-11df-9438-e7d9456f8886 CC-Member-CID-Name: CHOUINARD MO CC-Member-CID-Number: 4385551212 }
member-queue-end
{ Event-Subclass: callcenter::info Event-Name: CUSTOM CC-Queue: yang CC-Action: member-queue-end CC-Hangup-Cause: SUCCESS CC-Cause: Terminated CC-Agent: default.1007 CC-Agent-System: single_box CC-Agent-UUID: a49c4fe3-f806-4444-a5e2-a4c938652222 CC-Agent-Called-Time: 1610077451 //呼叫坐席时间 CC-Agent-Answered-Time: 1610077460 //坐席应答时间 CC-Member-Leaving-Time: 1610077574 //坐席结束时间 CC-Member-Joined-Time: 1610077451 CC-Member-UUID: 8de582b9-8eae-4bb1-a954-bbc4fb0cc983 CC-Member-Session-UUID: 180536c8-fb96-482c-b49f-4f6d3027721b CC-Member-CID-Name: 1002 //主叫名 CC-Member-CID-Number: 1002 //主叫号码 }
member-queue-end
{ Event-Subclass: callcenter::info Event-Name: CUSTOM CC-Queue: xiaoshoutest //队列名 CC-Action: member-queue-end CC-Member-Joined-Time: 9000 CC-Member-Leaving-Time: 10050 CC-Cause: Cancel CC-Cancel-Reason: TIMEOUT CC-Member-UUID: 453324f8-3424-4322-4242362fd23d CC-Member-Session-UUID: e260ffd0-a731-11df-9341-e7d9456f8886 CC-Member-CID-Name: Marc O Robinson CC-Member-CID-Number: 5145551212 }
说明:member-queue-end 事件中,如果来电的主叫没有和坐席通话前挂断电话,CC-Cause 的值将会是'Cancel',CC-Cause-Reason 包含了离开队列的原因。如果 CC-Cause 的值为'Terminated' 意味着坐席和主叫已经通过话。
callcenter 排队信息参考
系统默认members-count
为呼叫排队人数,此数量是呼入到队列但没有坐席接听此通话的数量(没有分配到坐席以及虽然分配了坐席,但是坐席还未接听,两种情况都包括在内)
如果上述需求不能满足场景需要,可通过如下事件过程,根据需求获取。
呼叫进入多队列后,会产生member-queue-start
事件,可根据此事件获取来话详细信息,比如主叫、被叫、CC-Member-UUID 等信息。
{ Event-Subclass: callcenter::info Event-Name: CUSTOM CC-Queue: support@default CC-Action: member-queue-start CC-Member-UUID: 453324f8-3424-4322-4242362fd23d CC-Member-Session-UUID: b77c49c2-a732-11df-9438-e7d9456f8886 CC-Member-CID-Name: CHOUINARD MO CC-Member-CID-Number: 4385551212 }
当获取到 agent-offering 事件信息时,说明该呼叫已经被分配到某个坐席
{ Event-Subclass: callcenter::info Event-Name: CUSTOM CC-Queue: support@default CC-Agent: AgentNameHere CC-Action: agent-offering CC-Agent-System: single_box CC-Member-UUID: 453324f8-3424-4322-4242362fd23d CC-Member-Session-UUID: 600165a4-f748-11df-afdd-b386769690cd CC-Member-CID-Name: CHOUINARD MO CC-Member-CID-Number: 4385551212 }
当获取到 bridge-agent-start 事件信息时,说明该呼叫与被分配到的坐席已成功通话
{ Event-Subclass: callcenter::info Event-Name: CUSTOM CC-Queue: support@default CC-Action: bridge-agent-start CC-Agent: AgentNameHere CC-Agent-System: single_box CC-Agent-UUID: 7acfecd3-ab50-470b-8875-d37aba0429ba CC-Agent-Called-Time: 10000 CC-Agent-Answered-Time: 10009 CC-Member-Joined-Time: 9000 CC-Member-UUID: 453324f8-3424-4322-4242362fd23d CC-Member-Session-UUID: c6360976-231c-43c6-bda7-7ac4c7d1c125 CC-Member-CID-Name: Their Name CC-Member-CID-Number: 555-555-5555 }
当获取到 member-queue-end 事件信息时,说明该呼叫已离开队列。
如需业务测展示排队情况,可根据上述过程事件,根据需求获取信息展示即可。
队列话单参考
事件中 CC-Action 表明事件动作,从以下事件中可获取相关参数:
- uuid :CC-Member-Session-UUID //通道唯一 uuid
- 主叫:CC-Member-CID-Name
- 被叫:Other-Leg-Destination-Number") or Caller-Destination-Number
- 队列:CC-Queue
- 服务坐席:CC-Agent
ccAction == member-queue-end
- 坐席 uuid: CC-Agent-UUID
- 开始时间:CC-Member-Joined-Time
- 结束时间:CC-Member-Leaving-Time
- 挂机原因;CC-Cancel-Reason
- 呼叫方向:Call-Direction // inbound 呼入,outbound 呼出
ccAction == bridge-agent-start
- 坐席响铃时间:CC-Agent-Called-Time
- 坐席接听时间:CC-Agent-Answered-Time
挂机后一些时长需要根据事件时间自行算出,如下:
- 排队时长:CC-Agent-Answered-Time - CC-Member-Joined-Time
- 响铃时长:CC-Agent-Answered-Time - CC-Agent-Called-Time
- 通话时长:CC-Member-Leaving-Time - CC-Agent-Answered-Time
通话事件中 CHANNEL_HANGUP_COMPLETE
- 根据 Unique-ID 查找出和坐席 CC-Agent-UUID 相同这个事件,取 variable_billsec 通话时长,variable_duration 总时长
state 坐席的呼叫状态:
{"Unknown", CC_AGENT_STATE_UNKNOWN}, -- 未知 {"Waiting", CC_AGENT_STATE_WAITING}, -- 等待呼叫 {"Receiving", CC_AGENT_STATE_RECEIVING}, -- 响铃 {"In a queue call", CC_AGENT_STATE_IN_A_QUEUE_CALL}, -- 正在通话 {"Idle", CC_AGENT_STATE_IDLE}, -- 空闲 {"Reserved", CC_AGENT_STATE_RESERVED}, -- 被分配
其中:
UNKNOWN 状态为异常状态,可以忽略,基本上很少出现,尤其是 callback 模式
CC_AGENT_STATE_WAITING表示目前坐席呼叫状态是空闲: 此时CC_AGENT_STATUS_LOGGED_OUT对应LOGIN或LOGOUT,LOGIN为第一次add-agent的时候 CC_AGENT_STATUS_ON_BREAK则对应unready
CC_AGENT_STATE_IDLE 是个特殊的空闲状态对应ACW CC_AGENT_STATE_RESERVED 用来标记该坐席已经被分配,可以认为是calling状态
以上状态产生对应的事件即可,需要特殊处理。其事件格式如下:
{ "eventChannel": "vcc.default.10001", "eventType": "agentStatus", "data": { "state": "READY/UNREADY/ACW/LOGIN/LOGOUT", "callState": "", "agentID": "10001", "extn": "1001", "queueID": "default", "groupID": "default", "timestamp": "1579357823737261" } }
CC_AGENT_STATE_RECEIVING表示目前坐席处于响铃状态: CC_AGENT_STATE_IN_A_QUEUE_CALL表示目前坐席处于接通状态: 此时无论status为何种状态,都对应busy。但理论上只会是AVAILABLE和BREAK
上述的状态,坐席都处于通话状态下,但 mod_callcenter 提供的事件不包含 channel 相关字段,且状态不全
则利用 agent 相关事件,这些包含 channel 相关字段
- agent-offering:可以认为是 calling 事件,对应 busy 状态
- agent-ringing:响铃事件,对应 busy 状态(未实现)
- bridge-agent-start:认为坐席 answer 并 bridge 成功,对应 busy,但是可能会失败
- bridge-agent-end:坐席正常挂断,对应 busy
- bridge-agent-fail:坐席呼叫或 bridge 失败,此时的状态需要结合 state/status,其状态同上