微信小程序音视频通话(for硬件)接入流程

498 阅读6分钟

微信小程序音视频通话(for硬件)接入流程

这是24年做的音视频通再此记录一下,博主主要负责小程序部分,三方硬件与后端对接相关就不清楚了。现在插件应该更新迭代比较多,详情请查看微信官方文档以及插件文档。

微信文档:连接硬件能力 / 音视频通话+摄像头(for 硬件) / VoIP 通话插件 / 接入指引

插件: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校园电话」

voip-2.1648f4a3.jpg

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 自定义设置 - 联调设备后看效果来修改

自定义设定播放完成后的跳转页面以及自定义按钮:

mp.weixin.qq.com/wxopen/plug…

3.1 自定义通话结束后的跳转页(重要)

使用 setVoipEndPagePath 设置通话结束后跳转的页面, 需保证在通话结束前设置

const wmpfVoip = requirePlugin('wmpf-voip').default

wmpfVoip.setVoipEndPagePath({
  // 结束通话后跳转的小程序页面路径例,可根据 typeof wmpf !== 'undefined' 判断运行环境
  url: '/pages/contactList/contactList', 
  options: 'param1=xxx&param2=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_tokenstring接口调用凭证,该参数为 URL 参数,非 Body 参数。使用access_token或者authorizer_access_token
snstringsn 设备唯一序列号。由厂商分配,长度不能超过128字节。字符只接受数字,大小写字母,下划线(_)和连字符(-)。
model_idstring设备型号 id ,通过注册设备获得

返回参数

属性类型说明
errcodenumber错误码
errmsgstring错误信息
sn_ticketstring设备票据,5分钟内有效。
1.1 access_token 获取(优先获取)
GET https://api.weixin.qq.com/cgi-bin/token

请求参数

属性类型必填说明
grant_typestring填写 client_credential
appidstring小程序唯一凭证,即 AppID,可在「微信公众平台 - 开发 - 开发管理 - 开发设置」页中获得。(需要已经成为开发者,且帐号没有异常状态)
secretstring小程序唯一凭证密钥,即 AppSecret,获取方式同 appid

2. model_id 获取(重要)

微信公众平台 —— 功能 —— 硬件设备