uni-app中发微信订阅消息必须通过button点击触发uni.requestSubscribeMessage,且仅支持一次性模板;需校验itemSettings中具体模板ID状态,后端发送时须确保access_token有效、touser为正确openid、模板字段名与后台配置严格一致。
uni-app 里不能直接“发模板消息”,必须走微信订阅消息链路,且只能是一次性模板;自动调用 uni.requestSubscribeMessage 必然失败,这是硬性限制。
微信强制要求该 API 只能在用户真实点击事件中调用,否则静默失败或报错 errCode: -1。常见错误包括:
onLoad、onShow、setTimeout 中调用 —— 直接被拦截view 或 text 绑定 @click —— 微信不认,必须是原生 button
open-type="subscribeMessage" 属性 —— 即使是 button 也无效(uni-app 3.0+ 才支持该属性)正确写法示例:
<button open-type="subscribeMessage" @click="handleSubscribe">开启订单通知</button>
对应 JS:
handleSubscribe() { uni.requestSubscribeMessage({ tmplIds: ['YOUR_TEMPLATE_ID'], success: (res) => { if (res['YOUR_TEMPLATE_ID'] === 'accept') { // 可立即调后端发消息 } }, fail: (err) => { console.error('授权失败', err) } })}
不能只看 uni.getSetting({withSubscriptions: true}) 的 mainSwitch,它只是总开关。关键要查具体模板的状态:
itemSettings['YOUR_TEMPLATE_ID'] === 'accept':已授权,可发(但一次性模板发完即失效)=== 'reject':用户点过“拒绝”,再调 requestSubscribeMessage 不会弹窗,需引导去设置页:uni.openSetting({withSubscriptions: true})
=== 'ban':模板被微信封禁(极少见,但真有)requestSubscribeMessage 的合适时机务必传 withSubscriptions: true,否则 itemSettings 为空对象。
前端拿到 'accept' 只是第一步,后端真正调用微信接口时,失败率极高,主因在:
access_token 必须缓存并校验有效期:微信限制每两小时刷新一次,且有调用频次限制;硬编码或每次重取会导致 40001 错误touser 字段必须是当前小程序的 openid:跨小程序、用测试号 openid、或拿错登录态(比如用了公众号 openid),都会返回 errcode: 43101
thing1,代码里写成 content 或 message,微信直接忽略该字段,不报错但内容为空发送接口地址是:https://api.weixin.qq.com/cgi-bin/message/subscribe/send,不是旧的模板消息地址,别混淆。
每个模板在微信公众平台「开发管理 → 订阅消息 → 我的模板」里生成唯一 templateId,且每个字段都有固定 name(如 character_string1、time4)。这些 name 是硬编码进后端请求体的,改一个字母就丢数据。
tmplIds 数组data 对象时,key 必须是模板详情页里写的字段 name,value 是字符串值thing.DATA 最多 20 字符;time.DATA 必须是 YYYY-MM-DD HH:mm 或带波浪线的时间段(如 "09:00~12:00")最容易被忽略的是:模板字段名大小写敏感,且不能加空格或下划线变体 —— 拿错一个,整条消息就显示为空白。