微信小程序订阅消息
1. 什么是订阅消息
订阅消息是微信小程序向用户推送通知的方式,分为:
- 一次性订阅:用户授权后只能发送一次
- 长期订阅:可多次发送(需特殊类目资质)
2. 配置
yaml
wechat:
program:
# 小程序AppID - 在微信公众平台(https://mp.weixin.qq.com)注册小程序后获取
appid: YOUR_APPID
# 小程序AppSecret - 在微信公众平台(https://mp.weixin.qq.com)注册小程序后获取
appSecret: secret: YOUR_SECRET3. 初始化服务
java
@Service
public class WxSubscribeMsgService {
@Value("${wechat.program.appid:}")
private String appId;
@Value("${wechat.program.secret:}")
private String appSecret;
private WxMaService wxMaService;
@PostConstruct
public void init() {
WxMaDefaultConfigImpl config = new WxMaDefaultConfigImpl();
config.setAppid(appId);
config.setSecret(appSecret);
wxMaService = new WxMaServiceImpl();
wxMaService.setWxMaConfig(config);
}
}4. 发送订阅消息
4.1 构建消息命令
java
@Data
public class SendSubscribeMsgCommand {
@NotBlank
private String openid;
@NotBlank
private String templateId;
@NotNull
private List<MsgData> data;
private String page;
}
@Data
@AllArgsConstructor
public class MsgData {
private String key; // 模板字段名
private String value; // 字段值
}4.2 发送方法
java
@Service
@RequiredArgsConstructor
public class WxSubscribeMsgService {
private final WxMaService wxMaService;
public void sendSubscribeMsg(SendSubscribeMsgCommand command) throws WxErrorException {
// 构建订阅消息
WxMaSubscribeMessage message = WxMaSubscribeMessage.builder()
.toUser(command.getOpenid())
.templateId(command.getTemplateId())
.data(command.getData())
.page(command.getPage())
.build();
// 调用接口发送
wxMaService.getSubscribeService().sendSubscribeMsg(message);
}
}5. 业务场景示例
5.1 订单状态通知
java
@Service
@RequiredArgsConstructor
public class OrderNotifyService {
private final IWxSubscribeMsgService wxSubscribeMsgService;
private final IDroneOrderService orderService;
private static final String ORDER_TEMPLATE_ID = "YOUR_ORDER_TEMPLATE_ID";
public void sendOrderStatusNotice(Long orderId, String openid) {
DroneOrder order = orderService.getOrderById(orderId);
// 构建消息数据
List<MsgData> data = new ArrayList<>();
data.add(new MsgData("thing11", order.getTitle())); // 订单标题
data.add(new MsgData("phrase10", order.getStatusDesc())); // 状态描述
SendSubscribeMsgCommand command = new SendSubscribeMsgCommand(
openid,
ORDER_TEMPLATE_ID,
data,
"/pages/order/detail?id=" + orderId
);
wxSubscribeMsgService.sendSubscribeMsg(command);
}
}5.2 提现通知
java
@Service
@RequiredArgsConstructor
public class WithdrawalNotifyService {
private final IWxSubscribeMsgService wxSubscribeMsgService;
private final IDroneAccountLogService accountLogService;
private static final String WITHDRAWAL_TEMPLATE_ID = "YOUR_WITHDRAWAL_TEMPLATE_ID";
public void sendWithdrawalNotice(Long accountLogId) {
DroneAccountLog log = accountLogService.getById(accountLogId);
List<MsgData> data = new ArrayList<>();
data.add(new MsgData("amount2", log.getAmount() + "元")); // 提现金额
data.add(new MsgData("phrase3", "待确认")); // 状态
SendSubscribeMsgCommand command = new SendSubscribeMsgCommand(
log.getOpenid(),
WITHDRAWAL_TEMPLATE_ID,
data,
"/pages/wallet/detail?id=" + accountLogId
);
wxSubscribeMsgService.sendSubscribeMsg(command);
}
}6. 模板占位符说明
| 占位符 | 类型 | 说明 |
|---|---|---|
| thing | 文本 | 最多20个字符 |
| number | 数字 | 最多32位数字 |
| amount | 金额 | 格式如 "100.00" |
| phrase | 关键词 | 已配置的关键词 |
| time | 时间 | 格式如 "2024-01-01 12:00:00" |
示例:"thing11" 表示第一个文本字段
7. 调用时机
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ 用户下单 │ -> │ 发送订阅消息 │ -> │ 用户收到通知 │
└─────────────┘ └─────────────┘ └─────────────┘
│
v
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ 支付成功 │ -> │ 发送订阅消息 │ -> │ 用户收到通知 │
└─────────────┘ └─────────────┘ └─────────────┘
│
v
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ 订单完成 │ -> │ 发送订阅消息 │ -> │ 用户收到通知 │
└─────────────┘ └─────────────┘ └─────────────┘8. 依赖
xml
<dependency>
<groupId>com.github.binarywang</groupId>
<artifactId>weixin-java-miniapp</artifactId>
<version>4.5.0</version>
</dependency>9. 注意事项
| 问题 | 原因 | 解决方案 |
|---|---|---|
| 用户收不到消息 | 未订阅 | 引导用户点击订阅按钮 |
| 模板ID错误 | 在小程序后台查找 | 微信公众平台 -> 订阅消息 -> 模板库 |
| 字段格式错误 | 占位符不匹配 | 对照模板修改字段名 |
| access_token过期 | 自动刷新 | SDK自动处理 |