微信小程序

常见问题 FAQ

# 常见问题(FAQ)

# 1. 功能相关(通用)

# 1.1 如何限制用户的单次通话时长?

在小程序中,可以在收到插件的 startVoip 事件后设置定时器,或者根据 calling 事件的 keepTime 字段计算通话时长。超过限制后可以调用插件 forceHangUpVoip 中断通话。

详见插件文档「7.2 结束当前通话」

# 1.2 在门禁、门锁场景,如何在手机端通话页面实现「开门」等功能?

插件提供了在手机端接听通话页面自定义按钮的功能,开发者可配置一个自定义的弹层来实现具体功能。

详见插件文档「4.1 自定义接听页面按钮」

C 端用户体验如下图所示:

# 1.3 用户如何取消授权?

用户可以在小程序设置页里取消授权,或通过在最近使用中删除小程序来清空授权记录。请参考「处理授权失效的情况」。

# 1.4 如何查询用户是否已授权设备(组)?

请参考「授权状态查询」。

# 1.5 如何设置呼叫超时时长(长时间不接听时停止呼叫)?是否支持轮询呼叫?

开发者可以自行控制超时时间,超时后调用插件 forceHangUpVoip 接口中断通话。

超时后,开发者可以根据业务场景,选择自动拨打给其他用户,实现轮询呼叫的能力。例如 101 号房有 A、B、C 三位业主,打给 A 业主 30 秒未接听,可自动打给 B 业主,依此类推。

# 1.6 如何自定义手机端看到的设备端来电名称?

为强化设备通话的认知、保证用户体验统一,手机端用户授权设备名称、接听设备来电的名称需保持一致。

授权设备名称 = 来电方名称 = 开发者自定义名称 + 设备类型名称。如「艾玛的希沃网课学习机」。开发者需要考虑名称显示,对名称做好规范。

(案例示意:订阅设备名称、来电方名称、语音通话中设备名称)

# 1.7 使用物联网卡时,如何配置域名和 IP 白名单?

VOIP 业务依赖于微信基础服务和小程序相关的业务内容,涉及比较多的 IP 和域名,其中很大一部分是动态下发的,本身会随着业务的变更而增添或者裁撤。因此暂时没办法提供稳定的域名和IP列表,有可能的话还是建议使用非定向的流量。

若不得不使用定向流量,暂时可以参考微信刷脸设备的配置列表,但目前无法保证该名单的完整性,后续也可能会新增和移除。

# 1.8 音视频通话的流量使用情况?

根据测算,语音通话大概是 2MB/分钟,视频是 10-30MB/分钟。

# 1.9 设备无摄像头或因隐私等原因不希望传画面(门禁、门锁的用户端),如何默认禁用摄像头?

插件发起通话时可以设置 caller.cameraStatus 或 listener.cameraStatus,设置两端是否默认开启摄像头。

如果要禁止用户切换摄像头,可以用插件的 setUIConfig 设置 callerUI/listenerUI 的 enableToggleCamera 选项。

详见插件文档

# 1.10 为何推送消息显示的通话时长和通话结束或者 endVoip 事件获取的不一致?应该如何获取准确的通话时长?

VOIP 插件 2.2.1 及以下版本,通话结束页显示的时间为本地定时器计算的时间,endVoip 事件的 keepTime 提供的也是这个时间。但是由于通话双方之间存在一定网络延迟,这里的时间可能与实际扣费时长并不一致(一般要多于实际扣费的时长)。

VOIP 插件 2.2.2 版本开始,会在通话结束后(即 endVoip 事件后)从后台获取实际扣费时长,并通过 finishVoip 事件的 keepTime 返回给开发者。通话结束页也会更新显示实际的扣费时长。

# 2. 功能相关(安卓设备)

# 2.1 安卓应用和小程序之间如何进行参数传递和通信?安卓应用如何接收小程序发来的消息?
  1. 简单的「安卓应用 -> 小程序」单向单此传递参数的场景,可以直接在启动小程序的 path 中拼接 query。
  2. 如果安卓应用要接收小程序发来的事件、需要双向通信或者数据量大时可以通过 WMPF 提供的通信通道(Invoke Channel)
# 2.2 通话完成后如何关闭小程序?

当设备端小程序只承载 VOIP 通话能力时,可能需要在通话结束后将小程序切后台或关闭。

小程序收到插件的 endVoIP 事件后,通过 WMPF 提供的通信通道(Invoke Channel)通知 App。

收到通知后,App 可以选择调用 CloseWxaApp 将小程序切后台或关闭(可参考《性能与体验优化指南》的说明选择)。

# 2.3 如何判断当前小程序是在设备端(WMPF)还是手机端打开

在 WMPF 运行时,小程序能可以访问到 wmpf 这个全局变量。可以通过是否存在这个全局变量来判断:typeof wmpf !== 'undefined' 即为设备端。

注意:调用 wmpf 上的方法前,应提前判断 wmpf 这个全局变量是否存在,否则在手机微信端走到这段逻辑时会报错。

# 3. 异常相关(通用)

# 3.1 手机端未收到微信通话强提醒或提醒强度不符合预期(锁屏未提醒、未响铃、未震动等)

请确认下以下手机端几个设置是否正常:

  • 微信客户端已升级到 8.0.30 及以上版本;
  • 手机系统需开启非静音、非振动模式;并在系统设置中开启微信通知权限和通知声音。
  • 需开启微信消息提醒:「微信客户端」-「我」-「设置」-「消息通知」- 「语音和视频通话提醒」、「消息通知横幅」已经开启;
  • 需开启服务通知的提醒:「服务通知」-「设置」 - 「消息免打扰」未开启,「播放语音提醒」已开启;
  • 需开通对某个小程序的消息授权:「小程序设置页」-「语音、视频通话提醒」已开启。

上面条件满足的情况下,可以确认下同一台手机,微信好友和好友之前的通话提醒有没有语音震动。如果都没有,属于微信客户端问题,如果仅微信硬件VoIP不正常,说明微信硬件VoIP有问题。相关问题可反馈微信号、日志、发生时间、手机机型、微信客户端版本号等信息到社区。

# 3.2 获取设备票据 getSnTicket 接口返回 48001 (api unauthorized)

小程序 appId 未完成硬件设备接入导致。请确认:

  • appId 对应小程序已在「小程序管理后台」完成硬件设备接入。
  • 请求时使用的 access_token 通过是完成申请小程序的 appId 申请的,而不是其他小程序的 appId 或者移动应用的 hostAppId。
# 3.3 wx.requestDeviceVoIP 报错 invalid scope

小程序 appId 未完成硬件设备接入或接入后未申请「小程序音视频能力」设备能力导致。请确认小程序已在「小程序管理后台」完成硬件设备接入并申请通过小程序音视频能力。

# 3.4 wx.getEnterOptionsSync 或插件的 getPluginEnteroptions 无法获取到进入小程序的 query

一般有以下几种情况:

  • 这两个函数只能获得小程序启动时(冷启动或热启动)的参数,如果是通过 wx.navigateTo 等路由方式跳转页面的情况,则需要在对应页面的 onLoad 生命周期获取。
  • 由于插件和宿主小程序的安全策略限制,当小程序启动路径为插件页面时,需要通过 VOIP 插件提供的 getPluginEnteroptions 获取 query;当小程序启动路径为小程序页面时,需要通过 wx.getEnterOptionsSync 获取 query。

建议排查时同时打印返回值中的 path 字段,确认是否是预期的传入 querypath

# 3.5 接听方接听时提示「页面不存在」

一般有以下几种情况:

  • 调用插件 initByCaller 时未设置 miniprogramState,或设置了 miniprogramState: formal,此时接听方会打开正式版小程序。而设备 VOIP 能力尚未发布正式版。
  • 调用插件 initByCaller 时设置了 miniprogramState: trial,此时接听方会打开体验版小程序。而当前设置为体验版的小程序中并未支持设备 VOIP 能力。
  • 调用插件 initByCaller 时设置了 miniprogramState: developer,此时接听方会打开开发版小程序。此时接听方需要提前扫码下载与拨打方相同的开发版小程序方可使用。

# 4. 异常相关(安卓设备)

# 4.1 WMPF 获取不到正确的摄像头,或摄像头画面旋转

可以使用 InitGlobalConfig 接口指定小程序使用的摄像头三元组(productId、vendorId、serialNumber),也可以指定摄像头画面的旋转角度。

fun initGlobalConfig() {
    val jsonConfig = JSONObject()
        // 请注意:USB 摄像头和系统摄像头使用的参数名称是不一样的。
    try {
        // 案例 1:微信端画面颠倒
        jsonConfig.put("cameraPushFlip", true) // USB 摄像头需使用 usbCameraPushFlip 参数

        // 案例 2:使用系统摄像头,微信端显示画面旋转
        jsonConfig.put("cameraRotationAngle", 90) // 根据实际情况调整角度

        // 案例 3:通过直接指定摄像头设备路径使用 USB 摄像头(与案例 4 的情况二选一)
        jsonConfig.put("usbCameraName", "/dev/xx/xx/xx")

        // 案例 4:通过指定三元组使用 USB 摄像头(与案例 3 的情况二选一)
        jsonConfig.put("usbCameraProductId", 0)
        jsonConfig.put("usbCameraVendorId", 0)
        jsonConfig.put("usbSerialNumber", "xxx")

        // 案例5:使用 USB 摄像头,WMPF 预览和 微信端显示画面旋转
        jsonConfig.put("usbCameraRotationAngle", 90) // 根据实际情况调整角度

        val json = jsonConfig.toString()
        LogUtils.d(TAG, "initGlobalConfig", json)
        Api.initGlobalConfig(json)
            .subscribe({
                LogUtils.d(TAG, GsonUtils.toJson(it))
                warmLaunch()
            }, {
                LogUtils.d(TAG, GsonUtils.toJson(it))
                warmLaunch()
            })
    } catch (e: Exception) { }
}

如果设置摄像头画面旋转未生效,建议按照下列指引检查:

  • InitGlobalConfig 必须在 ActivateDevice 回调成功后、启动小程序前调用。建议在 ActivateDevice 的 onSuccess 回调后调用。
  • InitGlobalConfig 设置是一次性的,在每次 WMPF 启动后都需要调用。
  • 请确认设备使用的是 USB 摄像头还是系统摄像头
    • 如果通过 usbCameraName,或 usbCameraProductId + usbCameraVendorId + usbSerialNumber 指定使用 USB 摄像头,需使用 usbCameraPushFlipusbCameraRotationAngle 设置画面旋转
    • 其他情况下使用系统摄像头,需使用 cameraPushFlipcameraRotationAngle 设置画面旋转。此时只能设置微信客户端看到的推流画面的旋转,不能改变设备端看到的预览画面。
# 4.2 设备端有时收不到推送的通话提醒

可以根据下列指引排查

  • 确认 WMPF 升级到 v1.1.5 及以上版本;
  • 确认设备端已联网,并确认网络畅通;
  • 确认设备端 WMPF 已启动并且以及完成激活(ActivateDevice),确保 WMPF 正常运行
  • WMPF 因 crash 等原因异常退出后,需要重新拉起。建议监听 IPCInvoker.addRemoteProcDiedListener(WMPFService.WMPF_SERVICE_PROCESS_NAME, listener),在 WMPF 退出后重新拉起。
# 4.3 设备端为什么会需要用户微信扫码登录?

使用小程序音视频通话(for 硬件)能力时,用户无需在设备端扫码登录。但是如果小程序内调用了与微信登录态相关的接口,例如 wx.login,会弹出扫码界面要求用户登录。

建议开发者参考 2.3,判断小程序在 WMPF 环境内运行时,避免调用相关接口。

# 4.4 WMPF ActivateDevice 报错 signature err 1

signature err 是指后台发现签名中的参数与 ActivateDevice 传入的参数不匹配。建议按照下列指引检查:

请注意,签名校验成功只能说明签名中包含的参数和校验时提供的参数一致,并不代表 ActivateDevice 不会报错。

  • 确认 WMPF 升级到 v1.1.5 及以上版本;
  • 确认生成签名时的 productId、deviceId 和所使用密钥的版本(keyVersion) 与 ActivateDevice 传入的参数一致。
  • 确认生成签名时使用的密钥对与 wecooper 上登记的一致。如密钥对更换,请及时在 wecooper 上更新,并使用新的密钥对和 keyVersion 进行签名。
  • 在开发者后台生成签名时,生成签名环境的 openssl 版本推荐使用 1.1.1,已确定 1.0.x 和 3.0.x 版本会有问题,其它版本开发者可自行尝试。
  • WMPF 文档中提供的辅助工具只适用于调试,mmIoT_ecdsa_sign.sh 脚本或 java 接口生成签名时,不支持并发操作。
# 4.5 WMPF 调用接口时回调 onBridgeNotFound,或提示 bridge not found

此报错说明 WMPF Service 未运行。WMPF Client 会尝试在调用接口时自动拉起 WMPF Service,但可能因为一些原因导致失败。建议按照下列指引检查:

  • 确认 WMPF Service APK 已安装
  • 确认系统设置中已开启 WMPF Service 的自启动权限。否则需要手动启动 WMPF Service。
# 4.6 WMPF 调用时报错 Failed to find provider info for com.tencent.wmpf.comm.provider

应用 targetSdkVersion >= 30 时,安卓要求在应用的清单文件中添加 <queries> 元素,请参考安卓文档进行配置。

<manifest>
    ...
    <queries>
        <provider android:authroities="com.tencent.wmpf.comm.provider"/>
    </queries>
    ...
</manifest>
# 4.7 WMPF ActivateDevice 报错 10013 request timeout

请按下列步骤排查

  • 确认设备网络正常;
  • 确认设备安卓系统为 7.1 及以上版本(WMPF 要求最低 7.1);
  • 如果设备为支付刷脸设备,使用硬件 VOIP 时,应确保支付相关的应用和服务已全部删除或禁用,否则会有冲突。