一、场景说明
使用电话条对接,可以将云客服的电话条功能外呼、挂断、转接咨询等能力集成到您自己的业务系统中,在您自己的业务系统使用此功能。 注意:WEBRTC登陆方式请尽可能使用Chrome浏览器并使用HTTPS协议。
二、对接步骤
1、安装
NPM
npm install ue-softphone-sdk
import ueSoftPhone from 'ue-softphone-sdk'
var ue = new ueSoftPhone ({ // 参数 })JS方式安装
固定链接(国内资源)
版本号链接(国际资源)
2、电话条初始化方法
var ue = new ueSoftPhone (Object object)参数:| 属性 | 类型 | 可选值 | 默认值 | 必填 | 说明 |
| accountName | string | — | — | 是 | 座席账号,如6000@ykf |
| password | string | — | — | 与passwordPk任选其一 | 座席密码 |
| passwordPk | string | - | - | 与password任选其一 | 加密后的座席密码,加密逻辑请参考本文档最下方 |
| loginType | string | PSTN / SIP / WEBRTC | PSTN | 否 | 登陆类型 1.手机、2.SIP话机、3.WEBRTC |
| server | string | _ | __ | 否 | callApiUrl |
| isOpenNetwork | boolean | true开启,false关闭 | false | 否 | 是否开启网络检测 |
| pushCallinRingStatistics | boolean | true开启,false关闭 | false | 否 | 坐席callin来电振铃,是否推送ivr按键信息,排队时间,3天内来电次数 |
| pushHangupStatistics | boolean | true开启,false关闭 | false | 否 | 坐席hangup挂机事件事件,是否推送坐席当日通话时长、当日通话次数。 |
| isOpenCallQueue | boolean | true开启,false关闭 | false | 否 | 是否开启呼叫队列,查看实时排队情况 |
| volume | object | interval: 100-5000 默认值500 | false | 否 | 是否开启音量检测。interval为音量检测的间隔 |
| debug | boolean | — | false | 否 | 是否开启控制台日志 |
| success | function | — | — | 否 | 座席初始化成功的回调函数 |
| error | function | — | — | 否 | 座席初始化异常的回调函数 |
| monitor | boolean | false | 否 | 是否开启监控信息推送 | |
| hangupTone | string | default 三声滴挂,default2 一声滴挂 | default | 否 | 挂机铃声选用 |
初始化请求参数示例:
window.ue = new ueSoftPhone({
accountName: '8088@useasy',
password: '123456Aa',
loginType: 'WEBRTC',
success(res) {
console.log(787877,res);
},
error:function(res) {
console.log('error',res);
}
})3、监听通话事件
ue.listenCallEvent(Object object)
ue.listenCallEvent({
success(res) {
console.log(res,'监听通话成功',);
},
message: (res) => {
console.log(res, '接收通话事件成功')
},
event: (res) => {
console.log(res, 'socket互踢')
}
})参数:
| 属性 | 类型 | 可选值 | 默认值 | 必填 | 说明 |
| success | function | — | — | 否 | 事件绑定通道建立成功回调 |
| message | function | — | — | 否 | 通话事件回调 具体看res.data参数说明 |
| error | function | — | — | 否 | 事件绑定异常回调 主要是底层链接ws的异常回调 |
| event | function | — | — | 否 | 捕获相同坐席登录多个的回调 |
object.message
回调函数参数Object res
| 属性 | 类型 | 说明 |
| subType | string | — |
| data | object | — |
Object res.data
| 名称 | 类型 | 说明 |
| accountId | string | 账户编号 |
| agentNumber | string | 座席编号 |
| state | string | 状态编号,0:空闲、1:忙碌、2:呼叫中、3:振铃、4:通话中、5:整理、6:保持、7:静音、8:未连接、9:失效、10:咨询、 11:三方、 12:咨询(被咨询方)、 13:三方(被咨询方)100之后为自定义 |
| stateName | string | 状态名称 |
| callType | string | 通话类型,呼入:callin,外呼:callout,双向呼叫:twoWayCall,外呼任务:callTask,自动外呼:autoCallout |
| queueNumber | string | 技能组编号 |
| customerNumber | string | 客户号码 |
| customerCity | string | 客户城市 |
| customerProvince | string | 客户号码所在省 |
| taskId | string | 任务id |
| eventTime | string | 事件发生时间 |
| defaultState | string | 默认登录状态 |
| defaultStateName | string | 默认登录状态名称 |
| callId | string | 通话ID |
| eventType | string | 通话事件:呼叫:calling,振铃:ring,接通:link,挂机:hangup |
| disNumber | string | 外显号 |
| serviceNumber | string | 服务号 |
| extras | string | 扩展参数 |
| ivrKey | string | ivr按键信息,如1_2,多个按键之间以_分隔开,仅限于callin事件且pushCallinRingStatistics为true的情况下推送 |
| queueDuration | int | 排队时间,单位为秒。仅限于callin事件且pushCallinRingStatistics为true的情况下推送 |
| threeDayCallinTimes | int | 三天内来电次数。仅限于callin事件且pushCallinRingStatistics为true的情况下推送 |
| dailyCallDuration | int | 当日通话时长,单位为秒。仅限于hangup事件且初始化时pushHangupStatistics为true情况下推送 |
| dailyCallTimes | int | 当日通话次数。仅限于hangup事件且初始化时pushHangupStatistics为true情况下推送 |
| dailyConnectTimes | int | 当日接通次数。仅限于hangup事件且初始化时pushHangupStatistics为true情况下推送 |
4、监听网络检测事件
ue.listenCallNetork(监听网络检测事件)
ue.listenCallNetork({
message(res) {
console.log(res);
}
})message返回值
{
delay: 网络检测数值
}| 属性 | 类型 | 说明 |
| success | function | 事件绑定成功回调 |
| error | function | 事件绑定异常回调 |
| message | function | 网络检测事件回调,检测值res以json返回 |
5、监听呼叫队列
可使用此方法监听呼叫队列listenCallQueueEvent
// 监听呼叫队列socket
ue.listenCallQueueEvent({
success(res) {
console.log('监听呼叫队列socket成功',res);
},
message(res) {
console.log(res, '获取呼叫队列数据成功')
}
})初始化队列数据
{
"success": true,
"message": "200 ok!",
"code": "200",
"data": [
{
"accountId": "1090",
"queueNumber": "10000187",
"queueName": "新需求",
"onlineCount": 1,
"idleCount": 1,
"callingCount": 0,
"currentWait": 0,
"online": [
"8006"
],
"groupLeader": [],
"idle": [
"8006"
],
"calling": [],
"currentQueue": []
},
{
"accountId": "1090",
"queueNumber": "10000188",
"queueName": "杨测试",
"onlineCount": 1,
"idleCount": 1,
"callingCount": 0,
"currentWait": 0,
"online": [
"8006"
],
"groupLeader": [],
"idle": [
"8006"
],
"calling": [],
"currentQueue": []
},
{
"accountId": "1090",
"queueNumber": "10000210",
"queueName": "ftest",
"onlineCount": 1,
"idleCount": 1,
"callingCount": 0,
"currentWait": 0,
"online": [
"8006"
],
"groupLeader": [],
"idle": [
"8006"
],
"calling": [],
"currentQueue": []
},
{
"accountId": "1090",
"queueNumber": "10000218",
"queueName": "8073",
"onlineCount": 1,
"idleCount": 1,
"callingCount": 0,
"currentWait": 1,
"online": [
"8006"
],
"groupLeader": [],
"idle": [
"8006"
],
"calling": [],
"currentQueue": [
{
"ivrId": null,
"callId": "740036808283537408",
"queueNumber": "10000218",
"trunkNumber": "02120775542",
"customerNumber": "13520558188",
"displayNumber": "",
"queueStartTime": "2023-11-23 16:54:26",
"waitDuration": 5938869,
"queueName": "8073"
}
]
},
{
"accountId": "1090",
"queueNumber": "10000579",
"queueName": "8006",
"onlineCount": 1,
"idleCount": 1,
"callingCount": 0,
"currentWait": 0,
"online": [
"8006"
],
"groupLeader": [],
"idle": [
"8006"
],
"calling": [],
"currentQueue": []
}
]
}获取socket 呼叫队列
{
"subtype": "queue",
"data": {
"accountId": "1090",
"queueNumber": "10000210",
"queueName": "ftest",
"onlineCount": 1,
"idleCount": 1,
"callingCount": 0,
"currentWait": 0,
"online": [
"8006",
"8010"
],
"groupLeader": [
"8010"
],
"idle": [
"8006"
],
"calling": [],
"currentQueue": []
}
}6、监听通话音量(webtrc模式可用)
可使用此方法监听通话音量listenCallVolume
开启音量检测
ue.listenCallVolume({
success(res) {
console.log('监听音量检测-->success',res);
},
message(res) {
console.log('监听音量检测-->message',res);
},
error(res) {
console.log('监听音量检测-->error',res);
}
})关闭音量检测
window.ue.stopListenVolume({
success(res) {
console.log(res,'关闭音量监听成功')
},
error(error) {
console.log(error,'关闭音量监听失败')
}
})7、获取监控信息
可使用此方法获取监控信息ue.listenMonitor
ue.listenMonitor({
success(res) {
console.log('座席监控信息success', res);
},
message(res) {
// 返回参数说明 type: summary: 监控总览, agent: 座席监控, queue: 服务组监控
console.log(res, '座席监控信息message', res.type);
},
error(res) {
console.log(res, '座席监控信息error');
}
});8、获取机器人转人工随路数据
ue.listenCallEvent(Object object)
ue.listenCallEvent({
success(res) {
console.log(res,'监听通话成功',);
},
message: (res) => {
console.log(res, '接收通话事件成功')
},
event: (res) => {
console.log(res, 'socket互踢')
}
})参数:
| 属性 | 类型 | 可选值 | 默认值 | 必填 | 说明 |
| success | function | — | — | 否 | 事件绑定通道建立成功回调 |
| message | function | — | — | 否 | 通话事件回调 具体看res.data参数说明 |
| error | function | — | — | 否 | 事件绑定异常回调 主要是底层链接ws的异常回调 |
| event | function | — | — | 否 | 捕获相同坐席登录多个的回调 |
object.message
回调函数参数Object res
| 属性 | 类型 | 说明 |
| subType | string | robotEvent |
| data | object | — |
Object res.date.msg
| 属性 | 类型 | 说明 |
| dialog_type | int | 1: 语音机器人 2:客户 |
| content | string | 消息文本内容 |
| create_time | string | 消息产生时间 |
示例
{"data":{"msg":[{"dialog_type":1,"content":"您好,我是汽车专属购车顾问,看到您之前有了解过我们品牌,目前我们有很不错的政策,请问现在还在关注吗?","create_time":"2026-09-16 20:03:56"},{"dialog_type":2,"content":"转人工","create_time":"2026-09-16 20:04:01"}],"callUniqueId":"1112619258619568128"},"subType":"robotEvent"}三、通话能力方法
1、外呼
ue.call.callout(Object object)
参数:
| 属性 | 类型 | 可选值 | 默认值 | 必填 | 说明 |
| customerNumber | string | — | — | 是 | 外呼号码 |
| agentTimeout | string | — | — | 否 | 呼叫座席侧超时时间,默认60秒 |
| customerTimeout | string | — | — | 否 | 呼叫客户侧超时时间,默认120秒 |
| customerDisNumber | string | — | — | 否 | 指定呼叫客户外显号码 |
| agentDisNumber | string | — | — | 否 | 指定呼叫座席外显号码 |
| loginType | string | PSTN / SIP / WEBRTC | PSTN | 否 | 登陆类型 1.手机、2.SIP话机、3.WEBRTC |
| numberGroupName | string | — | — | 否 | 号码组名称,传该值,会查找对应名称的号码组,并根据策略选择外显号。未找到号码组按照没传处理 |
| numberGroupId | string | — | — | 否 | 号码组编号,传该值,会查找对应Id的号码组,并根据策略选择外显号。未找到号码组按照没传处理,号码组名称和id同时存在时,优先根据编号查找号码组 |
| extras | string | — | — | 否 | 自定义参数,通话中通过事件推送,通话后通话记录中可以查询搜索和定位 限制字节数为255个 超出则报错。 |
| success | function | — | — | 否 | 外呼成功回调 |
| fail | function | — | — | 否 | 外呼失败回调 |
| encrypt | string | 0/1 | 0 | 否 | encrypt为1的时候customerNumber需要传加密后的数据,可参考AES加密示例, 该功能自4.0.35版本后开始支持 |
2、挂断
ue.call.hangup(Object object)参数:| 属性 | 类型 | 可选值 | 默认值 | 必填 | 说明 |
| success | function | — | — | 否 | 挂机成功回调 |
| fail | function | — | — | 否 | 挂机失败回调 |
3、保持或取消保持
该方法仅在通话进行中时可以用
ue.call.holdOrUnHold(Object object)参数:| 属性 | 类型 | 可选值 | 默认值 | 必填 | 说明 |
| success | function | — | — | 否 | 调用成功回调 |
| fail | function | — | — | 否 | 调用失败回调 |
| type | string | — | — | 是 | 操作类型 |
object.type 的合法值
| 值 | 说明 |
| 1 | 保持 |
| 2 | 取消保持 |
4、静音或取消静音
该方法仅在通话进行中时可以用
ue.call.muteOrUnMute(Object object)参数:| 属性 | 类型 | 可选值 | 默认值 | 必填 | 说明 |
| success | function | — | — | 否 | 调用成功回调 |
| fail | function | — | — | 否 | 调用失败回调 |
| type | string | — | — | 是 | 操作类型 |
object.type 的合法值
| 值 | 说明 |
| 1 | 静音 |
| 2 | 取消静音 |
5、转接
该方法仅在通话进行中时可以用
ue.call.transfer(Object object)参数:| 属性 | 类型 | 可选值 | 默认值 | 必填 | 说明 |
| success | function | — | — | 否 | 调用成功回调 |
| fail | function | — | — | 否 | 调用失败回调 |
| agentNumber | string | — | — | 否 | 当前座席工号 |
| number | string | — | — | 是 | 转接号码、或转接的座席工号 |
| type | string | — | — | 是 | 转接类型 |
object.type 的合法值
| 值 | 说明 |
| agent | 座席 |
| outline | 外线电话 |
| ivr | 语音导航 |
6、咨询
该方法仅在通话进行中时可以用
ue.call.consult(Object object)参数:| 属性 | 类型 | 可选值 | 默认值 | 必填 | 说明 |
| success | function | — | — | 否 | 调用成功回调 |
| fail | function | — | — | 否 | 调用失败回调 |
| agentNumber | string | — | — | 是 | 当前需要发起咨询的座席工号 |
| number | string | — | — | 是 | 可传入,外线号码, 座席工号, 技能组编号例如:15010xxxx, 8000, 10014640 |
| mode | string | — | — | 是 | 咨询类型 |
object.mode 的合法值
| 值 | 说明 |
| agent | 座席 |
| outline | 外线电话 |
| ivr | 语音导航 |
7、取消咨询
该方法仅在通话且处于咨询状态时可用。可保持咨询状态继续咨询其他人
ue.call.cancelconsult(Object object)参数:
| 属性 | 类型 | 可选值 | 默认值 | 必传 | 说明 |
| success | function | — | — | 是 | 调用成功回调 |
| fail | function | — | — | 是 | 调用失败回调 |
8、结束咨询
该方法仅在通话进行且已经在咨询状态时可用。调用后将挂掉被咨询方,用户听到保持音乐,可再咨询其他人或者调用咨询接回回到和客户的通话
ue.call.endConsult(Object object)参数:| 属性 | 类型 | 可选值 | 默认值 | 必填 | 说明 |
| success | function | — | — | 是 | 调用成功回调 |
| fail | function | — | — | 是 | 调用失败回调 |
9、咨询接回
该方法仅在通话进行且已经在咨询状态时可用。 结束当前咨询,回到跟客户的通话
ue.call.callbackConsult(Object object)参数:| 属性 | 类型 | 可选值 | 默认值 | 必填 | 说明 |
| success | function | — | — | 是 | 调用成功回调 |
| fail | function | — | — | 是 | 调用失败回调 |
10、咨询转接
该方法仅在通话进行且已经在咨询状态时可用。调用后将把当前通话转接给咨询方
ue.call.consultTransfer(Object object)参数:| 属性 | 类型 | 可选值 | 默认值 | 必填 | 说明 |
| success | function | — | — | 是 | 调用成功回调 |
| fail | function | — | — | 是 | 调用失败回调 |
11、三方通话
该方法仅在通话进行且已经在咨询状态时可用。调用后将把咨询方拉入通话,形成三方通话。
ue.call.threeWayCall(Object object)参数:| 属性 | 类型 | 可选值 | 默认值 | 必填 | 说明 |
| success | function | — | — | 是 | 调用成功回调 |
| fail | function | — | — | 是 | 调用失败回调 |
12、满意度评价
该方法仅在通话进行时可用
ue.call.evaluate(Object object)参数:| 属性 | 类型 | 可选值 | 默认值 | 必填 | 说明 |
| success | function | — | — | 否 | 调用成功回调 |
| fail | function | — | — | 否 | 调用失败回调 |
| type | string | — | — | 是 | 要转接的IVRl类型 如SATISFACTION |
13、会议
ue.call.meeting(Object object)参数:| 属性 | 类型 | 可选值 | 默认值 | 必填 | 说明 |
| success | function | — | — | 否 | 调用成功回调 |
| fail | function | — | — | 否 | 调用失败回调 |
| number | string | — | — | 是 | 转接号 |
14、关闭振铃音
用于呼入场景关闭振铃音响铃
ue.muteRing(Object object)
window.ue.muteRing({
success(res) {
console.log(res,'关闭铃声成功')
},
error(error) {
console.log(error,'关闭铃声失败')
}
})
})15、开启或关闭麦克风
该方法仅支持 `WEBRTC` 登录方式,并且需要在通话已建立、本地麦克风音轨存在时调用。其他登录方式调用时会返回失败提示。
ue.webrtc.setMicrophoneEnabled(Object object)
参数:
| 属性 | 类型 | 可选值 | 默认值 | 必填 | 说明 |
| success | function | - | - | 否 | 调用成功回调 |
| fail | function | - | - | 否 | 调用失败回调 |
| enabled | boolean | - | - | 是 | 是否开启麦克风 |
object.enabled 的合法值
| 值 | 说明 |
| true | 开启麦克风 |
| false | 关闭麦克风 |
调用成功返回:
```js
{
success: true,
message: "setMicrophoneEnabled success",
enabled: true
}
```
非 WEBRTC 登录方式调用失败返回:
```js
{
success: false,
message: "当前登录方式不支持麦克风控制,请切换为 WEBRTC 登录方式!"
}
```调用示例:
// 开启麦克风
ue.webrtc.setMicrophoneEnabled({
enabled: true,
success: function (res) {
console.log(res, "开启麦克风成功");
},
fail: function (error) {
console.log(error, "开启麦克风失败");
}
});
// 关闭麦克风
ue.webrtc.setMicrophoneEnabled({
enabled: false,
success: function (res) {
console.log(res, "关闭麦克风成功");
},
fail: function (error) {
console.log(error, "关闭麦克风失败");
}
});16、查询麦克风状态
该方法用于查询当前 WEBRTC 本地麦克风音轨是否开启。需要在 `WEBRTC` 登录方式下,并且本地麦克风音轨已存在时调用。
ue.webrtc.isMicrophoneEnabled()
参数:
无
返回值:
| 类型 | 说明 |
| boolean | true 表示麦克风已开启,false 表示麦克风已关闭或当前没有可用的本地麦克风音轨 |
示例:
const enabled = ue.webrtc.isMicrophoneEnabled();
if (enabled) {
console.log("麦克风已开启");
} else {
console.log("麦克风已关闭或暂无可用麦克风音轨");
}17、监控方法
调用监控方法前,需要初始化软电话条,且monitor需要是true
1、监控条件查询(开启监控)
window.ue.sdkMonitorMsg({
type: ['agent','summary','queue'], //监控类型 summary: 监控总览, agent: 座席监控, queue: 服务组监控
requestMsg: {
pageNumber: pageNum, // 页码 必传参数
pageSize: 10, //一页能展示多少数据 必传参数
agentNumber:'22, //座席工号 非必传参数
queueNumber:'', //服务组号码 非必传参数
stateName:["未连接","忙碌","空闲","开会","就餐","下午茶","整理"], //服务组号码 非必传参数
sortList:[ //排序状态 非必传参数 asc升序 desc降序
{"field":"agentNumber","orderBy":"asc"},
{"field":"stateDuration","orderBy":"desc"},
{"field":"stateName",
"orderBy":["忙碌","未连接","空闲","开会","就餐","整理","呼叫中","振铃","通话中","保持","静音","失效","咨询","三方","签出","离线接听"]}
]
},
success(res) {
console.log(res, '设置监控请求参数成功');
},
error(error) {
console.log(error, '设置监控请求参数失败');
}
});2、监听
window.ue.call.listen({
agentNumber: phoneNumber, //必传 被监听的座席工号
success(res) {
console.log('监听成功', res);
},
fail(error) {
console.log('监听失败', error);
}
});3、 抢接
window.ue.call.loot({
agentNumber: phoneNumber, //必传 被抢接的座席工号
success(res) {
console.log('抢接成功', res);
},
fail(error) {
console.log('抢接失败', error);
}
});4、 强拆
window.ue.call.forcedHangup({
agentNumber: phoneNumber, //必传 被强拆的座席工号
success(res) {
console.log('强拆成功', res);
},
fail(error) {
console.log('强拆失败', error);
}
});5、强插
window.ue.call.breakIn({
agentNumber: phoneNumber, //必传 被强插的座席工号
success(res) {
console.log('强插成功', res);
},
fail(error) {
console.log('强插失败', error);
}
});6、耳语
window.ue.call.whisper({
agentNumber: phoneNumber, //必传 被耳语的座席工号
success(res) {
console.log('耳语成功', res);
},
fail(error) {
console.log('耳语失败', error);
}
});7、监控监听关闭
window.ue.closeSdkMonitor({
type: ['agent','summary','queue'], //监控类型
success(res) {
console.log(res, '关闭成功');
},
error(error) {
console.log(error, '关闭失败');
}
});四、坐席相关方法
1、切换接听方式
ue.agent.switchLoginType(Object object)参数:| 属性 | 类型 | 可选值 | 默认值 | 必填 | 说明 |
| loginType | string | PSTN / SIP / WEBRTC | PSTN | 是 | 登陆类型 1.手机、2.SIP话机、3.WEBRTC |
| loginNumber | string | — | 系统绑定的手机号 或者 SIP号 | 否 | 手机模式:需要更换坐席绑定的手机号时,该字段传新的绑定手机号。不需要更改时不传 |
| success | function | — | — | 否 | 更新成功回调函数 |
| fail | function | — | — | 否 | 更新失败回调函数 |
2、获取电话条状态列表
ue.agent.findPhoneBarList(Object object)参数:| 属性 | 类型 | 可选值 | 默认值 | 必填 | 说明 |
| success | function | — | — | 否 | 获取成功回调函数 |
| fail | function | — | — | 否 | 获取失败回调函数 |
object.success
回调函数参数Object res
| 属性 | 类型 | 说明 |
| success | boolean | 执行是否成功 |
| data | array | 电话条状态列表 |
data object
数组里的对象值Object
| 属性 | 类型 | 说明 |
| name | string | 状态名称 |
| number | string | 切换状态值 |
3、切换电话条状态
ue.agent.switchPhoneBar(Object object)参数:| 属性 | 类型 | 可选值 | 默认值 | 必填 | 说明 |
| stateNumber | string | — | — | 是 | 切换状态值 |
| success | function | — | — | 否 | 获取成功回调函数 |
| fail | function | — | — | 否 | 获取失败回调函数 |
object.success
回调函数参数Object res
| 属性 | 类型 | 说明 |
| success | boolean | 执行是否成功 |
object.fail
回调函数参数Object res
| 属性 | 类型 | 说明 |
| message | string | 错误描述 |
4、退出登录
ue.agent.logout(Object object)参数:| 属性 | 类型 | 可选值 | 默认值 | 必填 | 说明 |
| toAnsweroffline | string | '0'/'1' | '0' | 否 | '0': 不离线接听 '1': 离线接听 |
| success | function | — | — | 否 | 获取成功回调函数 |
| fail | function | — | — | 否 | 获取失败回调函数 |
object.success
回调函数参数Object res
| 属性 | 类型 | 说明 |
| success | boolean | 执行是否成功 |
object.fail
回调函数参数Object res
| 属性 | 类型 | 说明 |
| message | string | 错误描述 |
5、获取服务组空闲座席(用于转接)
ue.agent.findIdleAgentsForQueue(Object object)参数:| 属性 | 类型 | 可选值 | 默认值 | 必填 | 说明 |
| success | function | — | — | 否 | 获取成功回调函数 |
| fail | function | — | — | 否 | 获取失败回调函数 |
object.success
回调函数参数Object res
| 属性 | 类型 | 说明 |
| success | boolean | 执行是否成功 |
object.fail
回调函数参数Object res
| 属性 | 类型 | 说明 |
| message | string | 错误描述 |
6、销毁实例
ue.destroy({
success(res) {
console.log('销毁成功', res);
},
fail(error) {
console.log('销毁失败', error);
}
});五、webrtc模式设备操作方法
1、接听
ue.webrtc.accept()2、注册设备
ue.webrtc.connect()3、注销设备
ue.webrtc.disconnect()4、检查设备是否注册
ue.webrtc.isConnected()5、发送DTMF
ue.webrtc.sendDTMF(String)String 的合法值| 值 | 说明 |
| 1 | 1号键 |
| 2 | 2号键 |
| 3 | 3号键 |
| 4 | 4号键 |
| 5 | 5号键 |
| 6 | 6号键 |
| 7 | 7号键 |
| 8 | 8号键 |
| 9 | 9号键 |
| 0 | 0号键 |
| * | *号键 |
| # | #号键 |
六、座席视频通话接入
本文面向使用 Demo 的客户,介绍如何启用座席间视频通话及调用 SDK 提供的 API。视频通话连接由 SDK 管理,使用时无需自行调用视频通话后端接口或管理 SIP 连接。
1. 接入说明
视频通话为可选能力,初始化参数 `enableVideoCall` 默认为 `false`。只有显式设置为 `true`,SDK 才会在电话条登录成功后自动准备视频通话连接。
- 视频通话使用 `ue.videoCall` API。登录成功前不要发起呼叫;可以提前注册事件监听。
- 呼出目标填写被叫座席工号,不是 SIP 用户名。
- 浏览器需要处于 HTTPS 或 localhost 等安全上下文,并取得摄像头、麦克风权限。仅语音呼叫可以使用 `mediaType: "audio"`。
2. 初始化
```js
const ue = new ueSoftPhone({
accountName: "8005@uecs1",
password: "登录密码",
server: "https://app.useasy.cn/api",
enableVideoCall: true,
});
// 登录成功后视频 SIP 注册由 SDK 自动完成。
// 建议在发起呼叫前监听状态,并在收到来电时展示接听界面。
ue.videoCall.on("stateChange", ({ state, detail }) => {
console.log("视频通话状态", state, detail);
});
ue.videoCall.on("incomingCall", ({ caller, callerName, callerSip }) => {
console.log("视频来电", callerName || caller, callerSip);
});
```
`enableVideoCall` 不设置或设为 `false` 时,不启用视频通话。登录成功后连接由 SDK 自动准备,业务侧只需通过 `ue.videoCall` 使用功能。3. 前端 API
发起呼叫
```ts
ue.videoCall.call({
targetExtension: "8006", // 被叫座席工号
mediaType: "video", // "video"(默认)或 "audio"
success: (result) => console.log("呼叫已发起", result),
fail: (error) => console.error("呼叫失败", error),
});
````call()` 返回 `Promise<void>`。`targetExtension` 必填;视频连接尚未就绪、已有进行中的通话或呼叫失败时会 reject。`success` / `fail` 是可选回调;`fail` 会在部分失败路径触发,所有错误处理请以 Promise 的 `try/catch` 为准。成功表示呼叫邀请已提交,不代表对方已经接听;接通状态以 `accepted` 事件为准。
发起视频呼叫时,浏览器会先请求摄像头和麦克风权限;授权成功后 SDK 才继续呼叫。拒绝授权或设备不可用时不会发起呼叫。如果之前选择了拒绝,浏览器通常不会再次弹授权框;请在浏览器地址栏的站点权限设置中重新允许摄像头和麦克风,再点击呼叫重试,无需重新初始化 SDK。权限提示期间可调用 `hangup()` 取消本次呼叫准备。
业务侧传入的 `targetExtension` 始终是被叫座席工号。
接听、拒绝和挂断
```js
await ue.videoCall.answer({ mediaType: "video" }); // 来电接听;默认视频
await ue.videoCall.reject(); // 拒绝当前来电
await ue.videoCall.hangup(); // 挂断当前来电或通话
```
没有待处理来电时调用 `answer()` 或 `reject()` 会失败。`hangup()` 在当前没有会话时不做任何操作。
媒体流与设备控制
```js
ue.videoCall.on("media", ({ localStream, remoteStream }) => {
if (localStream) {
localVideo.srcObject = localStream;
void localVideo.play().catch(() => {}); // 浏览器可能要求用户手势后播放
}
if (remoteStream) {
remoteVideo.srcObject = remoteStream;
void remoteVideo.play().catch(() => {});
}
});
ue.videoCall.setCameraEnabled(false); // 关闭本地视频轨道
ue.videoCall.setMicrophoneEnabled(false); // 静音本地音频轨道
const cameraOn = ue.videoCall.isCameraEnabled();
const microphoneOn = ue.videoCall.isMicrophoneEnabled();
````getLocalStream()` 和 `getRemoteStream()` 分别返回当前本地、远端 `MediaStream`,尚无流时返回 `null`。摄像头/麦克风开关方法在对应轨道尚不存在时返回 `false`,成功修改轨道时返回 `true`。它们控制当前通话的轨道,不会重新申请设备权限。
4. 事件
所有事件通过 `ue.videoCall.on(event, callback)` 监听。`on` 返回取消监听函数;也可以调用 `ue.videoCall.off(event, callback)` 取消指定监听。
| 事件 | 负载 | 说明 |
| --- | --- | --- |
| `stateChange` | `{ state, detail }` | 状态变化。状态值:`idle`、`connecting`、`registered`、`calling`、`ringing`、`inCall`、`ended`、`failed`、`disconnected`。`detail` 随状态变化,可能包含阶段、方向、目标或错误信息。 |
| `incomingCall` | `{ caller, callerSip, callerName, invitation }` | 收到来电时触发。`caller` 是主叫座席工号,`callerName` 可能为空;`callerSip` 是连接标识。`invitation` 为 SDK 内部对象,业务侧无需使用。 |
| `progress` | `{ direction, target }` | SIP 会话进入呼叫协商阶段。`direction` 为 `incoming` 或 `outgoing`。 |
| `accepted` | `{ direction, target }` | 通话接通。 |
| `ended` | `{ direction, target }` | 会话结束,包括本端或对端挂断。 |
| `failed` | `{ error, ... }` | 初始化、网络或呼叫过程发生错误;附加字段依失败阶段而异。 |
| `media` | `{ localStream, remoteStream }` | 通话建立或媒体轨道更新时触发。流可能暂时为 `null`,应按需更新视频元素。 |
呼入铃声在收到来电时播放,接听或拒绝时停止;已接通会话结束时播放项目内挂断提示音。
5. 释放与注意事项
- 收到对端挂断或本端结束通话后,SDK 会停止本地音视频轨道,释放摄像头和麦克风占用。
- 调用电话条实例的 `destroy()` 时,SDK 会结束视频会话、注销 SIP 并关闭独立连接。无需业务侧单独管理视频 SIP 连接。
- `enableVideoCall` 开启后,当前账户需要具备视频通话权限,并确保浏览器网络可访问视频通话服务。
- 如果状态停留在 `connecting` 或进入 `failed` / `disconnected`,请联系系统管理员检查视频通话服务配置和网络连通性,并查看浏览器控制台错误。
- 自动播放策略可能阻止视频元素播放声音或画面;可在用户点击接听等交互后调用 `video.play()`。
七、常见问题及处理方案
1、通话会出现无声
通话无声都是由于未处理互踢逻辑,座席多处注册导致语音流未流向正常座席导致的。可在listenCallEvent里监听互踢,如另一处登录,则销毁上一处实例,禁止多处登录。注意:使用时需把电话条升级到3.0.5以上版本
window.ueSoftphone.listenCallEvent({
event: res => {
console.log('互踢触发');
}})2、uniapp前端APP接入电话条功能的麦克风权限获取方案
一、问题背景
在 uniapp 前端开发的 APP 中直接接入电话条功能时,出现 “没麦克风权限” 的报错,原因是电话条 JS 依赖浏览器环境获取权限,而 uniapp 打包的 APP 本身的权限配置无法直接传递给电话条 JS。
二、解决方案
采用 “中间 H5 页面转接权限” 的方式,步骤如下:
- 单独部署一个H5 页面,在该 H5 中集成电话条功能(即对接
ue-softphone-sdk); - 在 uniapp 的 APP 中,通过
webview组件引入这个 H5 页面; - 让 uniapp 的 APP 将麦克风权限授予
webview(webview会模拟浏览器环境,使电话条 JS 能正常获取权限)。
三、核心逻辑
电话条功能的 JS SDK 是基于浏览器环境获取麦克风权限的,因此需要借助
webview充当 “浏览器载体”,让权限能被电话条 JS 识别到。
七、其他
1、 软电话条密码加密方法
1. 咨询云客服管理员,获取加密密钥secret_pk
2. 使用密钥对密码做加密,得到passwordPk
前端加密示例:
#加密示例#
password为原密码
secret_pk为密钥
const PUBLIC_KEY = decodeURIComponent(Base64.decode(secret_pk));
const encryptor = new JSEncrypt();
encryptor.setPublicKey(PUBLIC_KEY);
const md5Password = md5(password);
const passwordPk = encryptor.encrypt(md5Password);java加密示例:
import org.apache.commons.codec.digest.DigestUtils;
import javax.crypto.Cipher;
import java.nio.charset.StandardCharsets;
import java.security.KeyFactory;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;
public class Main {
public static String encrypt(String str, String publicKey) throws Exception {
byte[] decoded = org.apache.commons.codec.binary.Base64.decodeBase64(publicKey);
RSAPublicKey pubKey = (RSAPublicKey) KeyFactory.getInstance("RSA").generatePublic(new X509EncodedKeySpec(decoded));
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.ENCRYPT_MODE, pubKey);
String outStr = Base64.getEncoder().encodeToString(cipher.doFinal(str.getBytes("UTF-8")));
return outStr;
}
public static void main(String[] args) throws Exception {
String publicKey = ${secret_pk};
String message = ${password};
String md5 = DigestUtils.md5Hex(message);
String messageEn = encrypt(md5, base64ToString(publicKey));
System.out.println(messageEn);
}
public static String base64ToString(String base64String) {
return new String(Base64.getDecoder().decode(base64String), StandardCharsets.UTF_8);
}
}