呼叫中心呼叫系统接入
双向回呼微信小程序插件
微信小程序呼叫插件的开通、登录、插件配置、页面调用和授权说明。
微信小程序呼叫插件使用说明
插件接入步骤拆解
1. 联系七鱼技术支持同学,开通微信小程序呼叫插件白名单
2. 业务方服务端实现登录接口,获取小程序插件登录所需的 corp_code、token、appKey和csrfToken
- 业务方小程序通过异步接口向业务方服务端发起请求;
- 业务方服务端需要根据当前登录的客服,获取对应的账号信息,向七鱼服务端发起 http 请求,获取七鱼企业域名和七鱼动态生成的登录口令,并将返回值透传给业务方小程序。业务方服务端 curl 请求样例如下:
接口请求地址
curl -X POST
'http://qyhjcs.qiyukf.com/openapi/ipcc/applets/login?appKey=1c088a89de51d0af457616605f28390f&checksum=f570a5eb049eb803b086e45829b07e48&time=1511832531'
-H 'content-type: application/json;charset=utf-8'
-d '{"staffName": "admin", "fromPage": "APPLETS"}'请求参数
Query
参考 通用说明 - 数据校验
| 参数 | 数据类型 | 是否必须 | 参数说明 |
|---|---|---|---|
| appKey | String | 是 | 企业appkey |
| time | Integer | 是 | 当前 UTC 时间戳,从 1970 年 1 月 1 日 0 点 0 分 0 秒开始到现在的秒数 |
| checksum | String | 是 | SHA1(appSecret + md5 + time), 三个参数拼接的字符串,进行SHA1哈希计算,转化成16进制字符(String,小写) |
Body
| 参数 | 是否必须 | 数据类型 | 参数说明 |
|---|---|---|---|
| staffName | 是 | String | 使用呼叫插件的客服在七鱼系统对应的客服名称(此处对应的参数值为客服账号) |
| fromPage | 是 | String | 区分登录来源,值为固定值’APPLETS’ |
示例
返回示例
接口返回数据为 JSON 格式,返回样例如下:
{
"code": 200, // 错误码,200表示获取成功
"message": "", // 错误提示信息
"result": {
"corp_code": "xxx", // 登录客服对应的七鱼企业域名
"token": "xxx", // 动态登录口令
"appKey": "xxx",
"csrfToken": "xxx",
}
}<u>3.</u><u>接入微信小程序呼叫插件</u>,插件名称为 call-plugin
3.1 在 app.json 文件中引入插件 call-plugin
{
...
"plugins": {
"call-plugin": {
"version": "3.0.0",
"provider": "wx7ff4c8a25efce68b"
}
},
···
}3.2 在页面的 js 文件中引入呼叫插件,使用插件中的动态数据、将插件绑定到页面
const plugin = requirePlugin('call-plugin');
Page({
data: {
// 插件data数据是动态变化的,支持渲染到视图中
...plugin.data,
},
onLoad() {
// 绑定页面
plugin.attach(this);
},
onShow() {
// 长时间离开页面,可能导致状态不同步、长连接断开等问题
// 需要同步状态,确保长连接是连接的状态
plugin.updateData();
},
onUnload() {
// 取消绑定页面
plugin.detach(this);
},
});3.3 如果您想使用网络电话模式进行外呼,需要额外做一些操作:
- 3.3.1 联系网易七鱼技术支持同学,开启多端登录白名单
- 3.3.2 登录微信小程序管理后台,在开发管理-业务域名中,添加域名https://{corpCode}.qiyukf.com,corpCode请咨询网易七鱼技术支持同学获取
- 3.3.3 在页面的wxml文件中引入page-container,内部加载web-view
<!-- toolbarAuthUrl会在插件动态数据中提供,在适当的时机动态变化,开发者无需修改其值 -->
<page-container overlay="{{false}}" position="center" duration="{{0}}" show="{{toolbarAuthUrl}}" bind:beforeleave="handleToolbarAuthError">
<web-view wx:if="{{toolbarAuthUrl}}" src="{{toolbarAuthUrl}}" binderror="handleToolbarAuthError"></web-view>
</page-container>- 3.3.4 在页面的js文件中定义wxml中用到的handleToolbarAuthError方法
Page({
...
// 处理网络电话模式下的外呼异常
handleToolbarAuthError() {
plugin.handleSessionFailed();
},
...
});3.4 插件提供了一系列 API,可以根据自己的业务需要调用
以下代码演示了如何一键登录、通过网络电话服务模式外呼,并在通话结束后自动登出
const plugin = requirePlugin('call-plugin');
const { constants } = plugin;
const { CallMode, CallStatus } = constants; // 服务模式、坐席状态枚举
// 展示信息提示
const showToast = (title) => {
return wx.showToast({
title,
icon: 'none',
duration: 3000,
});
};
Page({
data: {
// 插件data数据是动态的,支持渲染到视图中
...plugin.data,
},
onLoad() {
// 绑定页面
plugin.attach(this);
// 7. 监听会话结束事件,执行登出逻辑
plugin.addEventListener('sessionEnd', this.logoutAfterSession);
},
onShow() {
// 长时间离开页面,可能导致状态不同步、长连接断开等问题
// 需要同步状态,确保长连接是连接的状态
plugin.updateData();
},
onUnload() {
// 8. 页面卸载取消监听事件,避免内存泄漏
plugin.addEventListener('sessionEnd', this.logoutAfterSession);
// 取消绑定页面
plugin.detach(this);
},
handleToolbarAuthError() {
plugin.handleSessionFailed();
},
// 一键登录、外呼
async loginAndCall() {
// 1. 事先调用第2步所述的接口,获取corp_code、token、appKey和csrfToken
// 代码略...
// 2. 调用插件登录接口
const { status: loginStatus, message: loginMessage } =
await plugin.login({ corpCode: corp_code, token, appKey, csrfToken });
showToast(loginStatus ? '登录成功' : loginMessage);
if (!loginStatus) return;
// 3. 设置服务模式为网络电话
const { status: modeStatus, code, message: modeMessage } = await plugin.setMode({
mode: CallMode.WEB,
});
if (!modeStatus) return showToast(modeMessage);
// 4. 设置坐席状态为挂起
const { status, message: statusMessage } = await plugin.setStatus({
status: CallStatus.HANGUP
});
if (!status) return showToast(statusMessage);
// 5. 开启随机外呼模式(您也可以关闭随机外呼模式,指定中继号进行外呼,相关api请参考setDidNumber)
const { status: didNumberRandomStatus, message: didNumberRandomMessage } = await plugin.setDidNumberRandom({ value: true });
if (!didNumberRandomStatus) return showToast(didNumberRandomMessage);
// 6. 外呼
const { status: callOutStatus, message: callOutMessage } =
await plugin.callOut({ phoneNumber: '13000000000' });
showToast(callOutStatus ? '外呼成功' : callOutMessage);
// 调用成功后,会展示web-view页面,用户需要在web-view页面授权使用麦克风
},
async logoutAfterSession() {
// 9. 登出前设置为软电话离线
await plugin.setMode({ mode: CallMode.WEB });
// 10. 登出
plugin.logout();
},
});以下代码演示了如何一键登录、通过双向回呼服务模式外呼,并在通话结束后自动登出
const plugin = requirePlugin('call-plugin');
const { constants } = plugin;
const { CallMode } = constants; // 服务模式枚举
// 展示信息提示
const showToast = (title) => {
return wx.showToast({
title,
icon: 'none',
duration: 3000,
});
};
Page({
data: {
// 插件data数据是动态的,支持渲染到视图中
...plugin.data,
},
onLoad() {
// 绑定页面
plugin.attach(this);
// 5. 监听会话结束事件,执行登出逻辑
plugin.addEventListener('sessionEnd', this.logoutAfterSession);
},
onShow() {
// 长时间离开页面,可能导致状态不同步、长连接断开等问题
// 需要同步状态,确保长连接是连接的状态
plugin.updateData();
},
onUnload() {
// 6. 页面卸载取消监听事件,避免内存泄漏
plugin.addEventListener('sessionEnd', this.logoutAfterSession);
// 取消绑定页面
plugin.detach(this);
},
// 一键登录、外呼
async loginAndCall() {
// 1. 事先调用第1步所述的接口获取corp_code、token、appKey和csrfToken
// 代码略...
// 2. 调用插件登录接口
const { status: loginStatus, message: loginMessage } =
await plugin.login({ corpCode: corp_code, token, appKey, csrfToken });
showToast(loginStatus ? '登录成功' : loginMessage);
if (!loginStatus) return;
// 3. 设置服务模式为双向回呼
const { status, code, message } = await plugin.setMode({
mode: CallMode.CLICK_CALL,
});
if (code === 18051) {
// code为18051,表示未绑定手机号,需要调用plugin.getCaptcha获取短信验证码,再调用plugin.bindPhone绑定手机号。具体逻辑参考demo
// 代码略...
}
if (!status) return showToast(message);
// 4. 外呼
const { status: callOutStatus, message: callOutMessage } =
await plugin.callOut({ phoneNumber: '13000000000' });
showToast(callOutStatus ? '外呼成功' : callOutMessage);
},
async logoutAfterSession() {
// 7. 登出前设置为软电话离线
await plugin.setMode({ mode: CallMode.WEB });
// 8. 登出
plugin.logout();
},
});4. 参考demo
插件 API
插件动态数据(plugin.data)
| 字段 | 类型 | 说明 |
|---|---|---|
| hasLogin | boolean | 是否已登录 |
| mode | 0 | 1 | 2 | 3 | 4 | 服务模式:0-网络电话,1-手机在线,2-SIP 话机,3-双向回呼,4-AXB |
| status | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 坐席状态:0-离线,1-网络电话在线,2-小休,3-通话中,4-手机在线,5-SIP 话机在线,6-挂起,7-处理中,8-自动外呼 |
| phoneStatus | ‘Idle’ | ‘CallingOut’ | ‘WaitingForOthers’ | ‘Speaking’ | ‘Processing’ | 通话状态:Idle-空闲,CallingOut-外呼中,WaitingForOthers-双向回呼本端已接听等待对端接听,Speaking-通话中,Processing-处理中 |
| didNumberRandom | boolean | 是否开启随机外呼模式(开启后,当客服拥有多个外呼号码进行外呼时,将随机使用一个号码进行外呼) |
| didNumberList | string[] | 外呼中继号码列表 |
| didNumber | string | 当前选用的外呼中继号码 |
| toolbarAuthUrl | string | 网络电话模式下执行外呼的web页面的url,需要通过web-view加载 |
插件方法
登录和初始化
login(options: {
corpCode: string; // 七鱼企业code
token: string; // 动态登录口令
appKey: string; // 七鱼appKey
csrfToken: string;
}:Promise<{
status: boolean; // 是否调用成功
message: string; // 错误信息
}>内部逻辑:
- 根据传入参数获取 cookie
- 获取坐席数据(服务模式、坐席状态、im 账号信息等)
- 建立 im 长连接
注意:以上任何一个步骤失败,都会导致登录失败
登出和销毁
logout():Promise<{
status: boolean; // 是否调用成功
message: string; // 错误信息
}>内部逻辑:
- 调用登出接口
- 断开 im 长连接
- 还原插件数据
注意:登出后呼叫插件所有功能将不可用,若想再次启用呼叫功能需重新走一遍功能使用的几个步骤(从登录开始)
设置是否开启随机外呼模式
// 调用成功后,可以看到动态数据didNumberRandom被修改
setDidNumberRandom(options: { value: boolean }):Promise<{
status: boolean; // 是否调用成功
message: string; // 错误信息
}>使用场景:
- 当需要指定中继号进行外呼时,应该先调用setDidNumberRandom将didNumberRandom设置为false,再调用setDidNumber设置中继号,然后使用callOut外呼
- 当无需指定中继号进行外呼时,可以先调用setDidNumberRandom将didNumberRandom设置为true,直接使用callOut外呼
设置当前选用的外呼中继号码
// 调用成功后,可以看到动态数据didNumber被修改
setDidNumber(didNumber: string): void使用场景:
- 当需要指定中继号进行外呼时,应该先调用setDidNumberRandom将didNumberRandom设置为false,再调用setDidNumber设置中继号,然后使用callOut外呼
- 外呼中继号码didNumber可以从动态数据didNumberList中选取
设置服务模式
setMode(options: {
mode: 0 | 3; // 服务模式;0-网络电话,3-双向回呼
}):Promise<{
status: boolean; // 是否设置成功
code: number; // 错误码
message: string; // 错误信息
}>内部逻辑:
- 设置服务模式
- 设置坐席状态为该服务模式下的默认状态(网络电话对应离线,双向回呼对应手机在线)
注意:使用手机在线或双向回呼模式之前,要绑定客服手机号,为了确保手机号为客服所有,要先获取手机验证码,校验通过后再绑定手机号。错误码为 18051,即表示客服未绑定手机号,需要调用 plugin.getCaptcha 获取短信验证码,再调用 plugin.bindPhone 绑定手机号。具体逻辑参考 demo
设置坐席状态
setStatus(options: {
status: 0 | 6; // 坐席状态;0-离线,6-挂起
}):Promise<{
status: boolean; // 是否设置成功
message: string; // 错误信息
}>使用场景:
- 在服务模式为网络电话时支持调用。设置为离线,坐席无法外呼;设置为挂起,坐席可以外呼
外呼
callOut(options:{
phoneNumber: string; // 外呼号码
}):Promise<{
status: boolean; // 是否外呼成功
message: string; // 错误信息
}>内部逻辑:
- 校验 im 长连接状态
- 校验服务模式是否为网络电话/双向回呼
- 校验坐席状态是否为挂起/手机在线
- 校验是否不在通话中
- 校验外呼号码是否为空
- 校验外呼号码是否在黑名单中
- 如果以上条件均校验通过,使用当前服务模式、当前中继号策略进行外呼
- 通话结束后不会进入处理中状态
注意:微信小程序中,仅网络电话/双向回呼服务模式才支持外呼
强制更新数据
updateData():Promise<{
status: boolean; // 是否调用成功
message: string; // 错误信息
}>内部逻辑:
- 未登录状态下不会执行任何逻辑
- 获取坐席数据(服务模式、坐席状态、im 账号信息等)
- 建立 im 长连接
使用场景:
- 长时间离开页面,可能导致状态不同步、长连接断开等问题。需要在页面展示时(onShow 生命周期)调用
- 插件登录时,需要获取初始数据,建立 im 长连接(插件内部已处理)
- 网络状态从断开变为已连接时,需要更新数据,确保 im 已连接(插件内部已处理)
获取短信验证码
getCaptcha(options:{
mobile: string; // 本机号码
}):Promise<{
status: boolean; // 是否获取成功
message: string; // 错误信息
}>使用场景:
- 调用设置服务模式(setMode)API,处理错误码为 18051 的场景。获取短信验证码时间间隔要大于 60 秒
绑定手机号
bindPhone(options:{
mobile: string; // 本机号码
captcha: string; // 调用plugin.getCaptcha获取到的手机号
}):Promise<{
status: boolean; // 是否绑定成功
message: string; // 错误信息
}>使用场景:
- 调用设置服务模式(setMode)API,处理错误码为 18051 的场景,获取到手机验证码后,绑定客服手机号。切换到手机在线/双向回呼模式都会将通话接通至该手机号
处理网络电话模式下的外呼失败
handleSessionFailed():void使用场景:
- 在【插件接入步骤拆解】中的3-3.3-3.3.2中使用
插件事件监听
addEventListener(type: 'sessionStart'|'acceptedByKefu'|'accepted'|'sessionEnd'|'sessionFailed', callback: (data: any) => void): void参数说明:
- type:监听的事件
- callback:监听到事件后需要触发的回调函数
事件含义、事件对象
| 事件 type | 事件对象 data | 说明 |
|---|---|---|
| sessionStart | ISession | 通话开始 |
| acceptedByKefu | {sessionId: number} | 客服接起 |
| accepted | {sessionId: number} | 访客接起 |
| sessionEnd | ISession | 通话结束 |
| sessionFailed | {tip: string} | 外呼失败 |
其中 ISession 为会话信息,具体字段包括
| 字段 | 类型 | 说明 |
|---|---|---|
| sessionId | number | 会话 id |
| direction | 1 | 2 | 会话方向;1-呼入,2-呼出 |
| address | string | 号码归属地 |
| userNumber | string | 访客号码 |
移除事件监听,可以执行:
removeEventListener(type: 'sessionStart'|'acceptedByKefu'|'accepted'|'sessionEnd'|'sessionFailed', callback: (data: any) => void): void注意:由于手机端无法确保网络一直保持连接,通话事件又依赖网络通信,通话事件可能丢失或延迟,请谅解
注意事项
- 如果您在网络电话模式下进行外呼,在通话界面中,无法返回上一级页面,且尽量不要做出离开通话页面的行为(关闭小程序、杀应用、手势返回操作、安卓系统的常驻返回操作等),通话结束后系统将自动返回上级页面
FAQ
- 同一号码外呼两次后无法再次接通
如果对方两次拒接电话,七鱼会限制当天再次拨打号码,防止被投诉。可在第二天重试
- 外呼后通话立刻结束
跟对方确认是否立刻挂断或者设置了号码拦截
这篇文档有帮助吗?