微信要求 uni.requestsubscribemessage 必须在用户点击按钮后5秒内调用,否则静默失败;需检查 subscriptionssetting 状态,引导用户设置时注意 ios 无订阅入口。

uni.requestSubscribeMessage 调用时机不对,用户根本看不到弹窗
微信强制要求:必须在用户主动触发(如点击按钮)的 5 秒内调用 uni.requestSubscribeMessage,否则静默失败,控制台无报错,但 fail 回调会返回 errCode: 20004 或直接不触发。这不是 uni-app 的 bug,是微信底层限制。
实操建议:
- 绝不能在
onLoad、onShow或异步请求回调里直接调;必须绑定到按钮@click或tap事件中 - 按钮文案要具象,比如“开启订单提醒”比“授权通知”更易点击;避免使用“同意”“授权”等抽象词
- 如果用户首次拒绝,再次调用仍会拉起弹窗(只要没点“不再提示”),但需先检查当前状态,避免白忙活
如何判断用户是否已授权,而不是每次都弹窗
靠 uni.getSetting 查 subscriptionsSetting,但要注意字段嵌套深、值类型多,且不同版本返回结构略有差异。
实操建议:
- 必须传参
withSubscriptions: true,否则subscriptionsSetting字段为空 -
res.subscriptionsSetting.mainSwitch是总开关(用户是否允许小程序发订阅消息),为false表示用户在系统设置里全局关闭了 - 单个模板状态在
res.subscriptionsSetting.itemSettings[tmplId],可能值为:'accept'(已同意)、'reject'(拒绝过)、'ban'(被后台禁用) - 别用
==判定字符串,统一用===,'accept '(带空格)这种脏数据真会出现
用户点了“拒绝”或“不再提示”,怎么友好引导去设置页
微信不允许 JS 主动跳转到“订阅消息”子页面,uni.openSetting 只能打开权限总览页,且 iOS 和 Android 展示逻辑不同——iOS 不显示订阅消息入口,Android 才有。
实操建议:
- 检测到
err.errCode === 20004或itemSettings[tmplId] === 'reject'时,才弹uni.showModal引导 -
uni.openSetting必须加withSubscriptions: true参数,否则 Android 也进不到对应页 - 弹窗文案别写“请前往设置开启”,要写“消息提醒已关闭,去设置里打开才能及时收到订单更新”,把后果说清
- 调用
uni.openSetting后,建议uni.navigateBack()或uni.reLaunch,因为用户设置完不会自动回到你的页面
模板 ID 写错、漏填、多填,会导致什么
tmplIds 是数组,但微信只认你传进去的、已在公众号平台「我的模板」里成功添加并审核通过的 ID。ID 错一位、多一个空格、或者用了未审核的测试 ID,都会让整个请求失败,success 不触发,fail 里也拿不到具体原因。
实操建议:
- 模板 ID 从微信公众平台「功能 → 订阅消息 → 我的模板」里复制,不要手打,不要从控制台 log 里复制(容易带换行或引号)
- 一次最多传 10 个 ID,但建议每次只传 1 个——用户只需点一次确认,就能同时授权多个模板,但失败时无法定位是哪个错了
- 后端发送消息时用的
template_id必须和前端传的完全一致,大小写、下划线都不能差 - 上线前务必用真机扫码测试,开发者工具里 mock 的授权状态不可靠










