【微信小程序】订阅消息的一次性订阅 vs 长期订阅?其实一次性订阅也能实现长期发布订阅消息
文章目录
前言
为何要订阅消息 & 订阅的好处
相信你也曾被微信的服务通知所骚扰过(bushi)…
没错,微信的订阅消息会发送到用户的服务通知处;
而服务通知不同于公众号/服务号等通知;
“服务通知”:属于
强提醒,会以大红点的形式出现,而且还会在手机/电脑提醒消息;“公众号/服务号”:属于
弱提醒,只会以小红点的形式出现,不会在手机/电脑中提醒。
如图(对比):

因此,订阅消息的好处就不言而喻了,最显然的就是:提高用户的转化率
一、一次性订阅 & 长期订阅
一次性订阅:用户订阅后,在任意时间发一次消息给用户,不能发第二次。
长期订阅:用户订阅后,可长期发送多条信息。(但是这个要求行业和资质高,只有特定的几个类目才能选)
那么如何实现一次性订阅也能长期发送多条消息呢?
如图:
当你调用wx.requestSubscribeMessage接口时(最多可传入3个模板id),就会触发授权弹窗。
注意!细节来了!
弹窗授权为发送一次以下消息(即一次性订阅);
而下方的总是保持以上选择是默认的选择项(字体这么小而且还是灰色的,是不是不容易发现0.0);
简单来讲:授权
发送一次以下消息+总是保持以上选择=只要你授权一次,我就可以无限次发订阅消息
但是需要用户手动开启授权模板,如下图留言通知/榜单更新通知/新活动通知的授权按钮默认是关闭的
虽然说是这么说,但是可以通过诱导(引导)用户来开启,如:不开启可能会导致功能无法使用…
(懂的都懂)

二、操作步骤
接下来是简单的代码实现,具体的可以自己添加更多的业务逻辑
1. 创建模板
进入微信小程序后台—“基础功能”—“订阅消息”,进入"公共模板库"挑选合适的模板后,得到模板ID。

2. 前端授权订阅消息
微信官方文档:小程序订阅消息(用户通过弹窗订阅)开发指南
使用
uni.requestSubscribeMessage发起授权,传参为模板ID,若有多个则需要传数组。
(最多授权3个模板ID)
注:开发时使用了uni-app框架,微信官方的API为 wx.requestSubscribeMessage,效果是一致的。
代码如下(示例):
Tip:可以在关键业务按钮埋下
授权订阅消息代码让用户授权,但也要注意用户体验。
// 创建问题
const createQuestion = async () => {
// 检查模板消息订阅权限
try {
const subscribeResult = await uni.requestSubscribeMessage({
tmplIds: [
'模板ID-1xxxxxx',
'模板ID-2xxxxxx',
],
})
if (subscribeResult.errMsg === 'requestSubscribeMessage:ok') {
// 用户同意了订阅或已经订阅过,继续创建问题
await handleCreateQuestion()
} else {
// 用户拒绝了订阅,显示提示后继续创建
uni.showModal({
title: '订阅提醒',
content: '为了及时接收回复通知,建议您开启订阅消息',
confirmText: '确定',
success: async (res) => {
if (res.confirm) {
// 用户点击确定,继续创建问题
await handleCreateQuestion()
}
},
})
}
} catch (err) {
console.error('请求订阅消息失败:', err)
// 发生错误时仍然允许创建问题
await handleCreateQuestion()
}
}
3. 后端发送订阅消息
环境 SpringBoot + Java17
引入依赖
提高调用效率
<!-- 添加WxJava依赖 -->
<dependency>
<groupId>com.github.binarywang</groupId>
<artifactId>weixin-java-mp</artifactId>
<version>4.5.7.B</version>
</dependency>
<dependency>
<groupId>com.github.binarywang</groupId>
<artifactId>weixin-java-common</artifactId>
<version>4.5.7.B</version>
</dependency>
<!-- fastjson 用于JSON转换 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.75</version>
</dependency>
配置 application.yaml
主要用于获取access_token(发送消息订阅时用)
wx:
mp:
app-id: xxxx
app-secret: xxxx
定义实体类
这里以"活动通知"消息模板为例
@Data
@Accessors(chain = true)
public class ActivityNoticeTemplate {
/**
* 跳转路径,例如:pages/question/detail?id=123
*/
private String path;
/**
* 活动标题
*/
private Thing title;
/**
* 活动名称
*/
private Thing name;
/**
* 活动内容
*/
private Thing content;
@Data
public static class Thing {
private String value;
}
public static ActivityNoticeTemplate build(String path, String title, String name, String content) {
ActivityNoticeTemplate template = new ActivityNoticeTemplate();
template.setPath(path);
Thing titleThing = new Thing();
titleThing.setValue(title);
template.setTitle(titleThing);
Thing nameThing = new Thing();
nameThing.setValue(name);
template.setName(nameThing);
Thing contentThing = new Thing();
contentThing.setValue(content);
template.setContent(contentThing);
return template;
}
}
发送请求
构建内容需要根据你选择的模板内容来构建

实现发送订阅消息
参考代码如下:
private static final String ACTIVITY_NOTICE_TEMPLATE_ID = "模板ID-1xxxxx";
private static final String SUBSCRIBE_MSG_URL = "https://api.weixin.qq.com/cgi-bin/message/subscribe/send";
@Resource
private WxMpService wxMpService;
@Override
public boolean sendActivityNotice(String openId, ActivityNoticeTemplate template) {
try {
// 构建请求数据
JSONObject messageJson = new JSONObject();
messageJson.put("touser", openId);
messageJson.put("template_id", ACTIVITY_NOTICE_TEMPLATE_ID);
messageJson.put("page", template.getPath());
messageJson.put("miniprogram_state", "formal"); // developer为开发版;trial为体验版;formal为正式版
// 构建模板数据 - 根据你选择模板来构建
JSONObject data = new JSONObject();
// 活动标题
JSONObject thing16 = new JSONObject();
thing16.put("value", template.getTitle().getValue());
data.put("thing16", thing16);
// 活动名称
JSONObject thing11 = new JSONObject();
thing11.put("value", template.getName().getValue());
data.put("thing11", thing11);
// 活动内容
JSONObject thing4 = new JSONObject();
thing4.put("value", template.getContent().getValue());
data.put("thing4", thing4);
messageJson.put("data", data);
// 使用SDK发送订阅消息
String responseContent = wxMpService.post(SUBSCRIBE_MSG_URL, messageJson.toJSONString());
// 解析响应
JSONObject response = JSONObject.parseObject(responseContent);
int errcode = response.getIntValue("errcode");
if (errcode == 0) {
log.info("发送活动通知订阅消息成功,openId: {}", openId);
return true;
} else {
log.error("发送活动通知订阅消息失败,openId: {}, errcode: {}, errmsg: {}",
openId, errcode, response.getString("errmsg"));
return false;
}
} catch (WxErrorException e) {
log.error("发送活动通知订阅消息失败,openId: {}, error: {}", openId, e.getMessage(), e);
return false;
}
}
这样就能实现发送订阅消息了~
拓展实现
- 群发:可以遍历数据库中的用户
openid来实现。 - 定时:可以根据业务实现,如节日促销。
- 结合业务:如用户消息回复。
总结
没想到吧,一次性订阅也能无限发送,疯狂轰炸你的微信哈哈哈(bushi)
细节
1. 为什么发请求不传 ACCESS_TOKEN?
答:依赖引入的WxJavaSDK底层实现了access_token的获取和拼接
(access_token是根据你的application.yaml配置的app-id和app-secret来获取)

2. 我怎么知道用户授权订阅消息了没?
好问题,亲测,微信的服务器会记录用户授权了哪个消息模板ID;
咱们开发者只管发,能不能成功就交给微信服务器来判断。
因此,开发者无需记录用户授权了哪个模板,发就完事了!
PS:如果有业务需求的可以记录
⭐⭐⭐纠错
一次性订阅的“总是保持以上” 仅用来实现后续不弹窗、无感接收的效果,和次数统计无关。
订阅次数是用户从该入口进入并同意订阅的次数,可叠加累计,每同意一次次数加一,每下发一条消息消耗一次。
这些次数永久有效,直到全部消耗完;只有用户在设置里主动关闭订阅消息,已存储的次数才会被清零。
PS:小程序的长期订阅模板需要特殊类目才能申请,一般人拿不到;
折中方案:继续使用一次性订阅模板,多放钩子,让用户多点击(有一定的风险)
- 优点:只需要在小程序实现,简单
- 缺点:可发送次数依赖于用户点击的次数
平替方案:使用服务号的模板消息替代(只要用户关注服务号,即永久可推送)
- 优点:可发送无数次
- 缺点:开发成本增加;需引导用户关注服务号;多花300¥开通微信开发者平台关联服务号和小程序。
实现思路:使用微信开发者平台关联小程序和服务号,即可对小程序的用户进行服务号的模板消息推送(前提是用户关注了服务号)
案例:顺丰快递、京东等服务号,其推送是模板消息。

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐



所有评论(0)