Skip to content

集成微信小程序

微信 VoIP 通话涉及小程序、业务服务端、探鸽云平台、设备端四方交互。小程序端负责用户登录、设备 VoIP 授权、发起/接听通话、中止呼叫。

接口归属说明

  • 微信提供:wx.loginwx.requestDeviceVoIPwx.getDeviceVoIPListwmpf-voip 插件(callDeviceonVoipEvent 等)
  • 业务服务端提供:所有 /v1/voip/user/*/v1/user/* 路径的 HTTP 接口,需业务方按 集成业务服务端 自行实现

阅读本文前,请先了解 通话流程集成业务服务端。小程序申请与配置见 微信小程序申请与配置


一、需要实现什么

按开发顺序,小程序 VoIP 模块需要依次完成:

顺序模块做什么
1微信登录wx.login → 业务服务端换取 openid
2VoIP 授权SN Ticket → wx.requestDeviceVoIP → 上报授权关系
3授权状态查询wx.getDeviceVoIPList 判断设备是否已授权
4呼叫设备wmpf-voip 插件 callDevice → 进入通话页面
5取消呼叫onVoipEvent('cancelVoip') → 通知业务服务端

二、微信登录

调用业务服务端 POST /v1/voip/user/wechat-mini-login。小程序先用 wx.login() 获取临时 code,发给服务端换取 openid。

js
// 获取 openid
const res = await wx.login()
const { data } = await request({
  url: `${server}/v1/voip/user/wechat-mini-login`,
  method: 'POST',
  data: { code: res.code }
})
// data.wx_user_openid 即为当前用户 openid

服务端内部调微信 jscode2session,返回 openid。openid 是后续所有 VoIP 操作的用户标识。


三、VoIP 设备授权

用户首次使用某设备通话前,需完成微信侧授权。

3.1 获取 SN Ticket

调业务服务端 POST /v1/voip/user/sn-ticket

js
const { data } = await request({
  url: `${server}/v1/voip/user/sn-ticket`,
  method: 'POST',
  data: { device_id: 'TIRZ00000001' }
})
// data.sn_ticket

服务端内部调微信 getsnticket 接口签发。

3.2 调用微信授权

js
wx.requestDeviceVoIP({
  sn: deviceId,
  snTicket: ticket,
  modelId: '<微信 IoT 后台配置的 ModelID>',
  deviceName: deviceId,
  success: () => { /* 授权成功 */ },
  fail: (err) => {
    // errCode 10001 表示已授权,等同于成功
    if (err.errCode === 10001) { /* 已授权 */ }
  }
})

3.3 上报授权关系到业务服务端

授权成功后,调业务服务端 POST /v1/voip/user/report-auth

js
await request({
  url: `${server}/v1/voip/user/report-auth`,
  method: 'POST',
  data: {
    device_id:   deviceId,
    wx_open_id:  openId,
    wx_model_id: modelId
  }
})

服务端存储后通过下行通道向设备推送 callers_update,设备可感知授权变更。

3.4 查询授权状态

js
wx.getDeviceVoIPList({
  success: (res) => {
    const authed = (res.list || [])
      .filter(i => i.status === 1)
      .map(i => i.sn)
    // authed 中为已授权设备列表
  }
})

status === 1 表示已授权。通常在设备列表页面调用,与业务服务端设备列表交叉比对,显示哪些设备可通话。


四、呼叫设备

使用微信官方 wmpf-voip 插件。在 app.json 中声明:

json
{
  "plugins": {
    "wmpf-voip": {
      "version": "latest",
      "provider": "wx069abb402f7b1df9"
    }
  }
}

4.1 发起呼叫

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

const { roomId } = await wmpfVoip.callDevice({
  sn:       deviceId,
  modelId:  '<微信 IoT ModelID>',
  roomType: 'voice',           // 'voice' 或 'video'
  nickName: '用户昵称',
  isCloud:  true,              // 必须为 true
  payload:  JSON.stringify({   // 自定义透传数据,服务端和设备端约定
    wxa_from: 'app',
    call_id:  '<唯一呼叫 ID>'
  })
})

// 保存当前通话上下文,供取消呼叫时使用
this.currentCall = { deviceId, roomId }

// 跳转到 VoIP 插件提供的通话页面
wx.redirectTo({ url: wmpfVoip.CALL_PAGE_PATH })
参数说明
sn设备 SN,与设备 ID 一致
modelId微信 IoT 后台配置的 ModelID
roomType"voice""video"
isCloud必须为 true,使用云代理模式
payload自定义 JSON 字符串,微信透传至服务端和设备端。建议约定 wxa_from(标识主叫方)和 call_id(唯一呼叫标识)

4.2 通话页面

callDevice 成功后跳转至 wmpfVoip.CALL_PAGE_PATH,插件提供完整的通话 UI(来电界面、接通/挂断按钮、音视频渲染)。无需自行开发通话页面。


五、未接通时取消呼叫

小程序主叫、被叫尚未接听时,用户主动取消。监听 wmpf-voip 插件事件:

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

App({
  onLaunch() {
    wmpfVoip.onVoipEvent((event) => {
      if (event.eventName === 'cancelVoip') {
        this._handleCancel(event)
      }
    })
  },

  _handleCancel(event) {
    if (!this.currentCall) return
    const { deviceId, roomId } = this.currentCall
    this.currentCall = null

    // 调业务服务端 POST /v1/voip/user/cancel,由服务端推送 call_cancel 至设备
    wx.request({
      url: `${server}/v1/voip/user/cancel`,
      method: 'POST',
      data: { device_id: deviceId, wx_room_id: roomId }
    })
  }
})

服务端收到后通过下行通道向设备推送 call_cancel,设备收到后结束振铃。


六、解绑时删除授权

用户解绑设备时,同步调业务服务端删除 VoIP 授权记录:

js
// 调业务服务端 DELETE /v1/user/device/reset(解绑设备)
await request({
  url: `${server}/v1/user/device/reset`,
  method: 'DELETE',
  data: { device_id: deviceId }
})

// 调业务服务端 POST /v1/voip/user/delete-auth(删除 VoIP 授权)
await request({
  url: `${server}/v1/voip/user/delete-auth`,
  method: 'POST',
  data: {
    device_id:  deviceId,
    wx_open_id: openId
  }
})

服务端自动通过下行通道推送 callers_update 至设备。


七、完整流程示例

1. 用户登录
   wx.login → code → POST /v1/voip/user/wechat-mini-login → openid

2. 首次使用设备:
   a. POST /v1/voip/user/sn-ticket → sn_ticket
   b. wx.requestDeviceVoIP({ sn, snTicket, modelId })
   c. POST /v1/voip/user/report-auth → 上报授权关系
   d. 服务端推送 callers_update → 设备

3. 呼叫设备:
   a. wmpfVoip.callDevice({ sn, modelId, roomType, isCloud: true })
   b. 拿到 roomId,保存 currentCall = { deviceId, roomId }
   c. wx.redirectTo({ url: CALL_PAGE_PATH })

4. 取消呼叫(被叫未接听):
   wmpfVoip.onVoipEvent('cancelVoip') → POST /v1/voip/user/cancel

八、实现要点

要点说明
isCloud 必须为 true微信 VoIP 必须使用云代理模式
modelId 与 IoT 后台一致不一致则 requestDeviceVoIP 报错
SN Ticket 由服务端签发不直接在客户端调微信 getsnticket
cancelVoip 事件仅未接通时触发已接通后的挂断由插件内部处理
payload 透传自定义字段经微信→服务端→设备全程透传,建议约定 wxa_fromcall_id
wx_app_id 可选上述业务服务端接口均可传 wx_app_id;不传则服务端使用默认 AppID。多小程序时建议传入

微信VoIP通话