概述
主体功能用于来电接听前后,订阅获取关于会话内容的消息推送,实现弹屏展示通话记录内容的相关业务。
旧版弹屏sdk会在坐席接听那刻一次性推送ai和用户聊天的全部消息
新版弹屏sdk会在话术触发转人工后,开始不断推送ai和用户聊天的消息,以及坐席接听后和用户的聊天记录,直到用户或坐席挂断通话。
一个坐席只允许一处登录,多处登录会互踢,被踢的坐席默认会定时3s尝试重新登录连接,此时如果异地登录的账号仍在线则会一直做检测能否登录,直到异地登录的账号退出,多处登录互踢的情况同理。
安装
npm设置私库源
- 参考 《获取94ai前端sdk通用流程》 密码:dbb9
- 执行install命令安装@94ai/aisdk
$ yarn add @94ai/aisdk
# or
$ npm i @94ai/aisdk
# or
$ pnpm add @94ai/aisdk
获取javascript文件
- 参考 《获取94ai前端sdk通用流程》 密码:dbb9
- 执行
npx -y @94ai/aisdk -- sdk-umd
,之后在当前执行命令路径下获取到94aisdk-1.1.2.umd.min.js
tip 获取旧版sdk 执行
npx -y @94ai/aisdk -- sdk-umd --old
,之后在当前执行命令路径下获取到94aisdk-1.1.1-old.umd.min.js
使用
初始化&销毁SDK实例
作为npm包使用
import { aiSDK } from '@94ai/aisdk' // or const { aiSDK } = require('@94ai/aisdk')
export interface UserInfo {
userId: string,
userType: string,
token: string
companyId: string
orgId: string
oldId: string
chainId: string
account:string
userName: string
userTypeName: string
}
export interface SDKConfig {
corpId: string,
secretId: string,
agentId: string,
onSuccess?: Function,
onError?: Function,
onMessage?: Function,
onReconnect?: Function
onSessionEnd?: Function
onKicked?: Function
}
export interface PushData {
/**
* 任务 ID
*/
taskId: string
/**
* 分机号
*/
extensionNumber: string
/**
* 外呼 ID
*/
callid: string
/**
* 外呼 ID
*/
callId: string
/**
* 外呼类型
*/
callType: CallType
/**
* 意向标签
*/
intentTag: string
/**
* 外呼号码
*/
number: string
/**
* 号码 ID
*/
numberMD5: string
/**
* 分配坐席 ID
*/
agentId: number
/**
* 坐席标签
*/
agentTag: string
/**
* 用户标签
*/
tag: string
/**
* AI 话术 ID
*/
templateId: string
chats: {
/**
* 说话内容
*/
"content": string,
/**
* 说话时间
*/
"createTime": string,
/**
* 说话号码
*/
"fromNumber": string
}[]
}
export type Context = SDKConfig & UserInfo
aiSDK.init({ // 👈 初始化SDK实例连接
secretId: '50ab02d3a42f788e6d8f7da1c01a68d7', //必填,secretID
corpId: '392f9b20cf5ff706', //必填,公司ID
agentId: '1860', //必填,坐席ID
onError(err: Error, context: Context) { // 👈 所有出错信息回调函数
console.log(err.message)
},
onSuccess(context: Context) {
console.log('注册订阅成功')
},
onKicked(context: Context) { // 👈 一个坐席只允许一处登录,多处登录会互踢,被踢的坐席默认会定时3s尝试重新登录连接,此时如果异地登录的账号仍在线则会一直做检测能否登录,直到异地登录的账号退出,多处登录互踢的情况同理。
console.log('坐席异地登录,当前被踢出') // 如果不需要重连机制可以在这里执行aiSDK.destroy(),之后如果需要手动连接请再执行aiSDK.init(param)
},
onReconnect(context: Context) { // 👈 当出现服务异常或网络异常或被踢导致连接终断,会尝试重连,重连前会回调该函数,如果不需要重连机制也可以在这里执行aiSDK.destroy()
console.log('尝试重连中...')
},
onSessionEnd(callId: string, context: Context) { // 👈 当一个外呼会话结束会执行此回调
console.log('当前呼叫会话callId:' + callId + '已结束' )
},
onMessage(message: PushData, context: Context) {
// 来电弹屏信息回调函数 👈 根据message.callId区分不同会话,同个会话callId相同会有多次推送,一个坐席会话结束订阅推送会自动终止查询,如需提前终止查询可以执行aiSDK.stopPolling()
console.log(message)
console.log('')
},
})
// 如果使用的是vue,参考如下销毁,其他框架同理
onUnmounted(() => {
aiSDK.destory() // 👈 销毁SDK实例&连接
})
作为JavaScript使用
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>94AI-SDK Demo v1.1.1</title>
</head>
<body>
94AI-SDK Demo
<div style="padding: 10px">
<div style="padding: 5px">secretID secretId: <input type="text" id="secretId"></div>
<div style="padding: 5px">公司ID corpId: <input type="text" id="corpId"></div>
<div style="padding: 5px"> 坐席ID agentId: <input type="text" id="agentId"></div>
<button type="button" id="submit">注册</button>
<button type="button" id="logout">退出</button>
</div>
<div id="angent-message-container"></div>
<script src="94aisdk-1.1.2.umd.min.js"></script>
<script>
document.addEventListener('DOMContentLoaded', () => {
var angentMessageContainer = document.getElementById('angent-message-container')
var secretId = document.getElementById('secretId')
var corpId = document.getElementById('corpId')
var agentId = document.getElementById('agentId')
var secretId_storage = localStorage.getItem('secretId')
var corpId_storage = localStorage.getItem('corpId')
var agentId_storage = localStorage.getItem('agentId')
// 设置默认值
secretId.value = secretId_storage ? secretId_storage : 'db4985b726d673db5db408901b873f3e'
corpId.value = corpId_storage ? corpId_storage : '17687fc0006b7248'
agentId.value = agentId_storage ? agentId_storage : '1859'
var dynamicGenerateDom = (message) => {
var container = document.createElement('div')
var agentIdShow = document.createElement('div')
var agentTag = document.createElement('div')
var callId = document.createElement('div')
var callType = document.createElement('div')
var number = document.createElement('div')
var numberMD5 = document.createElement('div')
var templateId = document.createElement('div')
var tag = document.createElement('div')
var taskId = document.createElement('div')
var hr1 = document.createElement('hr')
var hr2 = document.createElement('hr')
var chatsLog = document.createElement('div')
agentIdShow.innerHTML = `<span>agentId: ${ message.agentId }</span>`
agentTag.innerHTML = `<span>agentTag: ${ message.agentTag }</span>`
callId.innerHTML = `<span>callId: ${ message.callId }</span>`
callType.innerHTML = `<span>callType: ${ message.callType }</span>`
number.innerHTML = `<span>number: ${ message.number }</span>`
numberMD5.innerHTML = `<span>numberMD5: ${ message.numberMD5 }</span>`
templateId.innerHTML = `<span>templateId: ${ message.templateId }</span>`
tag.innerHTML = `<span>tag: ${ message.tag }</span>`
taskId.innerHTML = `<span>taskId: ${ message.taskId }</span>`
chatsLog.innerHTML = `<span>chatsLog: ${ JSON.stringify(message.chats) }</span>`
container.id = message.callId
container.appendChild(agentIdShow)
container.appendChild(agentTag)
container.appendChild(callId)
container.appendChild(callType)
container.appendChild(number)
container.appendChild(numberMD5)
container.appendChild(templateId)
container.appendChild(tag)
container.appendChild(taskId)
container.appendChild(hr1)
container.appendChild(chatsLog)
container.appendChild(hr2)
angentMessageContainer.appendChild(container)
}
var modifyDialogueRecord = (conversation, message) => {
conversation.children[0].innerHTML = `<span>agentId: ${ message.agentId }</span>`
conversation.children[1].innerHTML = `<span>agentTag: ${ message.agentTag }</span>`
conversation.children[2].innerHTML = `<span>callId: ${ message.callId }</span>`
conversation.children[3].innerHTML = `<span>callType: ${ message.callType }</span>`
conversation.children[4].innerHTML = `<span>number: ${ message.number }</span>`
conversation.children[5].innerHTML = `<span>numberMD5: ${ message.numberMD5 }</span>`
conversation.children[6].innerHTML = `<span>templateId: ${ message.templateId }</span>`
conversation.children[7].innerHTML = `<span>tag: ${ message.tag }</span>`
conversation.children[8].innerHTML = `<span>taskId: ${ message.taskId }</span>`
conversation.children[10].innerHTML = `<pre>chatsLog: ${ JSON.stringify(message.chats, null, 4) }</pre>`
}
submit.onclick = () => {
// 保存输入的id信息
localStorage.setItem('secretId', secretId.value)
localStorage.setItem('corpId', corpId.value)
localStorage.setItem('agentId', agentId.value)
var aiSDKObject = {
// 开发环境
secretId: secretId.value, // 必填,secretID
corpId: corpId.value, // 必填,公司ID
agentId: agentId.value, // 必填,坐席ID
onError(err, context) { // 👈 所有出错信息回调函数
console.log(err.message)
},
onSuccess(context) {
console.log('注册订阅成功')
},
onKicked(context) { // 👈 一个坐席只允许一处登录,多处登录会互踢,被踢的坐席默认会定时3s尝试重新登录连接,此时如果异地登录的账号仍在线则会一直做检测能否登录,直到异地登录的账号退出,多处登录互踢的情况同理。
console.log('坐席异地登录,当前被踢出') // 如果不需要重连机制可以在这里执行aiSDK.destroy(),之后如果需要手动连接请再执行aiSDK.init(param)
},
onReconnect(context) { // 👈 当出现服务异常或网络异常或被踢导致连接终断,会尝试重连,重连前会回调该函数,如果不需要重连机制也可以在这里执行aiSDK.destroy(),,之后如果需要手动连接请再执行aiSDK.init(param)
console.log('尝试重连中...')
},
onSessionEnd(callId, context) { // 👈 当一个【外呼会话结束】时会执行此回调,可以用来执行【销毁】 挂载到页面已结束的会话记录
console.log('当前呼叫会话callId:' + callId + '已结束')
},
// 来电弹屏信息回调函数
onMessage(message, context) {
const conversation = document.getElementById(message.callId)
if (conversation) {// 如果是同一会话,则更新
modifyDialogueRecord(conversation, message)
} else { // 如果是不同会话则创建
dynamicGenerateDom(message)
}
},
// 呼叫中
onCalling(callbackData, context) {
console.log('===============呼叫中start报文===============')
console.log('callbackData:' + callbackData)
console.log(callbackData)
console.log('context:')
console.log(context)
console.log('===============呼叫中end报文===============')
},
// 转接人工
onEavesdrop(callbackData, context) {
console.log('===============转接人工start报文===============')
console.log('callbackData:' + callbackData)
console.log(callbackData)
console.log('context:')
console.log(context)
console.log('===============转接人工end报文===============')
},
// 接听
onAnswer(callbackData, context) {
console.log('===============接听start报文===============')
console.log('callbackData:' + callbackData)
console.log(callbackData)
console.log('context:')
console.log(context)
console.log('===============接听end报文===============')
},
// 挂断
onHangup(callbackData, context) {
console.log('===============挂断start报文===============')
console.log('callbackData:' + callbackData)
console.log(callbackData)
console.log('context:')
console.log(context)
console.log('===============挂断end报文===============')
}
}
aiSDK.init(aiSDKObject) // 初始化SDK
}
logout.onclick = () => {
aiSDK.destroy()
}
})
document.addEventListener('unload', () => {
aiSDK.destroy()
})
</script>
</body>
</html>
secretId(必填)
类型:string
由 94AI 运营提供
corpId(必填)
类型:string
由 94AI 运营提供
sid(必填)
类型:string
管理员账号登录 94AI 决策平台,进入坐席管理列表页,查看坐席 ID
参数说明
onSuccess(context)
返回值:void
onError(err,context)
返回值:void
参数名 | 中文名 | 类型 | 必填 | 说明 |
---|---|---|---|---|
err.message | 错误信息 | String | Y | 例: 秘钥错误! 企业不存在或者accessToken不存在! 坐席不存在! |
onReconnect(context)
返回值:void
onKicked(context)
返回值:void
onSessionEnd(callId, context)
返回值:void
onMessage(msg,context)
返回值:void
参数名 | 中文名 | 类型 | 必填 | 说明 |
---|---|---|---|---|
msg.agentId | 分配坐席 ID | Number | Y | 分配坐席 ID |
msg.agentTag | 坐席标签 | String | Y | 建议填写坐席在贵司业务系统唯一标识,用于查询对应 agentId;可以为空。 |
msg.callId | 外呼 ID | String | Y | 例:9b2eb6b8-7a27-4357-b5ec-104450086e24 |
msg.callType | 外呼类型 | Number | Y | 1001:坐席-人工外呼 1002:坐席-AI 外呼-不转人工 1003:坐席-AI 外呼-接通转人工 1004:坐席-AI 外呼-智能转人工 2001:批量-预测外呼 2002:批量-AI 外呼-不转人工 2003:批量-AI 外呼-接通转人工 2004:批量-AI 外呼-智能转人工 2005:批量-语音通知 |
msg.number | 外呼号码 | String | Y | 外呼号码,需要根据后台设置,控制是否脱敏 |
msg.numberMD5 | 号码 ID | String | Y | 外呼号码 ID |
msg.templateId | AI 话术 ID | Number | Y | 外呼的话术模板 ID,可以为空 |
msg.tag | 用户标签 | String | Y | 用户标签,最多 50 个字符 |
msg.taskId | 任务 ID | String | Y | 决策系统中的任务编号 |
msg.chats | 对话记录 | Array | Y | 聊天记录,可以为空 例:[{ "fromNumber":"0", "content": "你好,请问您是王小帅吗?", "createTime": "2019-01-09 14:14:19" }, { "fromNumber":"7945bd83237335e5376ff44d62e4f0ae", "content": "嗯", "createTime": "2019-01-09 14:14:20" }, { "fromNumber":"0", "content": "您在九四平台有一笔贷款,本期应还金额 100 元,已经逾期 1 天了,请问您今天晚上 12 点之前能完成还款吗?", "createTime": "2019-01-09 14:14:21" }] |
chats
参数名 | 中文名 | 类型 | 必填 | 说明 |
---|---|---|---|---|
content | 说话内容 | String | Y | 说话内容 |
createTime | 说话时间 | String | Y | 说话时间,格式:2019-01-09 14:14:19 |
fromNumber | 说话号码 | String | Y | 说话号码,其中 0 为机器人 |
Demo:
{
"number": "13661634186",
"callId": "1",
"numberMD5": "md4",
"templateId": 1,
"agentTag": "agent tag",
"agentId": 1,
"callType": 1,
"taskId": "1",
"tag": "tag",
"chats": [
{
"content": "hello world906",
"createTime": "2021-8-5 19:39:03",
"fromNumber": "136616325478"
},
{
"content": "hello world559",
"createTime": "2021-8-5 19:39:03",
"fromNumber": "136616325478"
},
...
]
}
}