Spring Boot + 微信小程序订阅消息推送
·
一、开发前准备清单
1. 微信侧配置
-
注册小程序(微信公众平台)
-
获取小程序 AppID 和 AppSecret(开发管理->开发设置)
-
申请订阅消息模板(功能->订阅消息)
二、Spring Boot服务搭建
步骤1:初始化项目
通过 Spring Initializr 创建项目,选择:
-
Web
-
Redis
-
Lombok
步骤2:添加关键依赖
<!-- pom.xml -->
<dependencies>
<!-- 基础依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- Redis缓存 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!-- JSON处理 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.83</version>
</dependency>
</dependencies>
步骤3:配置文件
# application.yml
wx:
mini:
appid: wx1234567890abcdef # 替换你的AppID
secret: your_app_secret_here
template-id: TPL_001 # 订阅模板ID
spring:
redis:
host: localhost
port: 6379
三、核心代码实现
1. 微信配置自动加载
@Data
@Configuration
@ConfigurationProperties(prefix = "wx.mini")
public class WxMiniConfig {
private String appid;
private String secret;
private String templateId;
}
2. AccessToken管理器(自动刷新)
@Service
public class WxTokenService {
@Autowired
private RedisTemplate<String, String> redisTemplate;
@Autowired
private WxMiniConfig wxConfig;
private static final String REDIS_KEY = "wx:token";
public String getValidToken() {
// 1. 从Redis查询
String token = redisTemplate.opsForValue().get(REDIS_KEY);
if (StringUtils.isNotBlank(token)) return token;
// 2. 调用微信API获取
String url = String.format(
"https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=%s&secret=%s",
wxConfig.getAppid(), wxConfig.getSecret()
);
JSONObject response = restTemplate.getForObject(url, JSONObject.class);
token = response.getString("access_token");
int expires = response.getIntValue("expires_in");
// 3. 缓存Token(提前200秒过期)
redisTemplate.opsForValue().set(
REDIS_KEY,
token,
expires - 200,
TimeUnit.SECONDS
);
return token;
}
}
3. 消息推送服务
@Service
public class MsgPushService {
@Autowired
private WxTokenService tokenService;
@Autowired
private WxMiniConfig wxConfig;
public boolean pushMessage(String openid, Map<String,String> content) {
String url = "https://api.weixin.qq.com/cgi-bin/message/subscribe/send?access_token="
+ tokenService.getValidToken();
JSONObject params = new JSONObject();
params.put("touser", openid);
params.put("template_id", wxConfig.getTemplateId());
params.put("page", "pages/index/index"); // 跳转路径
JSONObject data = new JSONObject();
content.forEach((key, val) -> {
data.put(key, new JSONObject().fluentPut("value", val));
});
params.put("data", data);
// 发送请求
JSONObject result = restTemplate.postForObject(url, params, JSONObject.class);
return result.getIntValue("errcode") == 0;
}
}
4. 对外接口
@RestController
@RequestMapping("/api/msg")
public class MsgController {
@Autowired
private MsgPushService msgService;
@PostMapping("/push")
public ResponseEntity<String> push(@RequestParam String openid) {
// 构建消息内容(需与模板参数对应)
Map<String, String> data = new HashMap<>();
data.put("thing1", "您的订单已发货");
data.put("time2", LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm")));
boolean success = msgService.pushMessage(openid, data);
return success ?
ResponseEntity.ok("推送成功") :
ResponseEntity.status(500).body("推送失败");
}
}
四、小程序端对接
1. 触发订阅弹窗
// pages/order/order.js
Page({
onSubscribe() {
wx.requestSubscribeMessage({
tmplIds: ['TPL_001'], // 替换你的模板ID
success: (res) => {
if (res['TPL_001'] === 'accept') {
this.sendPushRequest();
}
}
})
},
sendPushRequest() {
wx.request({
url: 'https://xxxx.com/api/msg/push',
method: 'POST',
data: {
openid: getApp().globalData.userInfo.openid // 需提前获取openid
},
success: () => wx.showToast({ title: '消息已发送' })
})
}
})
2. 获取OpenID流程
// app.js
App({
onLaunch() {
wx.login({
success: res => {
wx.request({
url: 'https://your.domain.com/api/wx/login',
data: { code: res.code },
success: (res) => {
this.globalData.openid = res.data.openid;
}
})
}
})
}
})
五、避坑指南
高频问题排查
| 错误码 | 原因 | 解决方案 |
|---|---|---|
| 40001 | AccessToken失效 | 检查Redis缓存是否正常 |
| 43101 | 用户未授权订阅 | 确保已弹出订阅弹窗并点击同意 |
| 47003 | 模板参数错误 | 检查data字段与模板参数是否匹配 |
更多推荐
所有评论(0)