wechat_message_push.md 5.95 KB

微信小程序订阅消息推送后端开发文档(适用于 Spring Boot 微服务)

1. 背景与目标

本方案通过微信小程序的 订阅消息(Subscribe Message) 能力,在用户授权的前提下,在特定时间向用户推送服务通知。例如在订餐周期开启前提醒用户开始订餐。

微信要求订阅消息必须通过用户主动操作获得授权,且每次授权只能发送一次消息(非特权行业除外)。(Medium)


2. 模板申请与配置

2.1 登录微信公众平台

  1. 登录微信公众平台(小程序管理后台)。
  2. 在左侧菜单选择 功能 → 订阅消息
  3. 公共模板库 中查找最符合业务场景的模板;如无合适模板,可新建申请。
  4. 按需选择关键词组合并提交审核。
  5. 审核通过后在“我的模板”中得到 模板 ID

说明:该模板 ID 将用于消息发送接口参数。(aigwa.com)


3. 小程序前端授权流程简述

在前端,当用户在小程序产生关键交互(例如提交订单成功后)时,需要通过 wx.requestSubscribeMessage 调起订阅授权。

wx.requestSubscribeMessage({
  tmplIds: ['TEMPLATE_ID'],
  success(res) {
    // 例如:res['TEMPLATE_ID'] = "accept" | "reject" | ...
    // 结果上报后端
  }
})

提示:


4. 后端核心概念与数据模型

4.1 订阅授权状态表(示例)

CREATE TABLE wx_subscribe_permission (
  id BIGINT PRIMARY KEY AUTO_INCREMENT,
  openid VARCHAR(64) NOT NULL,
  template_id VARCHAR(64) NOT NULL,
  biz_type VARCHAR(32) NOT NULL,
  order_cycle_id VARCHAR(32),
  status ENUM('PENDING','USED','FAILED') NOT NULL DEFAULT 'PENDING',
  retry_count INT DEFAULT 0,
  last_error VARCHAR(255),
  authorized_at DATETIME,
  used_at DATETIME,
  created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
  updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);
  • PENDING:用户已授权但未发送;
  • USED:发送成功;
  • FAILED:发送失败且不再重试。

5. 微信服务端 API 调用

5.1 获取 access_token

用于后端所有接口调用授权凭证:

GET https://api.weixin.qq.com/cgi-bin/token
?grant_type=client_credential
&appid=APPID
&secret=APPSECRET

返回示例:

{
  "access_token": "ACCESS_TOKEN",
  "expires_in": 7200
}

5.2 发送订阅消息

使用订阅消息下发接口:

POST https://api.weixin.qq.com/cgi-bin/message/subscribe/send?access_token=ACCESS_TOKEN

请求 JSON 示例

{
  "touser": "USER_OPENID",
  "template_id": "TEMPLATE_ID",
  "page": "pages/order/index?cycleId=202501",
  "data": {
    "thing1": { "value": "下次订餐即将开启" },
    "time2": { "value": "周一 09:00" },
    "thing3": { "value": "请点击跳转完成订餐" }
  }
}

字段说明:

  • touser:接收用户微信 OpenID;
  • template_id:模板 ID;
  • page:消息点击跳转页面路径;
  • data:模板关键词对应数据。(gitcode.csdn.net)

6. 后端主要接口设计

6.1 授权结果回传 API(POST)

URL/api/wechat/subscribe/authorize

请求示例

{
  "openid": "xxxx",
  "templateId": "TEMPLATE_ID",
  "bizType": "ORDER_REMIND",
  "orderCycleId": "202501",
  "result": "accept"
}

响应示例

{ "code": 0, "msg": "ok" }

逻辑:

  • 若 result = accept,写入 wx_subscribe_permission 表;
  • 否则记录拒绝状态。

6.2 定时发送任务

后端定时任务(如 @Scheduled)在规定时间触发:

  1. 查询所有 status = PENDING 且对应用户未订餐的记录;
  2. 将消息入队(如 MQ);
  3. 消费执行发送逻辑;
  4. 更新 statusretry_count

7. 发送逻辑与重试策略

7.1 核心发送逻辑(伪码)

for (Permission p : pendingList) {
  try {
    sendSubscribeMessage(p);
    p.setStatus("USED");
    p.setUsedAt(now());
  } catch (WeChatApiException e) {
    if (canRetry(e) && p.getRetryCount() < 3) {
      p.incrementRetry();
    } else {
      p.setStatus("FAILED");
      p.setLastError(e.getMessage());
    }
  }
  update(p);
}

8. 常见错误码处理

错误码 说明 处理方式
43101 用户拒绝 标记 FAILED 不再重试
40001 access_token 错误 刷新 Token 并重试
网络错误 网络抖动 按退避重试

9. 测试建议

  1. 先使用测试 OpenID 调用发送接口;
  2. 检查模板字段是否与后台组装一致;
  3. 校验跳转页面路径参数是否正确。

10. 参考链接

  • 微信官方订阅消息后端发送接口说明(subscribeMessage.send)(gitcode.csdn.net)
  • 小程序端授权调用说明(wx.requestSubscribeMessage)(wdk-docs.github.io)

如果你需要,我可以进一步提供 Spring Boot 样板代码(包括定时任务 & 消息发送 Service 实现)。