微信小程序音视频通话(for硬件)接入流程
这是24年做的音视频通再此记录一下,博主主要负责小程序部分,三方硬件与后端对接相关就不清楚了。现在插件应该更新迭代比较多,详情请查看微信官方文档以及插件文档。
微信文档:连接硬件能力 / 音视频通话+摄像头(for 硬件) / VoIP 通话插件 / 接入指引
使用技术:原生微信小程序、小程序插件VOIP、以及三方公司的硬件支持
大致需求:用户单元门通过门铃拨通,接听方可以在微信中弹出视频通话界面、可以在通话界面或者专门为音视频做的界面控制单元门的开启。
如有侵权请联系我!!!!!!!!!!
开发
1. 用户授权设备
设备和用户间如果要进行通话,需用户在手机微信端对设备进行授权
1.1 请求授权(重要)
1.1.1 获取设备票据(snTicket)
用户授权前,需要从开发者的后台通过获取设备票据 接口拿到设备票据 snTicket。详情请看汇总
1.1.2 用户授权
在拿到 snTicket 后调用 wx.requestDeviceVoIP 请用户授权
wx.requestDeviceVoIP({
sn: 'xxxxxx', // 向用户发起通话的设备 sn(需要与设备注册时一致)
snTicket: 'xxxxxx', // 获取的 snTicket modelId: 'xxxxxx', // 「设备接入」从微信公众平台获取的 model_id 微信公众平台 硬件内获取
deviceName: 'xxx', // 设备名称,用于授权时显示给用户,动态获取页面显title
success(res) {
console.log(`res`, res)
},
fail(err) {
console.error(`err:`, err)
},
})
注意:
- 如果用户拒绝授权或在设置页中取消授权,再次调用
requestDeviceVoIP不会出现授权弹框。开发者应引导用户在设置页中手动开启。 - 授权框中「设备名字」= 「deviceName」 + 「modelId 对应设备型号」。如「devcieName」为「iot」,modelId 对应设备型号是「校园电话」,最终名字为「iot校园电话」
1.1.3 授权失败
用户在授权成功后,下列操作可能导致授权失效:
- 清空授权:在最近使用中删除小程序,用户的授权记录会被清空。
- 取消授权:用户同意授权后,小程序设置页面中会出现「语音、视频通话提醒」模块,点击进入后用户可以管理已授权的设备,并可以取消授权。(需要微信客户端 >= 8.0.30 支持)
为了保证用户能够正常使用音视频通话能力,开发者需要处理授权失效的情况。 在发起通话前,建议开发者检查授权状态。并在必要时提醒用户重新授权:
- 清空授权:可以直接调用
requestDeviceVoIP请用户进行重新授权。 - 取消授权/用户拒绝授权:再次调用
requestDeviceVoIP不会出现授权弹框。开发者应引导用户在设置页中手动开启授权开关。
1.2 授权状态查询
1.2.1 当前用户授权的设备
查询当前用户同意/拒绝或取消授权了哪些用户。
在手机微信端小程序内调用 wx.getDeviceVoIPList,可用于在手机端发起通话前检查授权状态。
wx.getDeviceVoIPList({
success(res) {
console.log(res.list)
// [{sn: 'xxx', model_id: 'xxx', status: 0}]
// status: 0/未授权;1/已授权
}
})
1.2.2 当前设备是否被授权
根据用户 openid 查询指定用户是否授权设备
由插件提供 getIotBindContactList 接口,一般在设备端使用,可用于在设备端发起通话前(如联系人页面)检查授权状态。
// VOIP 插件接口
wmpfVoip.getIotBindContactList({
sn: "设备sn",
model_id: "申请的modelid",
openid_list: ["openid_1", "openid_2"], // 传入需要验证的openid列表
}).then((res) => {
console.log(res.contact_list)
// [{sn: 'xxx', model_id: 'xxx', status: 0}]
// status: 0/未授权;1/已授权
})
2. 设备拨打手机微信
2.1 在 app.json 中引入 VOIP 插件
"plugins": {
"wmpf-voip": {
"version": "2.2.1",
"provider": "wxf830863afde621eb"
}
}
2.2 在需要用到的页面引入 VOIP
const wmpfVoip = requirePlugin("wmpf-voip").default
console.log(wmpfVoip) // 打印的出来则引入成功
2.3 获取 openid(重要)
if (token) {
// 获取用户 openid
wx.login({
success(res) {
if (res.code) {
wx.request({
url: 'https://api.weixin.qq.com/sns/jscode2session',
data: {
appid: "wxa1ce037c7a8b9689", // 小程序开发设置获取
secret: "", // 开发设置中获取
js_code: res.code,
grant_type: "authorization_code"
},
success(re) {
console.log(re); // 获取用户openid
}
})
}
}
})
}
2.4 调用插件接口获取 groupId(重要)
使用 Promise<Object> initByCaller(Object object) 接口获取通话房间号 (groupId)。
本接口为异步接口,返回 Promise。
调用此接口后,会创建 VOIP 房间,并且向接听方推送一条接听提醒。
开发文档:mp.weixin.qq.com/wxopen/plug…
let params = {
caller: {
id: "" // 设备 SN 使用 registerVoipDevice 获取SN
},
listener: {
id: openId, // 接听方用户 openId
name: "1栋1单元" // 接听方名称
},
roomType: "video", // 房间类型:voice:音频房间,video:音视频房间
businessType: 1, // 0:刷脸(默认),1:设备拨打手机,2:手机拨打设备
voipToken: "", // 使用 getCallerTicket 获取
miniprogramState: 'developer' // formal/正式版(默认);trial/体验版;developer/开发版
}
// 获取 groupId
const { groupId } = await wmpfVoip.initByCaller(params)
2.5 进入通话页面 - 前置条件(获取了groupId)
if (isSuccess) {
// 跳转到插件的通话页面
const callPagePlugin = 'plugin-private://wxf830863afde621eb/pages/call-page-plugin/call-page-plugin'
wx.redirectTo({
url: `${callPagePlugin}?isCaller=1&roomType=video&groupId=${groupId}`,
})
} else {
wx.showToast({
title: '播打失败',
icon: 'error',
})
}
3. VOIP 自定义设置 - 联调设备后看效果来修改
自定义设定播放完成后的跳转页面以及自定义按钮:
3.1 自定义通话结束后的跳转页(重要)
使用 setVoipEndPagePath 设置通话结束后跳转的页面, 需保证在通话结束前设置。
const wmpfVoip = requirePlugin('wmpf-voip').default
wmpfVoip.setVoipEndPagePath({
// 结束通话后跳转的小程序页面路径例,可根据 typeof wmpf !== 'undefined' 判断运行环境
url: '/pages/contactList/contactList',
options: 'param1=xxx¶m2=xxx', // 拼接在 url 后面的 query
key: 'Call',
})
4. VOIP 通话事件(重要)
通过 onVoipEvent 绑定通话事件的监听。事件绑定需在通话前完成。
wmpfVoip.onVoipEvent((event) => {
console.info(`onVoipEvent`, event)
})
参数参考:mp.weixin.qq.com/wxopen/plug…
5. 结束当前通话(重要)
应用场景:
- 用户操作硬件设备的某些按钮结束通话。例如,设备有单独的话机听筒时,用户挂断听筒。
- 用户通话时长超过限制
通话到指定时间。调用forceHangUpVoip主动要求插件结束当前通话
开发汇总
1. snTicket获取(重要)
接口:getSnTicket
POST https://api.weixin.qq.com/wxa/getsnticket?access_token=ACCESS_TOKEN
请求参数:
| 属性 | 类型 | 必填 | 说明 |
|---|---|---|---|
| access_token | string | 是 | 接口调用凭证,该参数为 URL 参数,非 Body 参数。使用access_token或者authorizer_access_token |
| sn | string | 是 | sn 设备唯一序列号。由厂商分配,长度不能超过128字节。字符只接受数字,大小写字母,下划线(_)和连字符(-)。 |
| model_id | string | 是 | 设备型号 id ,通过注册设备获得 |
返回参数
| 属性 | 类型 | 说明 |
|---|---|---|
| errcode | number | 错误码 |
| errmsg | string | 错误信息 |
| sn_ticket | string | 设备票据,5分钟内有效。 |
1.1 access_token 获取(优先获取)
GET https://api.weixin.qq.com/cgi-bin/token
请求参数
| 属性 | 类型 | 必填 | 说明 |
|---|---|---|---|
| grant_type | string | 是 | 填写 client_credential |
| appid | string | 是 | 小程序唯一凭证,即 AppID,可在「微信公众平台 - 开发 - 开发管理 - 开发设置」页中获得。(需要已经成为开发者,且帐号没有异常状态) |
| secret | string | 是 | 小程序唯一凭证密钥,即 AppSecret,获取方式同 appid |
2. model_id 获取(重要)
微信公众平台 —— 功能 —— 硬件设备