微信小程序订阅消息官方文档地址:https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/subscribe-message/subscribeMessage.send.html
本文通过java代码整合小程序接口和rabbitMq,实现订阅消息延时发送。
一,微信小程序开发相关接口
(1)推荐一个小程序插件jar:
<dependency> <groupId>com.github.binarywang</groupId> <artifactId>weixin-java-miniapp</artifactId> <version>3.6.0</version> </dependency>
(2)yml配置文件信息中添加小程序配置信息
wx:
miniapp:
appid: 小程序appid
secret: 小程序secret
msgDataFormat: JSON
(3)添加配置类properties
@Data @ConfigurationProperties(prefix = "wx.miniapp") public class WxMaProperties { /** * 设置微信小程序的appid. */ private String appid; /** * 设置微信小程序的Secret. */ private String secret; /** * 设置微信小程序消息服务器配置的token. */ private String token; /** * 设置微信小程序消息服务器配置的EncodingAESKey. */ private String aesKey; /** * 消息格式,XML或者JSON. */ private String msgDataFormat; }
(4)添加对应的config 加载初始化小程序配置信息
@AllArgsConstructor @Configuration @ConditionalOnClass(WxMaService.class) @EnableConfigurationProperties(WxMaProperties.class) @ConditionalOnProperty(prefix = "wx.miniapp", value = "enabled", matchIfMissing = true) public class WxMaAutoConfiguration { private WxMaProperties properties; /** * 小程序service. * * @return 小程序service */ @Bean @ConditionalOnMissingBean(WxMaService.class) public WxMaService service() { WxMaDefaultConfigImpl config = new WxMaDefaultConfigImpl(); config.setAppid(StringUtils.trimToNull(this.properties.getAppid())); config.setSecret(StringUtils.trimToNull(this.properties.getSecret())); config.setToken(StringUtils.trimToNull(this.properties.getToken())); config.setAesKey(StringUtils.trimToNull(this.properties.getAesKey())); config.setMsgDataFormat(StringUtils.trimToNull(this.properties.getMsgDataFormat())); final WxMaServiceImpl service = new WxMaServiceImpl(); service.setWxMaConfig(config); return service; } }
二,添加rabbitMq相关接口
实现延时消息发送需要安装mq延时插件 官网下载地址:https://www.rabbitmq.com/community-plugins.html
(1)添加mq jar
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-amqp</artifactId> </dependency>
(2) yml 中配置mq
queue: subscribeMsg-delayExchange: com.chunmi.subscribeMsg.delayExchange.local subscribeMsg-delayQueue: com.chunmi.subscribeMsg.delayQueue.local subscribeMsg-delayRoutingKey: com.chunmi.subscribeMsg.delayRoutingKey.local
(3) 添加配置类
@Configuration public class DelayMqConfig { @Value("${queue.subscribeMsg-delayExchange}") public String delayExchange; @Value("${queue.subscribeMsg-delayQueue}") public String delayQueue; @Value("${queue.subscribeMsg-delayRoutingKey}") public String delayRoutingKey; @Bean public CustomExchange delayExchange() { Map<String, Object> args = new HashMap<>(16); args.put("x-delayed-type", "direct"); return new CustomExchange(delayExchange, "x-delayed-message", true, false, args); } @Bean public Queue queue() { return new Queue(delayQueue, true); } @Bean public Binding binding(Queue queue, CustomExchange delayExchange) { return BindingBuilder.bind(queue).to(delayExchange).with(delayRoutingKey).noargs(); } }
(4)添加发送消息类
@Slf4j @Component public class MsgPublishService { @Autowired private RabbitTemplate rabbitTemplate; @Value("${queue.subscribeMsg-delayExchange}") public String delayExchange; @Value("${queue.subscribeMsg-delayRoutingKey}") public String delayRoutingKey; public void sendSubscribeMsg(String str, long delayTimes) { try { rabbitTemplate.convertAndSend(delayExchange, delayRoutingKey, str, new MessagePostProcessor() { @Override public Message postProcessMessage(Message message) throws AmqpException { message.getMessageProperties().setHeader("x-delay", delayTimes); return message; } }); } catch (Exception e) { log.error("发送订阅消息出错:{}", e.getMessage()); e.printStackTrace(); } } }
(5)到这里基本配置信息已经搭建完成,在需要发送订阅消息的接口中封装信息 例如订单未支付给用户发送消息
private void sendSubscrbeMsg(Order order) { try { TemplateVo templateVo = new TemplateVo(); templateVo.setToUser("用户openid"); Map<String, String> map = new HashMap<>(16); templateVo.setTemplateId("模板TemplateId"); templateVo.setPage("消息卡片点击跳转的地址"); //封装data 注意map 的key 和微信公众服务配置信息一致 map.put("character_string1", order.getOrderNo()); //联系人名称 map.put("amount2", order.getTotalFee().toString()); //订单金额 map.put("thing3", "您有一笔等支付的订单,点击查看详情。"); templateVo.setDataMap(map); //延时十分钟发送订阅消息 msgPublishService.sendSubscribeMsg(JSON.toJSONString(templateVo), 10 * 60 * 1000); } catch (Exception e) { e.printStackTrace(); } } 模板信息类: @Data public class TemplateVo implements Serializable { private static final long serialVersionUID = -1L; @ApiModelProperty("订阅模板id") private String templateId; @ApiModelProperty("接收者用户的openid") private String toUser; @ApiModelProperty("点击模板卡片后的跳转页面") private String page; @ApiModelProperty("模板内容") private Map<String, String> dataMap; }
三:在mq服务处理生产者发送的消息
@Slf4j @Service public class SubscribeMsgConsumer { @Autowired private WxMaService wxService; @RabbitListener(queues = {"${queue.subscribeMsg-delayQueue}"}) public void processMsg(String jsonStr) { log.info("接收订阅 时间:{},消息内容:{}", DateUtil.format(new Date(), "yyyy-MM-dd HH:mm:ss"), jsonStr); TemplateVo templateVo = JSONObject.parseObject(jsonStr, TemplateVo.class); WxMaSubscribeMessage subscribeMessage = new WxMaSubscribeMessage(); subscribeMessage.setPage(templateVo.getPage()); subscribeMessage.setTemplateId(templateVo.getTemplateId()); subscribeMessage.setToUser(templateVo.getToUser()); List<WxMaSubscribeData> wxMaSubscribeDataList = new ArrayList<>(); if (!CollectionUtils.isEmpty(templateVo.getDataMap())) { templateVo.getDataMap().forEach((k, v) -> { WxMaSubscribeData data = new WxMaSubscribeData(); data.setName(k); data.setValue(v); wxMaSubscribeDataList.add(data); }); } subscribeMessage.setData(wxMaSubscribeDataList); try { wxService.getMsgService().sendSubscribeMsg(subscribeMessage); } catch (Exception e) { e.printStackTrace(); } } }