java对接微信公众号
前言
一、填写服务器配置
参数解析
- Token:可由开发者可以任意填写,用作生成签名(该Token会和接口URL中包含的Token进行比对,从而验证安全性)
- 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);
总结
- 需区分GET和POST请求各自的作用
- 测试环境进行调试的时候,http请求验证通过,但是在消息推送时有可能转成https请求,需要进行相应处理,才能正确接收事件推送。
