## 预测式外呼
>[info] **功能说明**
> 预测式外呼是一种基于数据分析和机器学习的外呼方式,它通过预测客户接通电话的概率和坐席的空闲状态,自动发起外呼,并将接通的电话自动分配给座席,以提高工作效率。
> 2:这种外呼方式可以有效地过滤无效号码,避免座席拨打无效号码的浪费时间。
* **名词解释**
* 队列:预测式外呼中所使用的队列是“fifo队列”,是一个“生产者一一消费者”的模式,即来话或去话相当于生产者,而座席则相当于消费者,它对来话进行服务即相当于“消费”生产者生产的内容。fifo是先入先出模式,即最先进入队列的客户电话,最先被座席接听,也就相当于生活中的排队模式。
* offhook座席:座席的SIP电话,呼入到队列并等待(队列会给座席放等候音乐),座席一直不挂机,当客户应答后客户电话转入到队列,队列会自动把客户电话(生产者)平均分配给已经在队列中等待的座席(消费者),座席这种接听电话的方式就叫:offhook座席。“offhook座席”在繁忙的通话场景中能更迅速地为客户提供更快速的服务。
* 签入:座席(消费者角色)进入队列,在"offhook座席"场景中,"offhook座席"呼入到队列就是签入。
* 签出:已经进入队列的座席(消费者角色)出队列,在"offhook座席"场景中,"offhook座席"挂机是签出。
* 排队时长:客户电话在队列中等待座席接听的时长(预测式外呼需要尽量减少该时长,越小越好)。
* 通话时长:客户与座席的通话时长,不包含在队列中排队的时长。
* **工作流程**
1. 业务系统调用软交换的API,给客户拨打电话;
2. 软交换开始呼叫客户;
3. 客户接听电话后,软交换将接听的通话转入到fifo队列;
4. 队列将电话转给签入并且空闲的座席。
如图所示:
![](https://img.kancloud.cn/9a/66/9a667acf81378daf78ddacea67b80dac_927x604.png)
* **后端接口**
**获取队列状态接口:**
预测式外呼最重要的工作是需要知道队列中有多少签入并且空闲的座席,后端获取队列状态有两种方式:
1:主动查询软交换;
2:通过前端传会的事件(座席签入,签出,和客户通话桥接,和客户通话断开)。
主动查询软交换获取队列状态API请求地址:
```
{base_url}pbxapi/{api_version}/fifoCount
```
* **请求参数**
| 参数 | 是否必选 | 类型 | 描述 |
| --- | --- | --- | --- |
| fifoName | 否 | string | 队列名称,如果不传或值为空则表示查询所有队列 |
* **响应参数**
| 参数 | 类型 | 描述 |
| --- | --- | --- |
| status | string | 请求结果:success:成功,failed:失败。|
| data | array | 队列当前实时状态。 |
| data. fifo_name | string | 队列名称 |
| data. consumer_count | int | 签入座席的合计数量(即消费者),空闲与通话的都算 |
| data.waiting_caller | int | 正在排队的客户数量,已经与座席通话的不算 |
| data. idle_consumer | int | 空闲的座席数量 |
| msg | string | 如果返回failed,对失败原因的描述。|
* **响应示例**
```
{
"status": "success",
"data": [{
"fifo_name": "6501",
"consumer_count": "1",
"waiting_caller": "0",
"idle_consumer": "1"
}, {
"fifo_name": "6500",
"consumer_count": "0",
"waiting_caller": "0",
"idle_consumer": "0"
}],
"msg": "查询成功"
}
```
提交外呼数据接口:
```
{base_url}pbxapi/{api_version}/predictive
```
* **请求参数**
| 参数 | 是否必选 | 类型 | 描述 |
| --- | --- | --- | --- |
| fifoName | 是 | string | 队列名称 |
| callto | 是 | string | 被叫号码,即客户的电话号码 ,如果是多个电话号码,使用逗号分隔 |
| trunkName | 否 | string | 中继名称,如果服务器上接入了多个运营商的中继,可以选择使用哪个运营商的中继线路拨打电话。 |
| trunkNumber | 否 | string | 出局号码,即透传号码,但该功能必须运营商支持透传号码才能生效。 |
| callPrefix | 否 | string | 外呼前缀,如果运营商要求号码加前缀,则需要提交该数据。 |
| customerId | 否 | string | 客户编号,与点击外呼相同 |
| UID | 否 | string | 与点击外呼相同 |
| relationID | 否 | string | 与点击外呼相同 |
| callbackData | 否 | string | json字符串格式,本次通话的客户数据,如客户ID,案件ID等等,在通话完毕回调时会原样回调,与点击外呼相同。 |
| callbackDomain | 否 | string | 回调地址,与点击外呼相同 |
* **响应参数**
| 参数 | 类型 | 描述 |
| --- | --- | --- |
| status | string | 请求结果:success:成功,failed:失败。|
| msg | string | 如果返回failed,对失败原因的描述。 |
* **响应示例**
```
{
"status": "success",
"msg": "预测外呼数据提交成功"
}
```
* **前端接口**
前端使用webrtc,此处仅描述与点击外呼webrtc不同的地方(会提供预测外呼的webrtc的demo)
1:增加全局变量
在js中增加全局变量window.session,如:
![](https://img.kancloud.cn/1f/ff/1fff4dcf013a0a33fcd0c94e28ae464e_1025x387.png)
在通话建立时,给window.session复制,如:
![](https://img.kancloud.cn/8e/b6/8eb6a947299d0e2cac6b886f0bf7534f_637x301.png)
在通话结束后,将window.session设置为:undefined,如:
![](https://img.kancloud.cn/57/05/57052409ac25d129626bfc0eff22b772_623x305.png)
这样做的目的是,座席可以对当前通话的session进行操作,如发送dtmf等,以下会用到。
1:签入
签入其实就是使用webrtc拨打队列号码,但是注意,需要加前缀:fifo-,如队列名词是:6500,那么webtrc拨打的号码就是:fifo-6500,队列名称需要从后端获取。
~~~
$('#btn_call').click(function() {
var telnum = 'fifo-6500';//队列号码,从后端获取
var session = phone.call(telnum);
});
~~~
签入与点击外呼基本相同,只是签入每次呼的号码都是固定的。
2:签出
签出其实就是挂机,与点击外呼挂机一样
3:挂断客户电话
如果客户主动挂机,则座席无需操作,如果客户不挂机,座席则可以向服务器发送dtmf的方式挂断本次通话,挂断或座席还在队列,没有签出。
~~~
$('#btn_dtmf').click(function() {
if (window.session) {
window.session.sendDTMF('*');//发送dtmf给服务器,服务器挂断电话
}
});
~~~
* **前端事件**
当有事件产生,服务器会给前端webrtc发送事件,事件有:
| 序号 | 事件名称 | 描述 |
| --- | --- | --- |
| 1| consumer_start | 座席签入|
| 2 | consumer_stop | 座席签出|
| 3| bridge-caller-start | 座席开始与客户通话|
| 3 | bridge-caller-stop | 座席与客户通话断开|
前端上的状态或计时,都可以根据以上事件开发。
**座席签入事件格式:**
```
{
"action": "consumer_start",
"sipNumber": "90000002",
"fifoName": "6501"
}
```
**座席签出事件格式:**
```
{
"action": "consumer_stop",
"sipNumber": "90000002",
"fifoName": "6501"
}
```
**座席开始与客户通话事件格式:**
```
{
"action": "bridge-caller-start",
"trunkName": "GSM",
"fifoName": "6500",
"callfrom": "90000002",
"callto": "18600118300",
"trunkNumber": "18600647467",
"customerId": "111",
"UID": "222",
"relationID": "444",
"type": "predictive"
}
```
**座席与客户通话断开事件格式:**
```
{
"action": "bridge-caller-stop",
"trunkName": "GSM",
"fifoName": "6500",
"callfrom": "90000002",
"callto": "18600118300",
"trunkNumber": "18600647467",
"customerId": "111",
"UID": "222",
"relationID": "444",
"type": "predictive"
}
```