必须显式传 withSubscriptions: true 才能获取 subscriptionsSetting 字段;itemSettings[templateId] 为 undefined 表示首次触达,非拒绝;requestSubscribeMessage 需在用户点击后5秒内调用;缓存需按 templateId 分粒度且设有效期。

uni.getSetting 必须传 withSubscriptions: true 才能拿到订阅状态
不传或传 withSubscriptions: false,返回结果里压根没有 subscriptionsSetting 字段,后续所有判断都成空谈。这是最常踩的坑——调了 uni.getSetting() 却发现 res.subscriptionsSetting 是 undefined,根本原因就在这里。
实操建议:
- 永远显式传参:
uni.getSetting({ withSubscriptions: true }) - 别依赖默认值,微信文档没写默认行为,不同基础库版本表现可能不一致
- 在
success回调里立刻检查res.subscriptionsSetting是否存在,不存在就直接 return,避免后续报错
itemSettings[templateId] 为 undefined 不等于用户拒绝
res.subscriptionsSetting.itemSettings[templateId] 是 undefined,说明这个模板 ID 从未被用户触达过——既不是“接受”,也不是“拒绝”,而是“没弹过窗”。很多开发者误以为这是拒绝态,直接引导去设置页,反而破坏用户体验。
正确判断逻辑:
-
res.subscriptionsSetting.mainSwitch === false→ 用户在系统设置里关掉了总开关,此时itemSettings可能为空或全为ban -
itemSettings[templateId] === 'accept'→ 已授权,可立即调用后端发送接口 -
itemSettings[templateId] === 'reject'→ 用户点过“拒绝”,但没勾选“不再提示”,仍可再次触发弹窗 -
itemSettings[templateId] === undefined→ 首次接触该模板,必须调用uni.requestSubscribeMessage
uni.requestSubscribeMessage 必须在用户点击 5 秒内触发
微信强制限制:只有在用户主动点击(@click、tap)事件的同步上下文或 5 秒内调用 uni.requestSubscribeMessage,弹窗才会出现。超出时间静默失败,fail 回调可能不触发,或只返回 errCode: 20004。
常见错误场景:
- 在
onLoad或onShow里直接调用 → 白忙活,无弹窗 - 在异步请求(如
uni.request)的success回调里调用 → 时间不可控,大概率超时 - 按钮文案写“授权通知” → 点击率低;应改为具体动作,如“开启发货提醒”
缓存订阅状态要区分 templateId 和时效性
用户授权状态不是永久有效的:一次性模板每发一条就消耗一次,且微信可能因用户投诉封禁模板。所以本地缓存只能用于减少重复弹窗,不能替代实时检测。
实操要点:
- 缓存 key 必须含
templateId,例如subscribe_status_order_update - 缓存有效期建议设为 1–7 天,太长会误判已失效的授权
- 缓存值只存状态(
'accept'/'reject'),不要缓存mainSwitch,它属于全局开关,变化需重新检测 - 每次调用
uni.requestSubscribeMessage前,先读缓存;成功后立即更新缓存;失败时不覆盖原缓存
templateId 的状态独立演化,且受用户操作、后台审核、平台策略多重影响。最易忽略的是:即使用户点了“允许”,你拿到的也只是“这一次的授权凭证”,不是“永久许可”。真正的复杂性不在代码怎么写,而在如何把每一次授权请求,嵌进用户真实的业务动线里。


















