当前位置:   article > 正文

Java实现微信公众号给关注用户推送信息实现详解_微信公众号 java 针对已关注的用户 推送消息

微信公众号 java 针对已关注的用户 推送消息

需求背景:小程序下单完成之后,通过微信公众号给关注的用户推送信息、小程序和公众号的同一ID为unionId

前置条件

(1)在公众号开放平台绑定小程序和公众号是同一主体【公众账号和小程序】

(2)开通服务号模版消息接口授权使用(一般需要两到三天)

(3)公众号配置通知地址

提交配置的时候,可能会提示token无效,那是因为接口验证没有通过、代码验签实现如下:

【因为接收事件推送消息的数据包是XML格式,所以需要倒入解析的jar包】

  • 接收的数据格式
  1. <xml>
  2. <ToUserName>< ![CDATA[toUser] ]></ToUserName>
  3. <FromUserName>< ![CDATA[FromUser] ]></FromUserName>
  4. <CreateTime>123456789</CreateTime>
  5. <MsgType>< ![CDATA[event] ]></MsgType>
  6. <Event>< ![CDATA[subscribe] ]></Event>
  7. </xml>
  • 导入的jar包
  1. <dependency>
  2. <groupId>dom4j</groupId>
  3. <artifactId>dom4j</artifactId>
  4. <version>1.6.1</version>
  5. </dependency>

代码实现

  1. import com.alibaba.fastjson.JSON;
  2. import com.alibaba.fastjson.JSONObject;
  3. import org.apache.commons.lang3.StringUtils;
  4. import org.dom4j.Document;
  5. import org.dom4j.Element;
  6. import org.dom4j.DocumentHelper;
  7. import org.slf4j.Logger;
  8. import org.slf4j.LoggerFactory;
  9. import org.springframework.web.bind.annotation.*;
  10. import javax.servlet.http.HttpServletRequest;
  11. import java.io.*;
  12. import java.security.MessageDigest;
  13. import java.security.NoSuchAlgorithmException;
  14. import java.util.Arrays;
  15. /**
  16. * @version 1.0
  17. * @description: 公众号订阅通知
  18. */
  19. @RestController
  20. public class SubscribeNoticeController {
  21. private static final Logger log = LoggerFactory.getLogger(SubscribeNoticeController.class);
  22. /**
  23. * @GetMapping@PostMapping 路径名称是一样的,一个用来验证token、一个用来接收数据
  24. */
  25. /**
  26. * token 验签
  27. */
  28. @GetMapping("/noticeInfo")
  29. Long checkParams(@RequestParam("signature") String signature,
  30. @RequestParam("timestamp") String timestamp,
  31. @RequestParam("nonce") String nonce,
  32. @RequestParam("echostr") String echostr){
  33. String token = "和你在公众号配置中的token保持一致";
  34. String[] arr = {token, timestamp, nonce};
  35. Arrays.sort(arr);
  36. StringBuilder content = new StringBuilder();
  37. for (int i = 0; i < arr.length; i++) {
  38. content.append(arr[i]);
  39. }
  40. //sha1Hex 加密
  41. MessageDigest md = null;
  42. String temp = null;
  43. try {
  44. md = MessageDigest.getInstance("SHA-1");
  45. byte[] digest = md.digest(content.toString().getBytes());
  46. temp = byteToStr(digest);
  47. } catch (NoSuchAlgorithmException e) {
  48. e.printStackTrace();
  49. }
  50. if ((temp.toLowerCase()).equals(signature)){
  51. /**
  52. * 重点:要把接收的这个随机码返回
  53. */
  54. return Long.valueOf(echostr);
  55. }
  56. return null;
  57. }
  58. /**
  59. * 接收推送的数据
  60. */
  61. @PostMapping("/noticeInfo")
  62. @ResponseBody
  63. public String subscribeProcessor(HttpServletRequest request) throws Exception {
  64. BufferedReader br = request.getReader();
  65. String str="";
  66. String paramInfo = "";
  67. while((str = br.readLine()) != null){
  68. paramInfo += str;
  69. }
  70. if (StringUtils.isNotBlank(paramInfo)){
  71. JSONObject jsonObject = JSON.parseObject(paramInfo);
  72. String xmlInfo = jsonObject.getString("xmlInfo");
  73. paramInfo = xmlInfo;
  74. }
  75. log.info("微信公众号接收信息:{}",paramInfo);
  76. paramInfo = paramInfo.replaceAll(" ", "");
  77. Document document = DocumentHelper.parseText(paramInfo);
  78. Element root = document.getRootElement();
  79. String toUserName = root.elementText("ToUserName");
  80. String fromUserName = root.elementText("FromUserName");
  81. String createTime = root.elementText("CreateTime");
  82. String msgType = root.elementText("MsgType");
  83. String event = root.elementText("Event");
  84. log.info("微信公众号接收信息:{},{},{},{},{}",toUserName,fromUserName,createTime,msgType,event);
  85. /**
  86. * 处理后续的逻辑信息...
  87. */
  88. return null;
  89. }
  90. private static String byteToStr(byte[] byteArray){
  91. String strDigest = "";
  92. for (int i = 0; i < byteArray.length; i++) {
  93. strDigest += byteToHexStr(byteArray[i]);
  94. }
  95. return strDigest;
  96. }
  97. private static String byteToHexStr(byte mByte){
  98. char[] Digit = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A','B', 'C', 'D', 'E', 'F' };
  99. char[] tempArr = new char[2];
  100. tempArr[0] = Digit[(mByte >>> 4)& 0X0F];
  101. tempArr[1] = Digit[mByte & 0X0F];
  102. String s = new String(tempArr);
  103. return s;
  104. }
  105. }

至此就可以接收公众号推送的信息了、比如用户的订阅、取关事件都能有通知。

实现推送消息给用户

前面代码已经可以监听到用户的订阅、取关的事件了,因为可以通过用户订阅的事件拿到用户的FromUserName(用户的openId)信息、通过这个字段,就能查到用户的unionId、然后把openId和unionId保存到数据库、相关实现方法:

  1. /**
  2. * 获取AccessToken
  3. * @return
  4. */
  5. public static String obtainAccessToken(){
  6. String G_APPID = “公众号的APPID”;
  7. String G_SECRET = “公众号的SECRET”;
  8. String tokenData = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid="+G_APPID+"&secret="+G_SECRET;
  9. // 返回的用户信息json字符串
  10. JSONObject jsonObject = httpRequestUtil(tokenData);
  11. return String.valueOf(jsonObject.get("access_token"));
  12. }
  13. /**
  14. * 获取订阅用户的openid和unionid
  15. * @param accessToken
  16. * @param openId
  17. * @return
  18. */
  19. public static OpenUnionIdRelationDO obtainUserDetail(String accessToken,String openId){
  20. String openInfoUrl = "https://api.weixin.qq.com/cgi-bin/user/info?access_token="+accessToken+"&openid="+openId+"&lang=zh_CN";
  21. JSONObject userDetail = httpRequestUtil(openInfoUrl);
  22. String openid = userDetail.getString("openid");
  23. Integer subscribeTime = userDetail.getInteger("subscribe_time");
  24. String unionid = userDetail.getString("unionid");
  25. OpenUnionIdRelationDO openDO = new OpenUnionIdRelationDO();
  26. openDO.setOpenId(openid);
  27. openDO.setUnionId(unionid);
  28. // 时间类型转换 10位时间戳转 yyyy-MM-dd HH:mm:ss
  29. String st = "";
  30. if (null != subscribeTime){
  31. st = DateUtils.timestampToString(subscribeTime);
  32. }
  33. openDO.setSubscribeTime(st);
  34. openDO.setCreateTime(new Date());
  35. return openDO;
  36. }

给用户推送信息

前面已经维护好了用户的公众号ID和公众号小程序的一致的unionid,小程序就可以通过unionid查询数据库中的openid给公众号用户推送信息了

  1. /**
  2. * 给关注该公众好的用户发送信息
  3. * @throws Exception
  4. */
  5. public static void sendTemplateInfo() throws Exception{
  6. //获取小程序accessToken
  7. String accessToken = obtainAccessToken();
  8. //消息推送接口
  9. String path = "https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=" + accessToken;
  10. //封装参数
  11. JSONObject jsonData = new JSONObject();
  12. jsonData.put("touser", "公众号openid");
  13. jsonData.put("template_id", "公众号消息模板id");
  14. JSONObject miniprogram = new JSONObject();
  15. miniprogram.put("appid","小程序ID");
  16. miniprogram.put("pagepath","小程序调转路径");
  17. jsonData.put("miniprogram",miniprogram);
  18. JSONObject data = new JSONObject();
  19. JSONObject first = new JSONObject();
  20. first.put("value","测试购票支付详情!");
  21. first.put("color","#173177");
  22. JSONObject keyword1 = new JSONObject();
  23. keyword1.put("value","2112323832748239");
  24. keyword1.put("color","#173177");
  25. JSONObject keyword2 = new JSONObject();
  26. keyword2.put("value","2022-12-22 00:00:00");
  27. keyword2.put("color","#173177");
  28. JSONObject keyword3 = new JSONObject();
  29. keyword3.put("value","199.56元");
  30. keyword3.put("color","#173177");
  31. JSONObject keyword4 = new JSONObject();
  32. keyword4.put("value","微信支付");
  33. keyword4.put("color","#173177");
  34. JSONObject remark = new JSONObject();
  35. remark.put("value","温馨提示:请不要爽约哦!");
  36. remark.put("color","#173177");
  37. data.put("first",first);
  38. data.put("keyword1",keyword1);
  39. data.put("keyword2",keyword2);
  40. data.put("keyword3",keyword3);
  41. data.put("keyword4",keyword4);
  42. data.put("remark",remark);
  43. jsonData.put("data",data);
  44. HttpUtil.post(path, jsonData.toJSONString());
  45. }

效果展示:

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/从前慢现在也慢/article/detail/981034?site
推荐阅读
相关标签
  

闽ICP备14008679号