java对接微信公众号

前言

一、填写服务器配置

参数解析

  1. Token:可由开发者可以任意填写,用作生成签名(该Token会和接口URL中包含的Token进行比对,从而验证安全性)
  2. EncodingAESKey:由开发者手动填写或随机生成,将用作消息体加解密密钥,推荐使用兼容模式

二、开发验证服务器有效性接口

GET请求进行验证token有效性

Utils

三、开发处理微信事件推送接口

POST请求进行事件处理(业务处理)

service

@Override
    public void pushEvents(HttpServletRequest request) {
          
   
        String xmlStr = "";
        try {
          
   
            xmlStr = XmlUtil.inputStream2StringNew(request.getInputStream());
            Map<String, String> requestMap = XmlUtil.parseXml(xmlStr);
            String json = JSONObject.toJSONString(requestMap);
            log.info("WeChatEventsServiceImpl pushEvents request json: " + json);
            if (!StringUtils.isEmpty(requestMap.get("event"))) {
          
   
                WeChatAttentionDto weChatAttentionDto = JSON.parseObject(JSON.toJSONString(requestMap), WeChatAttentionDto.class);
                //处理推送消息
                this.weChatEvents(weChatAttentionDto);
            } else if (!StringUtils.isEmpty(requestMap.get("msgType"))) {
          
   
                //暂不进行处理
            }
        } catch (Exception e) {
          
   
            log.error("WeChatEventsServiceImpl pushEvents xml解析失败:" + xmlStr);
            e.printStackTrace();
        }
    }

XmlUtil

package com.riskeys.tobtoc.util;

import org.apache.commons.lang3.StringUtils;
import org.dom4j.io.SAXReader;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import javax.servlet.http.HttpServletRequest;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.lang.reflect.Method;
import java.security.MessageDigest;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class XmlUtil {
          
   

    // 将输入流使用指定编码转化为字符串
    public static String inputStream2StringNew(InputStream inputStream) throws Exception {
          
   
        // 建立输入流读取类
        InputStreamReader reader = new InputStreamReader(inputStream);
        // 设定每次读取字符个数
        char[] data = new char[512];
        int dataSize = 0;
        // 循环读取
        StringBuilder stringBuilder = new StringBuilder();
        while ((dataSize = reader.read(data)) != -1) {
          
   
            stringBuilder.append(data, 0, dataSize);
        }
        return stringBuilder.toString();
    }

    // 将 xml 文件解析为指定类型的实体对象。此方法只能解析简单的只有一层的xml
    private static DocumentBuilderFactory documentBuilderFactory = null;

    //屏蔽某些编译时的警告信息(在强制类型转换的时候编译器会给出警告)
    public static Map<String, String> parseXml(String Str) throws Exception {
          
   
        // 将解析结果存储在HashMap中
        Map<String, String> map = new HashMap<String, String>();

        // 从request中取得输入流
        // 读取输入流
        SAXReader reader = new SAXReader();
        org.dom4j.Document document = reader.read(new ByteArrayInputStream(Str.getBytes()));
        // 得到xml根元素
        org.dom4j.Element root = document.getRootElement();
        // 得到根元素的所有子节点
        List<org.dom4j.Element> elementList = root.elements();

        // 遍历所有子节点
        for (org.dom4j.Element e : elementList)
            map.put(getName(e.getName()), e.getText());
        return map;
    }

    private static String getName(String name) {
          
   
        if (StringUtils.isBlank(name)) {
          
   
            return null;
        }
        String frist = String.valueOf(name.charAt(0)).toLowerCase();
        return frist + name.substring(1, name.length());
    }
}

处理消息推送

//处理推送消息
                this.weChatEvents(weChatAttentionDto);

总结

  1. 需区分GET和POST请求各自的作用
  2. 测试环境进行调试的时候,http请求验证通过,但是在消息推送时有可能转成https请求,需要进行相应处理,才能正确接收事件推送。
经验分享 程序员 微信小程序 职场和发展