最近遇到一个需求,需要推送微信小程序订阅消息,下面分享一下实现步骤以及过程中踩到的坑。
首先是发送订阅消息的api和所需要的一些参数
POST https://api.weixin.qq.com/cgi-bin/message/subscribe/send?access_token=ACCESS_TOKEN
- access_token: 接口调用凭证,具体获取方式可参照获取接口调用凭据 | 微信开放文档
- template_id:订阅模版id,需要在发开者页面进行配置
- touser:接收者的open_id,获取方式可参考上一篇分享Java实现微信小程序登录_java微信小程序登录_DearMrWhite的博客-CSDN博客
- data:模版内容(此处会有一些坑,下面会具体讲解)
- miniprogram_state:调整小程序类型,developer为开发版;trial为体验版;formal为正式版;默认为正式版
接下来是具体实现:
/**
* 发送订阅请求
*/
public boolean sendSubscriptionMessage(String accessToken, String openId, String programState) {
return sendSubscribeMessage(accessToken, openId, programState, formatData());
}
/**
* 拼接请求参数data
*/
private JSONObject formatData() {
JSONObject data = new JSONObject();
data.put("thing4", createJsonObj("测试thing4"));
data.put("thing2", createJsonObj("测试thing2"));
data.put("date5", createJsonObj("2023年09月18日 14:00"));
data.put("thing6", createJsonObj("测试thing6"));
data.put("name1", createJsonObj("测试姓名"));
return data;
}
private JSONObject createJsonObj(String value) {
JSONObject obj = new JSONObject();
obj.put("value", value);
return obj;
}
/**
* 发送订阅请求
*/
private boolean sendSubscribeMessage(String accessToken, String toUser, String programState, JSONObject data) {
String subscribeUrl = buildWeChatSubscribeUrl(accessToken);
HttpEntity<String> entity = setSubscribeRequestEntity(toUser, programState, data);
ResponseEntity<String> response;
try {
response = restTemplate.postForEntity(subscribeUrl, entity, String.class);
} catch (RestClientException e) {
log.error("微信订阅消息推送失败:", e);
return false;
}
Integer responseCode = JSONObject.parseObject(response.getBody()).getInteger("errcode");
if (responseCode != 0) {
log.error("微信订阅消息推送失败, 错误代码:{}, 消息体:{}", responseCode, entity);
return false;
}
return true;
}
/**
* 构建消息推送的url
*/
private String buildWeChatSubscribeUrl(String accessToken) {
return UriComponentsBuilder.fromHttpUrl(wxConfig.getSubscribeApiUrl())
.queryParam("access_token", accessToken)
.toUriString();
}
/**
* 设置消息订阅请求参数
*/
private HttpEntity<String> setSubscribeRequestEntity(String toUser, String programState, JSONObject data) {
JSONObject body = new JSONObject();
body.put("touser", toUser);
body.put("template_id", wxConfig.getSubscribeTemplateId());
body.put("data", data);
body.put("miniprogram_state", programState);
HttpHeaders header = new HttpHeaders();
header.add("Content-Type", "application/json;charset=UTF-8");
return new HttpEntity<>(body.toString(), header);
}
第一个需要特别注意的是在封装请求参数data的时候,一定要注意模版字段类型和对应的数据格式要求。比如,name字段的要求是10个以内纯汉字或20个以内纯字母或符号。因为我当时需要推送的内容是小程序端页面表格填写的,但是名称字段没有做格式限制,导致这个字段在测试的时候输入了数字内容,发送通知的时候就会报错。所以一定要仔细阅读微信开发者文档,并结合自身项目的实际需求来开发。
第二个是切勿“滥用”access_token,这里的“滥用”是指获取access_token的入口不唯一。小程序的access_token有效期为7200秒,所以可以考虑将其放入缓存并定期刷新,而不是哪里需要哪里重新获取,这样很有可能导致第一次获取的access_token,因为不知道哪个地方又获取了一次,导致access_token失效。
好了,今天的分享就到这里啦,祝大家编码愉快~