由于微信官方政策调整,模板消息已经升级为“订阅消息”,原来的模板消息需要用户在小程序内产生特定行为(如支付、提交表单)后才能触发,而订阅消息则允许用户主动订阅,之后开发者可以在一定时间内(通常为30天)向用户推送服务通知。
我将为你详细讲解如何使用 “订阅消息” 来实现类似模板消息的功能。
整体流程概览
- 获取模板ID:在微信公众平台申请并添加你需要的消息模板。
- 获取用户授权:在小程序中引导用户同意订阅,并获取
subscription item(订阅消息凭证)。 - 后端服务调用API:你的服务器使用
subscription item和模板ID,向微信服务器发送请求,推送消息。 - 用户接收消息:用户在微信的“服务通知”中收到推送的消息。
详细步骤
第一步:申请订阅消息模板
这是所有工作的前提,你需要先在微信公众平台后台配置好消息模板。
-
登录微信公众平台:
- 访问 https://mp.weixin.qq.com
- 登录你的小程序账号。
-
进入模板库:
- 在左侧菜单栏找到 「开发」 -> 「开发管理」 -> 「订阅消息」。
- 点击进入,然后点击 「公共模板库」。
-
选择并添加模板:
- 在模板库中,你可以根据行业和应用场景搜索模板,搜索“订单支付成功”、“物流更新”等。
- 找到合适的模板后,点击右侧的 「选用」 按钮。
- 选中模板后,点击页面底部的 「添加」 按钮。
-
记录模板ID:
- 添加成功后,模板会出现在你的 「我的模板」 列表中。
- 复制这个模板的 「模板ID」,这个ID在后续的API调用中会用到。
示例模板结构: 一个模板通常包含一些固定的文本和可替换的关键词(用 包围),一个“订单支付成功”的模板可能如下:
{{thing1.DATA}},您的订单{{number2.DATA}}已支付成功,金额为{{amount3.DATA}}元,{{phrase4.DATA}}。
这里的 thing1, number2, amount3, phrase4 就是模板的关键词,你在发送消息时需要提供对应的值。
第二步:在小程序中获取用户授权
用户必须主动同意订阅,你才能给他发消息,这个过程通常在一个用户触发的操作之后进行,比如点击“订阅通知”按钮。
-
前端代码 (WXML): 创建一个按钮来触发订阅请求。
<!-- pages/index/index.wxml --> <button bindtap="requestSubscribe">订阅订单支付通知</button>
-
前端代码 (JS): 在页面的 JS 文件中,调用
wx.requestSubscribeMessageAPI 来请求用户授权。// pages/index/index.js Page({ data: {}, // 请求订阅消息 requestSubscribeMessage() { // 1. 定义你想要订阅的模板ID列表 const templateIds = ['你的模板ID_1', '你的模板ID_2']; // 可以一次请求多个 // 2. 调用API请求订阅 wx.requestSubscribeMessage({ tmplIds: templateIds, success: (res) => { console.log('订阅请求成功', res); // res 返回一个对象,key 是 tmplId,value 是 'accept' 或 'reject' // { '你的模板ID_1': 'accept', '你的模板ID_2': 'reject' } if (res['你的模板ID_1'] === 'accept') { wx.showToast({ title: '订阅成功!', icon: 'success' }); // 用户同意后,通常会将这个凭证传给后端保存,以便后续使用 // 这里为了演示,我们直接调用发送函数 this.sendSubscriptionMessage(); } else { wx.showToast({ title: '您拒绝了订阅', icon: 'none' }); } }, fail: (err) => { console.error('订阅请求失败', err); wx.showToast({ title: '订阅失败', icon: 'none' }); } }); }, // 调用后端API发送订阅消息 sendSubscriptionMessage() { wx.showLoading({ title: '发送中...', }); // 调用我们自己写的后端接口 wx.request({ url: 'https://你的域名.com/api/send-subscribe-message', // 替换成你的后端接口地址 method: 'POST', data: { // 这里可以传一些用户信息,比如订单号、用户openid等 orderNo: 'DD202510270001', // 用户openid,通常是从全局变量或登录接口获取 openid: '用户的openid' }, success: (res) => { wx.hideLoading(); if (res.data.code === 0) { wx.showToast({ title: '消息发送成功!', icon: 'success' }); } else { wx.showToast({ title: res.data.msg || '发送失败', icon: 'none' }); } }, fail: (err) => { wx.hideLoading(); console.error('调用后端接口失败', err); wx.showToast({ title: '网络错误', icon: 'none' }); } }); } });
第三步:后端服务调用API发送消息
这是核心步骤,你的服务器需要使用微信提供的 subscribeMessage.send API 来实际推送消息。
API信息:
- 请求地址:
https://api.weixin.qq.com/cgi-bin/subscribe/send?access_token=ACCESS_TOKEN - 请求方式:
POST - 请求头:
Content-Type: application/json
准备工作:
你的后端需要能够获取到 access_token。access_token 是调用微信接口的全局凭证,有效期为2小时,需要缓存并定时刷新。
- 获取
access_token的API:https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET
请求体示例 (JSON):
{
"touser": "用户的openid",
"template_id": "你的模板ID",
"data": {
"thing1": {
"value": "微信小店"
},
"number2": {
"value": "123456789"
},
"amount3": {
"value": "128.00"
},
"phrase4": {
"value": "欢迎再次光临"
}
}
}
参数说明:
touser:接收消息用户的openid。template_id:你在第一步申请到的模板ID。data:一个对象,键是模板中的关键词(如thing1),值是一个包含value属性的对象,value就是你想替换上去的具体内容。
后端代码示例 (Node.js/Express):
// 引入依赖
const axios = require('axios');
const crypto = require('crypto');
// 微信小程序的 AppID 和 AppSecret
const APP_ID = '你的小程序AppID';
const APP_SECRET = '你的小程序AppSecret';
// 用于存储 access_token
let accessToken = '';
let tokenExpireTime = 0;
// 获取 access_token 的函数
async function getAccessToken() {
const currentTime = Date.now();
// token 存在且未过期,直接返回
if (accessToken && currentTime < tokenExpireTime) {
return accessToken;
}
console.log('正在获取新的 access_token...');
try {
const response = await axios.get('https://api.weixin.qq.com/cgi-bin/token', {
params: {
grant_type: 'client_credential',
appid: APP_ID,
secret: APP_SECRET
}
});
accessToken = response.data.access_token;
tokenExpireTime = currentTime + (response.data.expires_in - 300) * 1000; // 提前5分钟刷新
return accessToken;
} catch (error) {
console.error('获取 access_token 失败', error);
throw error;
}
}
// 发送订阅消息的接口
router.post('/api/send-subscribe-message', async (req, res) => {
try {
const { orderNo, openid } = req.body; // 从请求体中获取数据
if (!openid || !orderNo) {
return res.json({ code: -1, msg: '参数错误' });
}
// 1. 获取 access_token
const token = await getAccessToken();
// 2. 准备发送消息的数据
const templateId = '你的模板ID'; // 从配置或数据库中获取
const messageData = {
touser: openid,
template_id: templateId,
data: {
thing1: { value: "微信小店" },
number2: { value: orderNo },
amount3: { value: "128.00" },
phrase4: { value: "欢迎再次光临" }
}
};
// 3. 调用微信 API 发送消息
const apiResponse = await axios.post(
`https://api.weixin.qq.com/cgi-bin/subscribe/send?access_token=${token}`,
messageData
);
// 4. 处理微信 API 的返回结果
if (apiResponse.data.errcode === 0) {
res.json({ code: 0, msg: '消息发送成功' });
} else {
console.error('微信API返回错误', apiResponse.data);
res.json({ code: apiResponse.data.errcode, msg: apiResponse.data.errmsg });
}
} catch (error) {
console.error('发送订阅消息时发生错误', error);
res.status(500).json({ code: -1, msg: '服务器内部错误' });
}
});
总结与注意事项
- 订阅消息 vs 模板消息:请务必使用最新的 订阅消息 API,旧的模板消息接口已基本废弃。
- 用户主动:订阅消息的核心是 用户授权,你不能在用户不知情的情况下给他发消息。
wx.requestSubscribeMessage是获取授权的标准方式。 - 凭证时效性:
wx.requestSubscribeMessage返回的subscription item是有时效性的(通常为30天),你的后端需要妥善存储它,并在发送消息时使用。 access_token管理:后端的access_token必须缓存,避免频繁请求导致微信API调用次数超限或被封禁。- 内容合规:发送的消息内容必须符合微信平台规范,不能包含敏感、营销或诱导性词语,否则会被拦截或处罚。
- 错误处理:后端代码需要充分处理各种错误情况,如
access_token失效、用户拒绝订阅、模板ID错误等,并给出明确的返回信息。
遵循以上步骤,你就可以成功地在你的微信小程序中集成订阅消息功能了。
