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,其状态同上
WebSocket接口说明