200字范文,内容丰富有趣,生活中的好帮手!
200字范文 > java实现关注微信公众号推送模板消息

java实现关注微信公众号推送模板消息

时间:2023-09-16 01:28:34

相关推荐

java实现关注微信公众号推送模板消息

java实现关注微信公众号推送模板消息

消息模板配置直接上代码

消息模板配置

百度搜索有很多教程,线面附地址。

教程:消息模板配置教程

值得注意的是,公众号配置菜单之后再配置消息模板会有冲突,导致菜单无法显示。

直接上代码

我使用的是阿里的maven仓库。

<mirror><id>alimaven</id><name>aliyun maven</name><mirrorOf>central</mirrorOf><url>/nexus/content/groups/public/</url></mirror>

jar包依赖

<dependency><groupId>dom4j</groupId><artifactId>dom4j</artifactId><version>1.6.1</version></dependency><dependency><groupId>com.github.liyiorg</groupId><artifactId>weixin-popular</artifactId><version>2.8.24</version></dependency>

controller

package com.newtouch.springcloud.controller;import com.newtouch.springcloud.service.WeChatCallBackService;import com.wechat.wechatUtil.SignUtil;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Controller;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RequestMethod;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import java.io.IOException;import java.io.PrintWriter;import java.util.UUID;@Controller@RequestMapping("/weChatCallBack")public class WeChatCallBackController {Logger log = LoggerFactory.getLogger(this.getClass());@Autowiredprivate WeChatCallBackService weChatCallBackService;private static final String token = "d29499fb870e481a85b8818edab15852";/*** 微信消息推送的验证。** @param request* @param response*/@RequestMapping(value = "/sendMsg", method = RequestMethod.GET, produces = "text/html;charset=UTF-8")public void sendMsgget(HttpServletRequest request, HttpServletResponse response) {// 微信加密签名String signature = request.getParameter("signature");log.info("微信接口回调参数:signature========="+ signature);// 时间戳String timestamp = request.getParameter("timestamp");log.info("微信接口回调参数:timestamp========="+ timestamp);// 随机数String nonce = request.getParameter("nonce");log.info("微信接口回调参数:nonce========="+ nonce);// 随机字符串String echostr = request.getParameter("echostr");log.info("微信接口回调参数:echostr========="+ echostr);PrintWriter out = null;try {out = response.getWriter();} catch (IOException e) {e.printStackTrace();}// 通过检验signature对请求进行校验,若校验成功则原样返回echostr,表示接入成功,否则接入失败if (SignUtil.checkSignature(token, signature, timestamp, nonce)) {out.print(echostr);}out.close();out = null;}/*** 处理业务逻辑* @param request*/@RequestMapping(value = "/sendMsg", method = RequestMethod.POST, produces = "text/html;charset=UTF-8")public void sendMsgPost(HttpServletRequest request, HttpServletResponse response) {// 调用核心业务类接收消息、处理消息try {String returnStr = weChatCallBackService.processRequest(request, response);} catch (Exception e) {e.printStackTrace();}}}

Service层

package com.newtouch.springcloud.service.impl;import com.alibaba.fastjson.JSONObject;import com.newtouch.springcloud.constant.ProjectConst;import com.newtouch.springcloud.model.vo.BaseMessage;import com.newtouch.springcloud.model.vo.TextMessage;import com.newtouch.springcloud.service.RedisService;import com.newtouch.springcloud.service.WeChatCallBackService;import com.newtouch.springcloud.service.WeChatUserAuthService;import com.newtouch.springcloud.service.WechatSendModelMessageService;import com.qq.weixin.mp.aes.WXBizMsgCrypt;import com.wechat.wechatUtil.MessageUtil;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Service;import org.w3c.dom.Document;import org.w3c.dom.Element;import org.w3c.dom.NodeList;import org.xml.sax.InputSource;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;import javax.xml.parsers.DocumentBuilder;import javax.xml.parsers.DocumentBuilderFactory;import java.io.StringReader;import java.text.SimpleDateFormat;import java.util.Date;import java.util.Map;@Servicepublic class WeChatCallBackServiceImpl implements WeChatCallBackService {Logger log = LoggerFactory.getLogger(this.getClass());public static String ENCODINGAES_KEY = "wx:encodingAesKey:encodingAesKey";//解密字符串public static String SENDINTERFACE_TOKEN = "wx:sendInterfaceToken:sendInterfaceToken";//微信推送消息tokenprivate static String timestamp = "1585578656";private static String nonce = "734446698";private SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");@Autowiredprivate RedisService redisService ;@Autowiredprivate WeChatUserAuthService WeChatUserAuthService;@Autowiredprivate WechatSendModelMessageService wechatSendModelMessageService;@Overridepublic String processRequest(HttpServletRequest request, HttpServletResponse response) {try {String respMessage = processRequest(request);log.info("返给微信的参数:======" + respMessage);return respMessage;} catch (Exception e) {e.printStackTrace();}return "";}/*** 处理数据* @param request* @return* @throws Exception*/public String processRequest(HttpServletRequest request) throws Exception {String signatureTemp = request.getParameter("signature");log.info("微信接口回调参数:signature========="+ signatureTemp);// 时间戳timestamp = request.getParameter("timestamp");log.info("微信接口回调参数:timestamp========="+ timestamp);// 随机数nonce = request.getParameter("nonce");log.info("微信接口回调参数:nonce========="+ nonce);// 随机字符串String echostrTemp = request.getParameter("echostr");log.info("微信接口回调参数:echostr========="+ echostrTemp);String msgSignatureStr = request.getParameter("msg_signature");log.info("微信接口回调参数:msgSignature========="+ msgSignatureStr);String respMessage = null;WXBizMsgCrypt pc = new WXBizMsgCrypt(redisService.get(ProjectConst.SENDINTERFACE_TOKEN).toString(), redisService.get(ProjectConst.ENCODINGAES_KEY).toString(), redisService.get(ProjectConst.APPID_KEY).toString());try {// xml请求解析Map<String, String> requestMap = MessageUtil.parseXml(request);log.info("微信接口回调参数:"+ JSONObject.toJSONString(requestMap));String mapToStr = "<xml><Encrypt><![CDATA["+requestMap.get("Encrypt")+"]]></Encrypt><ToUserName><![CDATA["+requestMap.get("ToUserName")+"]]></ToUserName><MsgSignature><![CDATA["+msgSignatureStr+"]]></MsgSignature></xml>";DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();DocumentBuilder db = dbf.newDocumentBuilder();StringReader sr = new StringReader(mapToStr);InputSource is = new InputSource(sr);Document document = db.parse(is);Element root = document.getDocumentElement();NodeList nodelist1 = root.getElementsByTagName("Encrypt");NodeList nodelist2 = root.getElementsByTagName("MsgSignature");String encrypt = nodelist1.item(0).getTextContent();String msgSignature = nodelist2.item(0).getTextContent();String format = "<xml><ToUserName><![CDATA[toUser]]></ToUserName><Encrypt><![CDATA[%1$s]]></Encrypt></xml>";String fromXML = String.format(format, encrypt);// 公众平台发送消息给第三方,第三方处理// 第三方收到公众号平台发送的消息String result2 = pc.decryptMsg(msgSignature, timestamp, nonce, fromXML);log.info("解密后明文: " + result2);//转换成map放入对象中Map<String, String> xmlStrToMap = MessageUtil.convertXmlStrToObject(result2);log.info("转换成msp后的参数: " + JSONObject.toJSONString(xmlStrToMap));BaseMessage baseMessage = JSONObject.parseObject(JSONObject.toJSONString(xmlStrToMap), BaseMessage.class);log.info("map转成BaseMessage后的参数: " + JSONObject.toJSONString(baseMessage));if(MessageUtil.REQ_MESSAGE_TYPE_SCAN.equals(baseMessage.getEvent())){//已关注/**已关注之后* 先查询数据库中的数据并组装返回信息给微信*///chechMessage();log.info("已关注,无需更新数据库==================== ");}else if (MessageUtil.EVENT_TYPE_SUBSCRIBE.equals(baseMessage.getEvent())){//关注/*** 先查询数据库中的数据是否存在如果有则更新openid*/log.info("未关注,需更新数据库====================== ");String telePhoneNo = xmlStrToMap.get("EventKey");if(null != telePhoneNo && !"".equals(telePhoneNo)){telePhoneNo = telePhoneNo.substring(telePhoneNo.indexOf("_")+1);}// 更新数据log.info("未关注,数据更新完成====================== ");String content = "恭喜您,您已完成注册!";log.info("未关注,开始推送模板消息==================");wechatSendModelMessageService.sendWarningByWechat(baseMessage.getFromUserName(),content,telePhoneNo,sdf.format(new Date()));log.info("未关注,推送模板消息成功===================");}/*** 处理完成后需组装信息末班,加密后返回给微信*///respMessage = pc.encryptMsg(resultXml, timestamp, nonce);//respMessage = resultXml;//log.info("加密后: " + respMessage);} catch (Exception e) {e.printStackTrace();}return respMessage;}}

发送模板消息的Service

package com.newtouch.springcloud.service.impl;import com.newtouch.springcloud.model.vo.Template;import com.newtouch.springcloud.model.vo.TemplateParam;import com.newtouch.springcloud.service.WechatSendModelMessageService;import com.wechat.wechatUtil.ApacheHttpClientUtils;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.beans.factory.annotation.Autowired;import com.newtouch.springcloud.service.RedisService;import org.springframework.stereotype.Service;import java.util.ArrayList;import java.util.List;@Servicepublic class WechatSendModelMessageServiceImpl implements WechatSendModelMessageService {Logger log = LoggerFactory.getLogger(this.getClass());@Autowiredprivate RedisService redisServer;/**** @param openIds openid组 逗号分割* @param content 标题* @param telePhoneNo 手机号* @param sendDateTime 创建时间*/@Overridepublic void sendWarningByWechat(String openIds, String content, String telePhoneNo, String sendDateTime) {try {String templateMsgUrl = redisServer.get("wx:templateMsgUrl:templateMsgUrl").toString();templateMsgUrl = templateMsgUrl.replace("ACCESS_TOKEN", redisServer.get("wx:accessToken:").toString());log.info("通过微信推送模板消息地址:" + templateMsgUrl);//封装请求体Template template = new Template();template.setTemplateId(redisServer.get("wx:modelId:modelId").toString());List<TemplateParam> templateParams = new ArrayList<>();TemplateParam first = new TemplateParam("first", content + "\\n", "#DB");TemplateParam keyword1 = new TemplateParam("keyword1", telePhoneNo + "", "#DB");TemplateParam keyword2 = new TemplateParam("keyword2", "普通用户", "#DB");TemplateParam keyword3 = new TemplateParam("keyword3", sendDateTime + "", "#DB");TemplateParam remark = new TemplateParam("remark", "若有疑问请联系在线客服或拨打" + redisServer.get("wx:managementTel:managementTe").toString(), "#DB");templateParams.add(first);templateParams.add(keyword1);templateParams.add(keyword2);templateParams.add(keyword3);templateParams.add(remark);template.setTemplateParamList(templateParams);String[] openIdArr = openIds.split(",");if (openIdArr.length > 0) {for (String openID : openIdArr) {template.setToUser(openID);String paramStr = template.toJSON();log.info("通过微信推送模板消息入参:" + paramStr);ApacheHttpClientUtils.doTemplateMsgPost(templateMsgUrl, paramStr);log.info("通过微信推送模板消息完成===============");}}} catch (Exception e) {log.error(e.getMessage());e.printStackTrace();}}}

BaseMessage

package com.newtouch.springcloud.model.vo;/*** 消息基类(公众帐号 -> 用户)*/public class BaseMessage {/*** 接收方帐号(收到的OpenID)*/private String ToUserName;/*** 开发者微信号*/private String FromUserName;/*** 消息创建时间 (整型)*/private long CreateTime;/*** 消息类型*/private String MsgType;/*** 位0x0001被标志时,星标刚收到的消息*/private Integer FuncFlag;private String EventKey;private String Event;private String Ticket;public String getEvent() {return Event;}public void setEvent(String event) {Event = event;}public String getTicket() {return Ticket;}public void setTicket(String ticket) {Ticket = ticket;}public String getEventKey() {return EventKey;}public void setEventKey(String eventKey) {EventKey = eventKey;}public String getToUserName() {return ToUserName;}public void setToUserName(String toUserName) {ToUserName = toUserName;}public String getFromUserName() {return FromUserName;}public void setFromUserName(String fromUserName) {FromUserName = fromUserName;}public long getCreateTime() {return CreateTime;}public void setCreateTime(long createTime) {CreateTime = createTime;}public String getMsgType() {return MsgType;}public void setMsgType(String msgType) {MsgType = msgType;}public Integer getFuncFlag() {return FuncFlag;}public void setFuncFlag(Integer funcFlag) {FuncFlag = funcFlag;}}

SignUtil工具类

package com.wechat.wechatUtil;import java.security.MessageDigest;import java.security.NoSuchAlgorithmException;import java.util.Arrays;public class SignUtil {/*** 验证签名* * @param signature* @param timestamp* @param nonce* @return*/public static boolean checkSignature(String token, String signature, String timestamp, String nonce) {String[] arr = new String[] {token, timestamp, nonce };// 将token、timestamp、nonce三个参数进行字典序排序Arrays.sort(arr);StringBuilder content = new StringBuilder();for (int i = 0; i < arr.length; i++) {content.append(arr[i]);}MessageDigest md = null;String tmpStr = null;try {md = MessageDigest.getInstance("SHA-1");// 将三个参数字符串拼接成一个字符串进行sha1加密byte[] digest = md.digest(content.toString().getBytes());tmpStr = byteToStr(digest);} catch (NoSuchAlgorithmException e) {e.printStackTrace();}content = null;// 将sha1加密后的字符串可与signature对比,标识该请求来源于微信return tmpStr != null ? tmpStr.equals(signature.toUpperCase()) : false;}/*** 将字节数组转换为十六进制字符串* * @param byteArray* @return*/static String byteToStr(byte[] byteArray) {String strDigest = "";for (int i = 0; i < byteArray.length; i++) {strDigest += byteToHexStr(byteArray[i]);}return strDigest;}/*** 将字节转换为十六进制字符串* * @param mByte* @return*/private static String byteToHexStr(byte mByte) {char[] Digit = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };char[] tempArr = new char[2];tempArr[0] = Digit[(mByte >>> 4) & 0X0F];tempArr[1] = Digit[mByte & 0X0F];String s = new String(tempArr);return s;}}

MessageUtil

package com.wechat.wechatUtil;import com.newtouch.springcloud.model.vo.BaseMessage;import com.newtouch.springcloud.model.vo.NewsMessage;import com.newtouch.springcloud.model.vo.TextMessage;import com.thoughtworks.xstream.XStream;import com.thoughtworks.xstream.core.util.QuickWriter;import com.thoughtworks.xstream.io.HierarchicalStreamWriter;import com.thoughtworks.xstream.io.xml.PrettyPrintWriter;import com.thoughtworks.xstream.io.xml.XppDriver;import org.dom4j.Document;import org.dom4j.DocumentException;import org.dom4j.Element;import org.dom4j.io.SAXReader;import weixin.popular.bean.message.Article;import weixin.popular.bean.message.message.MusicMessage;import javax.servlet.http.HttpServletRequest;import java.io.ByteArrayInputStream;import java.io.IOException;import java.io.InputStream;import java.io.Writer;import java.util.HashMap;import java.util.List;import java.util.Map;public class MessageUtil {/*** 返回消息类型:文本*/public static final String RESP_MESSAGE_TYPE_TEXT = "text";/*** 返回消息类型:音乐*/public static final String RESP_MESSAGE_TYPE_MUSIC = "music";/*** 返回消息类型:图文*/public static final String RESP_MESSAGE_TYPE_NEWS = "news";/*** 请求消息类型:文本*/public static final String REQ_MESSAGE_TYPE_TEXT = "text";/*** 请求消息类型:图片*/public static final String REQ_MESSAGE_TYPE_IMAGE = "image";/*** 请求消息类型:链接*/public static final String REQ_MESSAGE_TYPE_LINK = "link";/*** 请求消息类型:地理位置*/public static final String REQ_MESSAGE_TYPE_LOCATION = "location";/*** 请求消息类型:音频*/public static final String REQ_MESSAGE_TYPE_VOICE = "voice";/*** 请求消息类型:推送*/public static final String REQ_MESSAGE_TYPE_EVENT = "event";/*** 已关注关注事件*/public static final String REQ_MESSAGE_TYPE_SCAN = "SCAN";/*** 事件类型:subscribe(订阅) 未关注关注事件*/public static final String EVENT_TYPE_SUBSCRIBE = "subscribe";/*** 事件类型:unsubscribe(取消订阅)*/public static final String EVENT_TYPE_UNSUBSCRIBE = "unsubscribe";/*** 事件类型:CLICK(自定义菜单点击事件)*/public static final String EVENT_TYPE_CLICK = "CLICK";/*** 解析微信发来的请求(XML)* * @param request* @return* @throws Exception*/public static Map<String, String> parseXml(HttpServletRequest request) throws Exception {// 将解析结果存储在HashMap中Map<String, String> map = new HashMap<String, String>();// 从request中取得输入流InputStream inputStream = request.getInputStream();// 读取输入流SAXReader reader = new SAXReader();Document document = reader.read(inputStream);// 得到xml根元素Element root = document.getRootElement();// 得到根元素的所有子节点List<Element> elementList = root.elements();// 遍历所有子节点for (Element e : elementList) {map.put(e.getName(), e.getText());}// 释放资源inputStream.close();inputStream = null;return map;}/*** 文本消息对象转换成xml* * @param textMessage 文本消息对象* @return xml*/public static String textMessageToXml(TextMessage textMessage) {xstream.alias("xml", textMessage.getClass());return xstream.toXML(textMessage);}/*** 文本消息对象转换成xml** @param baseMessage 文本消息对象* @return xml*/public static String baseMessageToXml(BaseMessage baseMessage) {xstream.alias("xml", baseMessage.getClass());return xstream.toXML(baseMessage);}/*** 音乐消息对象转换成xml* * @param musicMessage 音乐消息对象* @return xml*/public static String musicMessageToXml(MusicMessage musicMessage) {xstream.alias("xml", musicMessage.getClass());return xstream.toXML(musicMessage);}/*** 图文消息对象转换成xml* * @param newsMessage 图文消息对象* @return xml*/public static String newsMessageToXml(NewsMessage newsMessage) {xstream.alias("xml", newsMessage.getClass());xstream.alias("item", new Article().getClass());return xstream.toXML(newsMessage);}/*** 解密后的报文转成对象* @param xmlStr* @return* @throws DocumentException* @throws IOException*/public static Map<String, String> convertXmlStrToObject(String xmlStr) throws DocumentException, IOException {// 将解析结果存储在HashMap中Map<String, String> map = new HashMap<String, String>();// 从request中取得输入流InputStream inputStream = new ByteArrayInputStream(xmlStr.getBytes());// 读取输入流SAXReader reader = new SAXReader();Document document = reader.read(inputStream);// 得到xml根元素Element root = document.getRootElement();// 得到根元素的所有子节点List<Element> elementList = root.elements();// 遍历所有子节点for (Element e : elementList) {map.put(e.getName(), e.getText());}// 释放资源inputStream.close();inputStream = null;return map;}/*** 扩展xstream,使其支持CDATA块* * @date -05-19*/private static XStream xstream = new XStream(new XppDriver() {public HierarchicalStreamWriter createWriter(Writer out) {return new PrettyPrintWriter(out) {// 对所有xml节点的转换都增加CDATA标记boolean cdata = true;@SuppressWarnings("unchecked")public void startNode(String name, Class clazz) {super.startNode(name, clazz);}protected void writeText(QuickWriter writer, String text) {if (cdata) {writer.write("<![CDATA[");writer.write(text);writer.write("]]>");} else {writer.write(text);}}};}});}

为什么会有两个一样的接口呢?

请注意看代码,一个是get类型一个是post类型。第一次配置服务器试微信平台会发送get请求。

配置好服务器,关注公众号进行消息推送会发送post类型的请求。

url:服务器地址也就是调用你的get接口的接口地址

令牌:自己生成一个uuid就可以

EncodingAESKey:配置服务器手动点击随机生成按钮

注:令牌和EncodingAESKey保存好后面解密是会用到

第一次发博客,找了几位大神的帖子,结合自己的开发经历。有不对的地方请各位大佬指正。

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。