大家好,我是雄雄。交流技术可以进入到我的社区【雄雄的小课堂】
前言
看本篇文章之前,可以先看看前面两篇:
java实现微信服务(公众)号用户关注时,获取openid,安全模式下的加密解密实现
微信公众平台安全模式下传输xml数据包时解密方式
前面这两篇文章主要实现的,当用户关注了服务号或者订阅号之后,通过触发事件,然后会给开发者配置的接口中,传输加密的xml
格式数据,后台通过解密xml
格式数据,拿到自己想要的东西。
解密xml数据,提取内容
在前两篇文章中也提到过,我们开启服务器配置时,需要在后台写两个同名接口,只是一个是get
方式请求,另一个是post
方式请求,具体的在这不在赘述。
现在我们来看看代码的实现。
/*** 接收用户事件* @param requestBody* @return*/@RequestMapping(value = "/validationWeCat",method = RequestMethod.POST)public String validationWeCat(@RequestBody String requestBody){if(Strings.isNotBlank(requestBody)){log.info("进入了validationWeCat的post方法,由用户触发的,值是:"+requestBody);//解析xml数据JSONObject jsonObject = WeChatUtils.toParseTheXmlData(requestBody);int code = jsonObject.getInteger("code");if(code==200){//获取关注的密文String miwen = jsonObject.getString("encrypt");//解密String jiemiText = WeChatUtils.decodeNewUsers(miwen);//解密完之后还是个xml数据,继续解析JSONObject jiemiObject = WeChatUtils.toParseTheXmlData(jiemiText);if(jiemiObject.getInteger("code")==200){//获取消息类型String msgType = jiemiObject.getString("msgType");switch (msgType){//文本case "text" :break;//事件case "event" ://触发事件执行的方法eventCase(jiemiObject);break;// 语音case "voice" :break;// 视频case "video" :break;// 音乐case "music" :break;// 图文case "news" :break;// 图片case "image" :break;// 小视频case "shortvideo" :break;// 地理位置case "location" :break;// 链接case "link" :break;default:break;}}else{log.error("解析xml报错");}}else{log.error("解析xml报错");}}return requestBody;}
/*** 触发的是事件* @param jsonObject*/public void eventCase(JSONObject jsonObject){//获取事件类型String event = jsonObject.getString("event");switch (event){//关注case "subscribe" ://获取微信号String weChatNum = jsonObject.getString("toUserName");//获取openidString openid = jsonObject.getString("fromUserName");Member member = new Member();member.setWechat(weChatNum);member.setOpenIdGzh(openid);//默认名字是:微信用户member.setName("公众号用户");boolean flag = saveMember(member);if(!flag){log.error("添加会员报错");}break;//取消关注case "unsubscribe" :break;// 用户已关注时的事件推送case "SCAN" :break;// 用户已关注时的事件推送case "LOCATION" :break;// 点击菜单拉取消息时的事件推送case "CLICK" :break;// 点击菜单跳转链接时的事件推送case "VIEW" :break;default:break;}}
/*** 添加会员的业务逻辑*/public boolean saveMember(LtMember ltMember){return memberService.save(ltMember);return false;}
上面就是添加会员的基本操作,涉及到了一个工具类,我这边也放出来吧,此工具类主要是用来解析xml
数据的,代码如下:
package org.jeecg.modules.utils;import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.jeecg.modules.config.WeChatContant;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.StringReader;
import java.util.HashMap;
import java.util.LinkedHashMap;/*** @author: muxiongxiong* @date: 2022年08月17日 下午 10:06* 公众号:雄雄的小课堂* 博客:https://blog.csdn.net/qq_34137397* 个人站:http://www.穆雄雄.com* 个人站:http://www.muxiongxiong.cn* @Description: 微信工具类,主要是用来加密和解密信息*/
@Slf4j
public class WeChatUtils {/*** 解析xml数据的工具类* @param xmlTest* @return*/public static JSONObject toParseTheXmlData(String xmlTest){//new LinkedHashMap<>() 表示让集合添加的时候有顺序JSONObject jsonObject = new JSONObject(new LinkedHashMap<>());try {DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();//这里也不知道是啥意思dbf.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);dbf.setFeature("http://xml.org/sax/features/external-general-entities", false);dbf.setFeature("http://xml.org/sax/features/external-parameter-entities", false);dbf.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);dbf.setXIncludeAware(false);dbf.setExpandEntityReferences(false);DocumentBuilder db = dbf.newDocumentBuilder();StringReader sr = new StringReader(xmlTest);InputSource is = new InputSource(sr);Document document = db.parse(is);//得到根节点Element root = document.getDocumentElement();//用户关注触发事件之后微信传过来加密的信息NodeList encryptNode = root.getElementsByTagName("Encrypt");//开发者微信号NodeList toUserNameNode = root.getElementsByTagName("ToUserName");//发送方帐号(一个OpenID)NodeList fromUserNameNode = root.getElementsByTagName("FromUserName");//消息类型,eventNodeList msgTypeNode = root.getElementsByTagName("MsgType");//事件类型,subscribe(订阅)、unsubscribe(取消订阅)NodeList eventNode = root.getElementsByTagName("Event");//消息创建时间 (整型)NodeList createTimeNode = root.getElementsByTagName("CreateTime");//事件 KEY 值,qrscene_为前缀,后面为二维码的参数值NodeList eventKeyNode = root.getElementsByTagName("EventKey");//二维码的ticket,可用来换取二维码图片NodeList ticketNode = root.getElementsByTagName("Ticket");//地理位置纬度NodeList latitudeNode = root.getElementsByTagName("Latitude");//地理位置经度NodeList longitudeNode = root.getElementsByTagName("Longitude");//地理位置精度NodeList precisionNode = root.getElementsByTagName("Precision");//获取该节点下的值,将值添加到jsonobject中if(encryptNode.getLength()>0){String encrypt = encryptNode.item(0).getTextContent();jsonObject.put("encrypt",encrypt);}if (toUserNameNode.getLength()>0) {String toUserName = toUserNameNode.item(0).getTextContent();jsonObject.put("toUserName",toUserName);}if (fromUserNameNode.getLength()>0) {String fromUserName = fromUserNameNode.item(0).getTextContent();jsonObject.put("fromUserName",fromUserName);}if (msgTypeNode.getLength()>0) {String msgType = msgTypeNode.item(0).getTextContent();jsonObject.put("msgType",msgType);}if (eventNode.getLength()>0) {String event = eventNode.item(0).getTextContent();jsonObject.put("event",event);}if (createTimeNode.getLength()>0) {String createTime = createTimeNode.item(0).getTextContent();jsonObject.put("createTime",createTime);}if (eventKeyNode.getLength()>0) {String eventKey = eventKeyNode.item(0).getTextContent();jsonObject.put("eventKey",eventKey);}if (ticketNode.getLength()>0) {String ticket = ticketNode.item(0).getTextContent();jsonObject.put("ticket",ticket);}if (latitudeNode.getLength()>0) {String latitude = latitudeNode.item(0).getTextContent();jsonObject.put("latitude",latitude);}if (longitudeNode.getLength()>0) {String longitude = longitudeNode.item(0).getTextContent();jsonObject.put("longitude",longitude);}if (precisionNode.getLength()>0) {String precision = precisionNode.item(0).getTextContent();jsonObject.put("precision",precision);}jsonObject.put("code",200);jsonObject.put("msg","操作成功");}catch (Exception exception){jsonObject.put("code",500);jsonObject.put("msg","出异常了");jsonObject.put("error",exception.getMessage());}return jsonObject;}
}}
至此,就可以实现关注后自动将会员注册到我们实际库中。后面的业务根据这个架构往下写就行,就比较简单了。