@94ai/softphone 5.0.6 → 5.0.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/html-softphone-demo/{index-colony.html → index-local.html} +35 -315
- package/html-softphone-demo/index-open.html +584 -0
- package/html-softphone-demo/index-other.html +586 -0
- package/html-softphone-demo/{index-test.html → index-voice.html} +0 -169
- package/html-softphone-demo/index.html +30 -6
- package/html-softphone-demo/softphone.umd.min.js +1 -1
- package/lib/index.d.ts +12 -5
- package/lib/softphone.cjs.min.cjs +1 -1
- package/lib/softphone.esm-bundler.min.mjs +1 -1
- package/lib/softphone.umd.min.js +1 -1
- package/package.json +1 -1
|
@@ -220,104 +220,7 @@ function bufferToWave(channelData) {
|
|
|
220
220
|
return buffer;
|
|
221
221
|
}
|
|
222
222
|
|
|
223
|
-
/**
|
|
224
|
-
* 0.确保你的企业 【坐席外呼依赖】配置项 是【标识】 (默认是【登录】,如果不确定联系94运维在管理后台查看以及配置)
|
|
225
|
-
* 1. 使用 【https://94ai.yuque.com/staff-kqoz0c/xed39g/vifnf1?singleDoc 《九四智能API开放文档(全)》 密码:wqhg】,该文档有疑问可以找 航航同学
|
|
226
|
-
* - 3.1节 获取坐席信息
|
|
227
|
-
* - 3.2节 修改坐席状态接口,保证坐席状态在线
|
|
228
|
-
* tip: 该文档所有开放接口不支持跨域,如果直接通过ajax需要后端做转接(也可以直接用sdk创建的软电话实例的userAgentManager.requestOpenApi请求,该方法支持跨域同时自带请求签名)
|
|
229
|
-
* - example1:呼叫,也可以直接使用`await userAgentManager.callNumber('15018707394')`
|
|
230
|
-
* - 请求: http://openapi.94ai.com/v1/task/importAgentCustomer
|
|
231
|
-
* - 相当于: userAgentManager.requestOpenApi({
|
|
232
|
-
* url: '/v1/task/importAgentCustomer',
|
|
233
|
-
* data: {
|
|
234
|
-
* agentTag: 'xxx',
|
|
235
|
-
* agentId: 'xxx',
|
|
236
|
-
* callType: 1001,
|
|
237
|
-
* customers: [{ number: 15018707394 }]
|
|
238
|
-
* }
|
|
239
|
-
* })
|
|
240
|
-
* - example2:切换当前坐席小休,也可以直接使用`await userAgentManager.toggleNap(false)`
|
|
241
|
-
* - 请求: http://openapi.94ai.com/v1/agent/updateAgentStatus
|
|
242
|
-
* - 相当于: userAgentManager.requestOpenApi({
|
|
243
|
-
* url: '/v1/agent/updateAgentStatus',
|
|
244
|
-
* data: {
|
|
245
|
-
* agentTag: 'xxx',
|
|
246
|
-
* agentId: 'xxx',
|
|
247
|
-
* agentStatus: 3, // 3: 小休 1: 在线
|
|
248
|
-
* }
|
|
249
|
-
* })
|
|
250
|
-
* - example3:获取当前坐席信息,也可以直接使用`const angentInfo = await userAgentManager.getAgentInfo()`
|
|
251
|
-
* - 请求: http://openapi.94ai.com/v1/agent/getAgent
|
|
252
|
-
* - 相当于: userAgentManager.requestOpenApi({
|
|
253
|
-
* url: '/v1/agent/getAgent',
|
|
254
|
-
* data: {
|
|
255
|
-
* agentTag: 'xxx',
|
|
256
|
-
* agentId: 'xxx',
|
|
257
|
-
* }
|
|
258
|
-
* })
|
|
259
|
-
* 2. 点击连接外呼服务器
|
|
260
|
-
* 3. 在决策外呼一个任务,确保你的坐席账号在任务配置的坐席组里;或手动外呼一个号码(`await userAgentManager.callNumber('15018707394')`)
|
|
261
|
-
* - tip 任务外呼:是先呼用户再呼坐席; 手动外呼:是先呼坐席在呼用户
|
|
262
|
-
* 4. 电话过来后会触发签入注册好的onInvite钩子,这个时候就可以接听,挂断,忽略,转人工,静音等等
|
|
263
|
-
* 5. 处理响应检测这块:
|
|
264
|
-
* - 建议接听/挂断/忽略只做一次性操作(不管失败成功与否无法二次操作,这个sip.js的局限性有一定关系,比如执行一次挂断后sip层的所有状态就被重置了)
|
|
265
|
-
* - 建议转人工可以做多次操作(没转成功 可以操作转多次)
|
|
266
|
-
* - 通讯电话的大多实现也是这样,没有二次挂断/接听/忽略的操作。
|
|
267
|
-
*/
|
|
268
|
-
|
|
269
223
|
document.addEventListener('DOMContentLoaded', async (event) => {
|
|
270
|
-
// try {
|
|
271
|
-
// await new Promise(((resolve, reject) => {
|
|
272
|
-
// navigator.getUserMedia({video: true,audio:true}, function onSuccess(stream) {
|
|
273
|
-
// resolve(stream)
|
|
274
|
-
// }, function onError(error) {
|
|
275
|
-
// reject(error)
|
|
276
|
-
// });
|
|
277
|
-
// }))
|
|
278
|
-
// alert('已点击允许,开启成功');
|
|
279
|
-
// } catch (error) {
|
|
280
|
-
// alert("错误:" + error);
|
|
281
|
-
// }
|
|
282
|
-
// const inputList = []
|
|
283
|
-
// const outputList = []
|
|
284
|
-
// ;(await navigator.mediaDevices.enumerateDevices()).forEach(item => {
|
|
285
|
-
// if (!item.label) return
|
|
286
|
-
// if (item.kind === 'audioinput') inputList.push(JSON.parse(JSON.stringify(item)))
|
|
287
|
-
// else if (item.kind === 'audiooutput') outputList.push(JSON.parse(JSON.stringify(item)))
|
|
288
|
-
// });
|
|
289
|
-
// alert('输入音频列表: ' + JSON.stringify(inputList))
|
|
290
|
-
// alert('输出音频列表: ' + JSON.stringify(outputList))
|
|
291
|
-
|
|
292
|
-
// 输入音频列表:
|
|
293
|
-
// [
|
|
294
|
-
// {"deviceld":"default",
|
|
295
|
-
// "kind":"audioinput",
|
|
296
|
-
// "label":"Default",
|
|
297
|
-
// "groupld":"7a8ef9d53aa7c8f2e5494ea603b1a825696ecfd7b965d69eabbc7b36ca24fde6"
|
|
298
|
-
// },
|
|
299
|
-
// {
|
|
300
|
-
// "deviceld":"dda9a37a56a1c8478824641c3218b30fab09035edccbe047c49f4b43cb273c3d",
|
|
301
|
-
// "kind":"audioinput",
|
|
302
|
-
// "label":"Speakerphone",
|
|
303
|
-
// "groupld":"96c1a27879018de7478bbbd4ac10d6c754c827e2e49b8946ccceea95af5381a7"
|
|
304
|
-
// },
|
|
305
|
-
// {"deviceld":"577a863742550f83e9fffc15465083087ce67abbcd0d1a69ac8a2d7a469c6f56",
|
|
306
|
-
// "kind":"audioinput",
|
|
307
|
-
// "label":"Headsetearpiece",
|
|
308
|
-
// "groupld": "af14e67d688dc0d4b40cb8162ce9794c3f9a0d15b5f5d34817292be3260f9127"
|
|
309
|
-
// }
|
|
310
|
-
// ]
|
|
311
|
-
|
|
312
|
-
// 输出音频列表:
|
|
313
|
-
// [
|
|
314
|
-
// {
|
|
315
|
-
// "deviceld":"default",
|
|
316
|
-
// "kind":"audiooutput",
|
|
317
|
-
// "label":"Default",
|
|
318
|
-
// "groupld": "default"
|
|
319
|
-
// }
|
|
320
|
-
// ]
|
|
321
224
|
const phoneRing = './antique_phone.mp3'
|
|
322
225
|
|
|
323
226
|
/**
|
|
@@ -370,34 +273,6 @@ document.addEventListener('DOMContentLoaded', async (event) => {
|
|
|
370
273
|
getMedia
|
|
371
274
|
} = softphone // 👈 sdk
|
|
372
275
|
|
|
373
|
-
|
|
374
|
-
// const userAgentManager = UserAgentFactory.getUserAgentManager({
|
|
375
|
-
// agentId: 1,
|
|
376
|
-
|
|
377
|
-
// sgOpen: '1',
|
|
378
|
-
// // sg:'1'
|
|
379
|
-
// openBaseUrl:'1',
|
|
380
|
-
|
|
381
|
-
// sign,
|
|
382
|
-
// timestamp,
|
|
383
|
-
// appKey: "910adb209ffe2080",
|
|
384
|
-
// signoverdued(){
|
|
385
|
-
// return get94Aisign().then((res)=> {
|
|
386
|
-
// return res.data;
|
|
387
|
-
// })
|
|
388
|
-
// },
|
|
389
|
-
|
|
390
|
-
// openXhrIntercept(xhr){ // 定制openapi请求头
|
|
391
|
-
// xhr.setRequestHeader('language','en-US');
|
|
392
|
-
// }
|
|
393
|
-
// })
|
|
394
|
-
|
|
395
|
-
/** 方式一:appKey + appSecret + agentTag 获取软电话链接代理实例 */
|
|
396
|
-
// 以下信息采用九四系统的坐席信息接入外呼服务器实现软电话功能
|
|
397
|
-
// agentTag: 'agent1111', // 测试线 坐席维度定位 或用agentId
|
|
398
|
-
// appKey: 'ed96615038ffe394', // 测试线 企业维度定位
|
|
399
|
-
// appSecret: '9fb4aac7b1dbfbb21696bcd7a30cb382', // 测试线 企业维度定位
|
|
400
|
-
|
|
401
276
|
/**
|
|
402
277
|
* 获取软电话代理实例
|
|
403
278
|
*/
|
|
@@ -420,50 +295,6 @@ document.addEventListener('DOMContentLoaded', async (event) => {
|
|
|
420
295
|
enableChatInfoPush: true // 开启会话记录实时推送,开启后,当任务外呼时,可以实时获取通话记录信息,实时回调到refreshChat,中途出现任何异常会回调refreshChatErrorCallback
|
|
421
296
|
})
|
|
422
297
|
|
|
423
|
-
|
|
424
|
-
/** 方式二:extensionNumber + extPassword + wsProtocol + wsRegisterAddress 获取软电话链接代理实例 */
|
|
425
|
-
// 即直接通过【分机号】和【分机密码】以及【外呼服务器地址】实现软电话的直接签入
|
|
426
|
-
// 测试环境不能访问openAPI,可以采用决策系统内部接口获取分机信息接入外呼服务器
|
|
427
|
-
// 生产环境如果采用分机维度的分机信息可以通过agentTag调用openapi获取
|
|
428
|
-
// const extensionNumber = '2839' // 测试线 分机账号
|
|
429
|
-
// const extPassword = 'zjh13542240708' // 测试线 分机密码
|
|
430
|
-
// const wsProtocol = 'ws' // 测试线外呼服务器地址协议
|
|
431
|
-
// const wsRegisterAddress = '192.168.31.239:5066' // 测试线 外呼服务器地址
|
|
432
|
-
// const sipServerHost = `sip:${extensionNumber}@${wsRegisterAddress}` // fs地址
|
|
433
|
-
// const wsAddress = `${wsProtocol}://${wsRegisterAddress}` // socket地址
|
|
434
|
-
|
|
435
|
-
// const extensionNumber = '2510' // 生产线 分机账号
|
|
436
|
-
// const extPassword = 'zengrongzhi123' // 生产线 分机密码
|
|
437
|
-
// const wsProtocol = 'ws' // 生产线 外呼服务器地址协议
|
|
438
|
-
// const wsRegisterAddress = '192.168.31.239:5066' // 生产线 外呼服务器地址
|
|
439
|
-
// const sipServerHost = `sip:${extensionNumber}@${wsRegisterAddress}` // fs地址
|
|
440
|
-
// const wsAddress = `${wsProtocol}://${wsRegisterAddress}` // socket地址
|
|
441
|
-
|
|
442
|
-
// const userAgentManager = UserAgentFactory.getUserAgentManager({
|
|
443
|
-
// authorizationPassword: extPassword, // 分机密码
|
|
444
|
-
// authorizationUsername: extensionNumber, // 分机账号
|
|
445
|
-
// uri: UserAgent.makeURI(sipServerHost), // fs地址
|
|
446
|
-
// transportOptions: {
|
|
447
|
-
// server: wsAddress // socket地址
|
|
448
|
-
// },
|
|
449
|
-
// logLevel: 'error', // 日志等级,默认error
|
|
450
|
-
// viaHost, // fp.umd.min.js生成的唯一值,用来配查呼叫问题,可以不传,内部会自动生成
|
|
451
|
-
// contactName: extensionNumber, // sip协议要求,同分机账号即可,注意类型为string, 不传默认同分机账号
|
|
452
|
-
// refreshSpeekVolumn(value) { // 当来电接通时,实时查看坐席说话的音量实际传送到给对方的音量大小
|
|
453
|
-
// volumn.innerText = value
|
|
454
|
-
// },
|
|
455
|
-
// refreshRequirementCheck(value) { // 权限网络检测
|
|
456
|
-
// browserSoftphoneEnv.innerText = JSON.stringify(value, null, 2)
|
|
457
|
-
// },
|
|
458
|
-
// refreshChat(info) {
|
|
459
|
-
// chatInfo.innerText = JSON.stringify(info, null, 2)
|
|
460
|
-
// },
|
|
461
|
-
// refreshChatErrorCallback(e) {
|
|
462
|
-
// console.log(e)
|
|
463
|
-
// },
|
|
464
|
-
// enableChatInfoPush: true // 开启会话记录实时推送,开启后,当任务外呼时,可以实时获取通话记录信息,实时回调到refreshChat,中途出现任何异常会回调refreshChatErrorCallback
|
|
465
|
-
// })
|
|
466
|
-
|
|
467
298
|
/**
|
|
468
299
|
* 获取坐席当前状态信息(注意牵扯到openAPI的信息需要angentId,即方式一。如果通过方式二需要手动使用userAgentManager.requestOpenApi获取,即上述example3
|
|
469
300
|
*/
|
|
@@ -332,12 +332,19 @@ document.addEventListener('DOMContentLoaded', async (event) => {
|
|
|
332
332
|
* },
|
|
333
333
|
*/
|
|
334
334
|
const userAgentManager = UserAgentFactory.getUserAgentManager({
|
|
335
|
-
//
|
|
336
|
-
//
|
|
337
|
-
//
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
335
|
+
// sgOpen: '1',
|
|
336
|
+
// sg: '1',
|
|
337
|
+
// openBaseUrl: '1',
|
|
338
|
+
// logLevel: 'debug', // 日志等级,默认error
|
|
339
|
+
agentTag: '15018707394', // 生产线 坐席维度定位
|
|
340
|
+
appKey: '032d44009bff1752', // 生产线 企业维度定位
|
|
341
|
+
appSecret: '4c7304c94c5e8725613516d4d6db679b', // 生产线 企业维度定位 这里直接使用appSecret做演示
|
|
342
|
+
// agentId: '9870', // 生产线 坐席维度定位
|
|
343
|
+
// appKey: 'd85085f084e71477', // 生产线 企业维度定位
|
|
344
|
+
// appSecret: '1df8fdeaa960c7fefd8da39135a693ae', // 生产线 企业维度定位 这里直接使用appSecret做演示
|
|
345
|
+
// agentId: '2357', // 生产线 坐席维度定位
|
|
346
|
+
// appKey: '9297afc05dfe1704', // 生产线 企业维度定位
|
|
347
|
+
// appSecret: '616e860760cbd34deb1970390bf82659', // 生产线 企业维度定位 这里直接使用appSecret做演示
|
|
341
348
|
refreshSpeekVolumn(value) { // 当来电接通时,实时查看坐席说话的音量实际传送到给对方的音量大小
|
|
342
349
|
volumn.innerText = value
|
|
343
350
|
},
|
|
@@ -794,6 +801,20 @@ document.addEventListener('DOMContentLoaded', async (event) => {
|
|
|
794
801
|
|
|
795
802
|
/**
|
|
796
803
|
* 呼叫
|
|
804
|
+
* - 手机号外呼用openapi,如 userAgentManager.callNumber 或 userAgentManager.requestOpenApi({
|
|
805
|
+
* url: '/v1/task/importAgentCustomer',
|
|
806
|
+
* data: {
|
|
807
|
+
* agentTag: 'xxx',
|
|
808
|
+
* agentId: 'xxx',
|
|
809
|
+
* callType: 1001,
|
|
810
|
+
* customers: [{ number: 15018707394 }]
|
|
811
|
+
* }
|
|
812
|
+
* })
|
|
813
|
+
* - 分机外呼用invite, 如await userAgentManager.invite({
|
|
814
|
+
* // uri: 'xxx' // 如果是不同外呼服务器的分机,使用uri,格式同上 sipServerHost
|
|
815
|
+
* extension: call.value // 同个外呼服务器地址的分机 例如上述分机账号 extensionNumber
|
|
816
|
+
* })
|
|
817
|
+
*
|
|
797
818
|
*/
|
|
798
819
|
const callPhone = async () => {
|
|
799
820
|
const callInfo = await userAgentManager.callNumber(call.value) // 👈 一键
|
|
@@ -802,6 +823,9 @@ document.addEventListener('DOMContentLoaded', async (event) => {
|
|
|
802
823
|
} else {
|
|
803
824
|
alert(callInfo.message)
|
|
804
825
|
}
|
|
826
|
+
// await userAgentManager.invite({
|
|
827
|
+
// extension: call.value
|
|
828
|
+
// })
|
|
805
829
|
}
|
|
806
830
|
|
|
807
831
|
/**
|