https://work.weixin.qq.com/api/doc/90000/90135/90966
先配置url,token,encodingAESKey
import com.ichangtou.common.util.AesException;
import com.ichangtou.common.util.WXBizMsgCrypt;
import com.ichangtou.service.WXCallBackService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import javax.servlet.ServletException;
import javax.servlet.ServletInputStream;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
@WebServlet(name = "CallbackServlet", urlPatterns = "/callbackServlet") //标记为servlet,以便启动器扫描。
@Slf4j
public class CallbackServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// 微信加密签名
String msg_signature = request.getParameter("msg_signature");
// 时间戳
String timestamp = request.getParameter("timestamp");
// 随机数
String nonce = request.getParameter("nonce");
// 随机字符串
String echostr = request.getParameter("echostr");
log.info("request=" + request.getRequestURL());
log.info("请求的数据为,msg_signature:{},timestamp:{},nonce:{},echostr:{}",msg_signature,timestamp ,nonce,echostr);
PrintWriter out = response.getWriter();
// 通过检验msg_signature对请求进行校验,若校验成功则原样返回echostr,表示接入成功,否则接入失败
String result = null;
try {
WXBizMsgCrypt wxcpt = new WXBizMsgCrypt(token, encodingAESKey, corpid);
result = wxcpt.VerifyURL(msg_signature, timestamp, nonce, echostr);
} catch (AesException e) {
e.printStackTrace();
}
if (result == null) {
result = "ok";
}
log.info("result=:{}",result);
out.print(result);
out.close();
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//1.将请求、响应的编码均设置为UTF-8(防止中文乱码)
log.info("进入post方法" + request.getRequestURL());
request.setCharacterEncoding("UTF-8");
response.setCharacterEncoding("UTF-8");
String respMessage=getDecryptMsg(request);
//进行回调处理
wXCallBackService.dealCallBackEvent(respMessage);
log.info("respMessage=:{}",respMessage);
PrintWriter out = response.getWriter();
out.print(respMessage);
out.close();
}
public String getDecryptMsg(HttpServletRequest request) {
String postData=""; // 密文,对应POST请求的数据
String result=""; // 明文,解密之后的结果
String msg_signature = request.getParameter("msg_signature"); // 微信加密签名
String timestamp = request.getParameter("timestamp"); // 时间戳
String nonce = request.getParameter("nonce"); // 随机数
try {
//1.获取加密的请求消息:使用输入流获得加密请求消息postData
ServletInputStream in = request.getInputStream();
BufferedReader reader =new BufferedReader(new InputStreamReader(in));
String tempStr=""; //作为输出字符串的临时串,用于判断是否读取完毕
while(null!=(tempStr=reader.readLine())){
postData+=tempStr;
}
//2.获取消息明文:对加密的请求消息进行解密获得明文
WXBizMsgCrypt wxcpt = new WXBizMsgCrypt(token, encodingAESKey, corpid);
result = wxcpt.DecryptMsg(msg_signature, timestamp, nonce, postData);
} catch (IOException e) {
e.printStackTrace();
} catch (AesException e) {
e.printStackTrace();
}
return result;
}
}
@Slf4j
@Service
public class WXCallBackServiceImpl implements WXCallBackService {
@Autowired
private WXAddressBookService wXAddressBookService;
@Override
public void dealCallBackEvent(String text) {
JSONObject json= XmlTool.documentToJSONObject(text);
String event=json.getString("Event");
String changeType=json.getString("ChangeType");
AddressBookEventEnum eventEnum=AddressBookEventEnum.getAddressBookEvent(event,changeType);
if(eventEnum!=null){
Class tc=eventEnum.getT();
if(tc.isAssignableFrom(Member.class)){
Member member=JSONObject.parseObject(json.toJSONString(), Member.class);
wXAddressBookService.dealAddressEvent(member);
}
}
}
}
下面是xml转json的工具类
import java.util.List;
import org.dom4j.Attribute;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
public class XmlTool {
/**
* String 转 org.dom4j.Document
* @param xml
* @return
* @throws DocumentException
*/
public static Document strToDocument(String xml){
try {
//加上xml标签是为了获取最外层的标签,如果不需要可以去掉
return DocumentHelper.parseText(xml);
} catch (DocumentException e) {
return null;
}
}
/**
* org.dom4j.Document 转 com.alibaba.fastjson.JSONObject
* @param xml
* @return
* @throws DocumentException
*/
public static JSONObject documentToJSONObject(String xml){
return elementToJSONObject(strToDocument(xml).getRootElement());
}
/**
* org.dom4j.Element 转 com.alibaba.fastjson.JSONObject
* @param node
* @return
*/
public static JSONObject elementToJSONObject(Element node) {
JSONObject result = new JSONObject();
// 当前节点的名称、文本内容和属性
List listAttr = node.attributes();// 当前节点的所有属性的list
for (Attribute attr : listAttr) {// 遍历当前节点的所有属性
result.put(attr.getName(), attr.getValue());
}
// 递归遍历当前节点所有的子节点
List listElement = node.elements();// 所有一级子节点的list
if (!listElement.isEmpty()) {
for (Element e : listElement) {// 遍历所有一级子节点
if (e.attributes().isEmpty() && e.elements().isEmpty()) // 判断一级节点是否有属性和子节点
result.put(e.getName(), e.getTextTrim());// 沒有则将当前节点作为上级节点的属性对待
else {
if (!result.containsKey(e.getName())) // 判断父节点是否存在该一级节点名称的属性
result.put(e.getName(), new JSONArray());// 没有则创建
((JSONArray) result.get(e.getName())).add(elementToJSONObject(e));// 将该一级节点放入该节点名称的属性对应的值中
}
}
}
return result;
}
}
@Data
public class Member {
private String toUserName;
private String fromUserName;
private String createTime;
private String msgType;
private String event;
private String changeType;
private String userID;
private String newUserID;
private String name;
private String department;
private String isLeaderInDept;
private String position;
private String mobile;
private String gender;
private String email;
private String status;
private String avatar;
private String alias;
private String telephone;
private String address;
private List extAttr;
}
@Data
public class Items {
List- item;
}
@Data
public class Item {
private String type;
private List
text;
private String name;
private List web;
}
@Data
public class TextValue {
private String Value;
}
@Data
public class WebValue {
private String Title;
private String Url;
}
https://work.weixin.qq.com/api/doc/90000/90138/90307
注意:企业微信提供的WXBizMsgCrypt类中,
Base64 要使用org.apache.commons.codec.binary.Base64
commons-codec
commons-codec
1.9
dom4j
dom4j
1.6.1