1、概述

微信公众号模板消息是腾讯提供的一种采用公众号发送消息方式,微信公众号官方提供了基础模板消息接口供业务调用。但是,如何在业务里面更加合理地发送模板消息是个难题。将消息以异步队列的方式和主业务功能解耦,实现不会因为消息发送影响主业务的正确性和性能;同时,解耦出来的消息队列可以用多种策略提高消息的送达率。为此,实现一种开源基于Redis的公众号模板消息队列开源框架奇辰Open-API。

2、开源框架架构

基于奇辰Open-API实现的前后端分离云原生应用前端请求后端业务如步骤1所示;需要通过微信公众号模板消息通知用户的场景直接调用奇辰Open-API封装好的消息中心往消息队列里面添加待发送的模板消息内容如步骤2所示;由奇辰Open-API消息中心自动完成微信基础API、SDK调用如步骤3所示;最终实现通过微信公众号给用户发送消息通知如步骤4所示。

3、开源实现

3.1原理技术

消息队列基于Redis的List数据结构管理消息队列,生产者(主业务流程)往List队列添加消息,消费者(消息中心)端能获取待发送消息,然后调用封装好的消息功能进行处理,实现主业务流程和消息中心的解耦。消息中心采用Java Springboot框架实现,调用Jedis接口实现Redis应用功能。

3.2消息触发

@SpringBootTest
class MessageApplicationTests {@AutowiredRedisTemplate<String, Object> redisTemplate;@Testvoid contextLoads() {JSONObject message = new JSONObject();message.put("openid", "omOR006*******2qevI");redisTemplate.opsForList().leftPush("message:queue", JSON.toJSONString(message));}}

采用Springboot的test机制模拟往openid为omOR006*******2qeVI的用户发送消息标识为message:queue的公众号模板消息,在第10、12行实现。

消息添加接口:

由于消息队列基于Redis的List数据结构实现采用Java Springboot框架实现,在Springboot框架调用Jedis连接Redis并进行操作。Jedis配置如下:

  • 添加redis依赖
<!-- redis --><dependency><groupId>redis.clients</groupId><artifactId>jedis</artifactId><version>3.3.0</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId><!--<version>2.1.4.RELEASE</version>--></dependency>
  • 配置redis参数
@Configuration
public class RedisConfig {/*** 设置Redis序列化方式,默认使用的JDKSerializer的序列化方式,效率低,这里我们使用 FastJsonRedisSerializer* @param redisConnectionFactory* @return*/@Beanpublic RedisTemplate<String, Object> redisTemplate(LettuceConnectionFactory redisConnectionFactory) {RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();// key序列化redisTemplate.setKeySerializer(new StringRedisSerializer());// value序列化redisTemplate.setValueSerializer(new StringRedisSerializer());// Hash key序列化redisTemplate.setHashKeySerializer(new StringRedisSerializer());// Hash value序列化redisTemplate.setHashValueSerializer(new StringRedisSerializer());redisTemplate.setConnectionFactory(redisConnectionFactory);return redisTemplate;}
}
  • 消息管理

开源框架已经对消息队列的管理进行了低代码封装,只需要在在后台可视化添加消息模板即可自动完成消息队列管理,如下图所示:

3.3队列消息发送

发送机制:开启独立线程(根据消息规模选取合适线程数量),循环判断消息队列是否有新消息。

@PostConstructpublic void brPop() {new Thread(() -> {List<Template> template_list = templateDao.queryAll();for (Template message_template : template_list) {if(message_template.getIdentity() != null && !message_template.getIdentity().equals("")) {while (true) {try {String message = (String) redisTemplate.opsForList().rightPop(message_template.getIdentity(), 10,TimeUnit.SECONDS);if (message != null) {RestTemplate template = new RestTemplate();String access_token = (String) redisTemplate.opsForValue().get("mp_access_token");if (access_token == null) {ConfMp conf = confMpDao.query();if (conf != null) {try {String url = "https://api.weixin.qq.com/cgi-bin/token?grant_type={grant_type}&appid={appid}&secret={secret}";Map<String, Object> requestMap = new HashMap<>();// JSONObject requestMap = new JSONObject();requestMap.put("grant_type", "client_credential");requestMap.put("appid", conf.getAppid());requestMap.put("secret", conf.getSecret());ResponseEntity<JSONObject> responseEntity = template.getForEntity(url, JSONObject.class, requestMap);HttpStatus statusCode = responseEntity.getStatusCode(); // 获取响应码if (statusCode == HttpStatus.OK) {JSONObject body = responseEntity.getBody();if (body.get("access_token") != null) {access_token = body.getString("access_token");Integer expires_in = body.getInteger("expires_in") - 5 * 60;redisTemplate.opsForValue().set("mp_access_token", access_token,expires_in,TimeUnit.SECONDS);}} else {log.error("saas 服务访问失败!");// throw new RuntimeException("saas 服务访问失败!");}} catch (Exception e) {log.error(e.toString());// throw new RuntimeException(e.toString());}}}if (access_token != null) {// Template template = templateDao.queryAll()String url = "https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=" + access_token;Map<String, Object> requestMap = new HashMap<>();// JSONObject requestMap = new JSONObject();JSONObject message_json = JSON.parseObject(message);requestMap.put("touser", message_json.getString("openid"));requestMap.put("template_id", message_template.getMp_template_id());Map<String, Object> data = new HashMap<>();Map<String, Object> first = new HashMap<>();first.put("value", "first");first.put("color", "#173177");data.put("first", first);Map<String, Object> keyword1 = new HashMap<>();keyword1.put("value", "keyword1");keyword1.put("color", "#173177");data.put("keyword1", first);Map<String, Object> keyword2 = new HashMap<>();keyword2.put("value", "keyword2");keyword2.put("color", "#173177");data.put("keyword2", first);Map<String, Object> keyword3 = new HashMap<>();keyword3.put("value", "keyword3");keyword3.put("color", "#173177");data.put("keyword3", first);Map<String, Object> keyword4 = new HashMap<>();keyword4.put("value", "keyword4");keyword4.put("color", "#173177");data.put("keyword4", first);Map<String, Object> remark = new HashMap<>();remark.put("value", "remark");remark.put("color", "#173177");data.put("remark", remark);requestMap.put("data", data);template.postForEntity(url, requestMap, JSONObject.class);}}} catch (Exception e) {log.info(e.toString());}}}}}).start();}

在第9行检测Redis的消息队列是否有新的消息:如果有新消息,根据对应消息的唯一标识查看对应公众号模板消息ID,调用微信公众号模板消息接口发送模板消息给用户,如下图所示:

微信模板消息:为了发送微信公众号模板消息,首先要获取公众号access token,见代码第25行;然后再以access token为参数加上微信公众号官网获取的模板消息ID,调用微信公众号接口实现模板消息发送,见代码第82行,这个过程开源框架已经封装实现,不需要单独开发。

消息队列在开源框架的message模块里面实现,该模块可以单独运行,保证主业务流程的运行和消息中心的运行独立,减轻主业务流程运行、维护负担,同时使得消息中心的研发也相对独立。

4、更多

开源项目:Open-Api

更多信息:www.lokei.cn

5、后续完善

后续可以继续完善的地方主要有两方面:1)处理微信公众号模板消息外,可以支持短信、邮件等更多消息模式;2)针对更大规模消息队列,可以考虑集成Kafaka等更加复杂消息队列方式。

【开源微信】Java实现基于Redis公众号模板消息队列相关推荐

  1. C#开发微信门户及应用(27)-公众号模板消息管理

    原文:C#开发微信门户及应用(27)-公众号模板消息管理 通过模板消息接口,公众号能向关注其账号的用户发送预设模板的消息.模板消息仅用于公众号向用户发送重要的服务通知,只能用于符合其要求的服务场景中, ...

  2. 基于tp5 微信公众号模板消息

    首先引入微信sdk,然后配置appid,appsecret,然后实例化类 发送模板消息前期准备 先通过appid appsecret获取code ,然后通过code获取access_token 通过a ...

  3. 微信公众号 - Java推送公众号模板消息给用户

    不啰嗦,我们直接开始! 由于没有公众帐号,本文使用微信公众平台接口测试帐号进行调试. 一.申请测试帐号 1.使用微信扫码登录下面网址 微信公众平台 (qq.com) 2.找到appID和appsecr ...

  4. java程序集成微信公众号模板消息功能

    要在 Java 程序中集成微信公众号模板消息功能,您需要按照以下步骤进行: 在微信公众平台上申请并获取您的公众号的 appid 和 appsecret. 使用 appid 和 appsecret 调用 ...

  5. 微信公众号模板消息管理

    通过模板消息接口,公众号能向关注其账号的用户发送预设模板的消息.模板消息仅用于公众号向用户发送重要的服务通知,只能用于符合其要求的服务场景中,如信用卡刷卡通知,商品购买成功通知等.不支持广告等营销类消 ...

  6. 微信公众号-模板消息管理

    微信公众号-模板消息管理 通过模板消息接口,公众号能向关注其账号的用户发送预设模板的消息.模板消息仅用于公众号向用户发送重要的服务通知,只能用于符合其要求的服务场景中,如信用卡刷卡通知,商品购买成功通 ...

  7. java redis延迟队列_基于redis实现的延迟消息队列

    delay-queue redis实现延迟消息队列 需求背景 最近在做一个排队取号的系统 在用户预约时间到达前XX分钟发短信通知 在用户预约时间结束时要判断用户是否去取号了,不然就记录为爽约 在用户取 ...

  8. 公众平台模板消息所在行业_微信公众号模板消息功能怎么快速推送?

    公众号平台上模板消息功能仅支持添加模板和更改所在行业,不支持模板消息推送,如果想要实现更多功能效果,可以使用微号帮平台的模板消息群发功能实现,也可以通过公众号平台的接口自己开发实现功能,均可以达到微信 ...

  9. 公众平台模板消息所在行业_第三方工具微信公众号模板消息群发如何操作?

    当下,公众平台模板消息功能仅支持添加模板,修改所在行业,如果想要群发模板消息,可以自己根据公众平台的接口编程实现,也可通过微号帮平台的模板消息群发功能实现,均可以让微信公众号群发模板消息,模板消息即按 ...

  10. 微信小程序——订阅消息与微信公众号模板消息

    订阅消息 一次性订阅消息 某个按钮(并且只能是用户自己就手动点击的)操作调起来这个允许授权弹窗,允许通知之后也只能发送一次消息.即便点上[总是保持一上选择,不再询问]也只是在下次点击同一个按钮时默认允 ...

最新文章

  1. win7系统启动到一半停止_win7系统启动一半死机的解决方法
  2. 【JZOJ1637】【ZJOI2009】狼和羊的故事
  3. github中origin和upstream的区别(转)
  4. 通过History Trends Unlimited通过统计台式机Chrome浏览器Top10网页历史访问量(2021.11.23)
  5. 记一次Sentry部署过程
  6. 动手学CV-目标检测入门教程2:VOC数据集
  7. Ruby中的Mixin
  8. drf 安装_drf 安装与配置
  9. 串口监视工具百度云免费下载
  10. 图解TCPIP---第一章
  11. 小程序毕设作品之微信积分商城小程序毕业设计成品(6)开题答辩PPT
  12. 机器学习——K均值算法(K-means)
  13. 拉钩教育大前端课程学习-半年总结
  14. matlab如何模拟数字舵机,模拟舵机和数字舵机区别
  15. C语言中文件指针和文件位置指针,位置指针相关库函数
  16. 已知圆上三点坐标求圆心
  17. 计算机英语(王艺)翻译(unit1-unit5)
  18. linux mysql 1055_mysql 1055错误
  19. 基于WEB快速开发平台的轻量ERP
  20. Angular(一)

热门文章

  1. origin画图初步入门
  2. android炫酷动画源码,QQ菜单、瀑布流、二维码源码
  3. 何宾 单片机原理及应用_STC单片机原理及应用何宾答案
  4. ASP.NET MVC 5高级编程 (pdf书)
  5. omnigraffle所有模板免费下载网站
  6. Symbian面试题
  7. aop面向切面编程(aspectJweaver)
  8. matlab 阶乘函数
  9. CentOS安装jre环境
  10. 通过IP查询地址之纯真IP数据库