企业微信通讯录回调模板-XML转JSON-让回调不再难!

本文涉及的产品
密钥管理服务KMS,1000个密钥,100个凭据,1个月
简介: 企业微信通讯录回调模板-XML转JSON-让回调不再难!


我们在开发企业内部应用时,需要实现内部应用和企业微信的双向同步,即互联互通。

举个例子

同步一:企业内部OA系统在修改内部通讯录时,可以同步企业微信(直接调API接口即可)

同步二:在企业微信后台修改通讯录时,反馈给内部OA系统(本文讲解)


总的来说,实现通讯录回调的流程分为四步:

第一步:管理员在企业微信在后台修改通讯录信息(除了API接口修改之外的都算)

第二步:企业微信修改通讯录后,以XML的方式,向企业内部系统发送修改详情

第三步:企业内部系统收到XML信息后,解密信息

第四步:对于解密后的信息,修改企业内部系统的通讯录

具体实现

 

一、导包

解密工具下载地址

下载企业微信提供的解密工具,放到自己的项目内。

注意com包不能改名字

如果1.9版本的包无法通过编译,可以使用1.4的包

1. <dependency>
2. <groupId>commons-codec</groupId>
3. <artifactId>commons-codec</artifactId>
4. <version>1.4</version>
5. </dependency>

 

二、验证URL

在企业微信管理后台,配置URL

 

test方法为验证URL的模板,拿来即用

ParameterSettings是我放固定字段的类,相应参数替换即可

1. import com.qq.weixin.mp.aes.AesException;
2. import com.qq.weixin.mp.aes.WXBizMsgCrypt;
3. 
4. import javax.servlet.http.HttpServletRequest;
5. import javax.servlet.http.HttpServletResponse;
6. import java.io.PrintWriter;
7. 
8. /**
9.      * 验证URL
10.      * @param request
11.      * @param response
12.      * @throws Exception
13.      */
14. public void test(HttpServletRequest request, HttpServletResponse response) throws Exception {
15. // 微信加密签名
16. String msg_signature = request.getParameter("msg_signature");
17. // 时间戳
18. String timestamp = request.getParameter("timestamp");
19. // 随机数
20. String nonce = request.getParameter("nonce");
21. // 随机字符串
22. String echostr = request.getParameter("echostr");
23. 
24.         System.out.println("request=" + request.getRequestURL());
25. 
26. PrintWriter out = response.getWriter();
27. // 通过检验msg_signature对请求进行校验,若校验成功则原样返回echostr,表示接入成功,否则接入失败
28. String result = null;
29. try {
30. WXBizMsgCrypt wxcpt = new WXBizMsgCrypt(ParameterSettings.YHHD_TOKEN, ParameterSettings.YHHD_EAK, ParameterSettings.AS_CORPID);
31.             result = wxcpt.VerifyURL(msg_signature, timestamp, nonce, echostr);
32.         } catch (AesException e) {
33.             e.printStackTrace();
34.         }
35. if (result == null) {
36.             result = ParameterSettings.YHHD_TOKEN;
37.         }
38.         out.print(result);
39.         out.close();
40.         out = null;
41.     }

原文CSDN链接:https://zwz99.blog.csdn.net/article/details/113818974


三、解密

验证URL完成后,将该URL的接口方法替代成下方callBack方法的代码

当企业微信发送回调通知时,该方法会实现接收

该模板会将XML格式的数据转换为标准JSON,方便后续处理

JSON用了阿里的fastjson,maven依赖如下:

1. <dependency>
2. <groupId>com.alibaba</groupId>
3. <artifactId>fastjson</artifactId>
4. <version>1.2.9</version>
5. </dependency>
1. import com.alibaba.fastjson.JSONObject;
2. import com.qq.weixin.mp.aes.AesException;
3. import com.qq.weixin.mp.aes.WXBizMsgCrypt;
4. import org.springframework.web.bind.annotation.RequestMapping;
5. import org.springframework.web.bind.annotation.RequestMethod;
6. 
7. import javax.servlet.ServletInputStream;
8. import javax.servlet.http.HttpServletRequest;
9. import javax.servlet.http.HttpServletResponse;
10. import java.io.BufferedReader;
11. import java.io.IOException;
12. import java.io.InputStreamReader;
13. import java.io.PrintWriter;
14. 
15. 
16. /**
17.      * 企业微信发送XML到这个方法
18.      * @param request
19.      * @param response
20.      * @throws Exception
21.      */
22. @RequestMapping(value = "/callBack", method = RequestMethod.POST)
23. public void callBack(HttpServletRequest request, HttpServletResponse response) throws Exception {
24.         request.setCharacterEncoding("UTF-8");
25.         response.setCharacterEncoding("UTF-8");
26. String respMessage = "";
27.         respMessage=getDecryptMsg(request);
28. //进行回调处理
29.         dealCallBackEvent(respMessage);
30. PrintWriter out = response.getWriter();
31.         out.print(respMessage);
32.         out.close();
33.     }
34. 
35. /**
36.      * 解密XML数据转换JSON
37.      * @param request
38.      * @return
39.      */
40. public String getDecryptMsg(HttpServletRequest request) {
41.         String postData="";   // 密文,对应POST请求的数据
42.         String result="";     // 明文,解密之后的结果
43. String msg_signature = request.getParameter("msg_signature"); // 微信加密签名
44. String timestamp = request.getParameter("timestamp");   // 时间戳
45. String nonce = request.getParameter("nonce");          // 随机数
46. try {
47. //1.获取加密的请求消息:使用输入流获得加密请求消息postData
48. ServletInputStream in = request.getInputStream();
49. BufferedReader reader =new BufferedReader(new InputStreamReader(in));
50. 
51.             String tempStr="";   //作为输出字符串的临时串,用于判断是否读取完毕
52. while(null!=(tempStr=reader.readLine())){
53.                 postData+=tempStr;
54.             }
55. //2.获取消息明文:对加密的请求消息进行解密获得明文
56. WXBizMsgCrypt wxcpt = new WXBizMsgCrypt(ParameterSettings.YHHD_TOKEN, ParameterSettings.YHHD_EAK, ParameterSettings.YH_CORPID);
57.             result = wxcpt.DecryptMsg(msg_signature, timestamp, nonce, postData);
58.         } catch (IOException e) {
59.             e.printStackTrace();
60.         } catch (AesException e) {
61.             e.printStackTrace();
62.         }
63. return result;
64.     }
65. 
66. /**
67.      * 对解密后的数据进行业务逻辑处理
68.      * @param text
69.      */
70. private void dealCallBackEvent(String text) {
71. JSONObject json = XmlTool.documentToJSONObject(text);
72. String event = json.getString("Event");
73. String changeType = json.getString("ChangeType");
74. if (event.equals("change_contact")) {
75. if (changeType.equals("create_user")) { // 创建用户回调
76. String name = json.getString("Name");
77. String userID = json.getString("UserID");
78. String departmentStr = json.getString("Department"); // 部门为逗号分开的字符串
79.                 String[] departmentList = departmentStr.split(",");
80. String corpID = json.getString("ToUserName");
81. String mobile = json.getString("Mobile");
82. if (corpID.equals(ParameterSettings.YH_CORPID)) { // 替换企业ID
83. // 业务逻辑代码
84.                 }
85.             }
86.         }
87.     }

 

核心代码到此结束,以下是其他所有代码

1. import java.util.List;
2. 
3. import org.dom4j.Attribute;
4. import org.dom4j.Document;
5. import org.dom4j.DocumentException;
6. import org.dom4j.DocumentHelper;
7. import org.dom4j.Element;
8. 
9. import com.alibaba.fastjson.JSONArray;
10. import com.alibaba.fastjson.JSONObject;
11. 
12. public class XmlTool {
13. /**
14.      * String 转 org.dom4j.Document
15.      * @param xml
16.      * @return
17.      * @throws DocumentException
18.      */
19. public static Document strToDocument(String xml){
20. try {
21. //加上xml标签是为了获取最外层的标签,如果不需要可以去掉
22. return DocumentHelper.parseText(xml);
23.         } catch (DocumentException e) {
24. return null;
25.         }
26.     }
27. 
28. /**
29.      * org.dom4j.Document 转  com.alibaba.fastjson.JSONObject
30.      * @param xml
31.      * @return
32.      * @throws DocumentException
33.      */
34. public static JSONObject documentToJSONObject(String xml){
35. return elementToJSONObject(strToDocument(xml).getRootElement());
36.     }
37. 
38. /**
39.      * org.dom4j.Element 转  com.alibaba.fastjson.JSONObject
40.      * @param node
41.      * @return
42.      */
43. public static JSONObject elementToJSONObject(Element node) {
44. JSONObject result = new JSONObject();
45. // 当前节点的名称、文本内容和属性
46.         List<Attribute> listAttr = node.attributes();// 当前节点的所有属性的list
47. for (Attribute attr : listAttr) {// 遍历当前节点的所有属性
48.             result.put(attr.getName(), attr.getValue());
49.         }
50. // 递归遍历当前节点所有的子节点
51.         List<Element> listElement = node.elements();// 所有一级子节点的list
52. if (!listElement.isEmpty()) {
53. for (Element e : listElement) {// 遍历所有一级子节点
54. if (e.attributes().isEmpty() && e.elements().isEmpty()) // 判断一级节点是否有属性和子节点
55.                     result.put(e.getName(), e.getTextTrim());// 沒有则将当前节点作为上级节点的属性对待
56. else {
57. if (!result.containsKey(e.getName())) // 判断父节点是否存在该一级节点名称的属性
58.                         result.put(e.getName(), new JSONArray());// 没有则创建
59.                     ((JSONArray) result.get(e.getName())).add(elementToJSONObject(e));// 将该一级节点放入该节点名称的属性对应的值中
60.                 }
61.             }
62.         }
63. return result;
64.     }
65. }

 

1. import lombok.Data;
2. import java.util.List;
3. 
4. @Data
5. public class Items {
6.     List<Item> item;
7. }
1. import lombok.Data;
2. 
3. import java.util.List;
4. 
5. @Data
6. public class Item {
7. private String type;
8. 
9. private List<TextValue> text;
10. 
11. private String name;
12. 
13. private List<WebValue> web;
14. }
1. import lombok.Data;
2. 
3. import java.util.List;
4. 
5. @Data
6. public class Member {
7. private String toUserName;
8. private String fromUserName;
9. private String createTime;
10. private String msgType;
11. private String event;
12. private String changeType;
13. private String userID;
14. private String newUserID;
15. private String name;
16. private String department;
17. private String isLeaderInDept;
18. private String position;
19. private String mobile;
20. private String gender;
21. private String email;
22. private String status;
23. private String avatar;
24. private String alias;
25. private String telephone;
26. private String address;
27. private List<Items> extAttr;
28. }
1. import lombok.Data;
2. 
3. @Data
4. public class TextValue {
5. 
6. private String Value;
7. }
1. import lombok.Data;
2. 
3. @Data
4. public class WebValue {
5. private String Title;
6. private String Url;
7. }

 


相关文章
|
3月前
|
XML 存储 JSON
Twaver-HTML5基础学习(19)数据容器(2)_数据序列化_XML、Json
本文介绍了Twaver HTML5中的数据序列化,包括XML和JSON格式的序列化与反序列化方法。文章通过示例代码展示了如何将DataBox中的数据序列化为XML和JSON字符串,以及如何从这些字符串中反序列化数据,重建DataBox中的对象。此外,还提到了用户自定义属性的序列化注册方法。
49 1
|
4月前
|
XML JSON 前端开发
【Web前端揭秘】XML与JSON:数据界的双雄对决,你的选择将如何改写Web世界的未来?
【8月更文挑战第26天】本文深入探讨了XML和JSON这两种广泛使用的数据交换格式在Web前端开发中的应用。XML采用自定义标签描述数据结构,适用于复杂层次数据的表示,而JSON则以键值对形式呈现数据,更为轻量且易解析。通过对两种格式的示例代码、结构特点及应用场景的分析,本文旨在帮助读者更好地理解它们的差异,并根据实际需求选择最合适的数据交换格式。
70 1
|
3月前
|
XML JSON 数据处理
C# 中的 XML 与 JSON 数据处理
在现代软件开发中,数据交换和存储需求日益增长,XML 和 JSON 成为最常用的数据格式。本文从 C# 角度出发,详细介绍如何处理这两种格式,并提供示例代码。对于 XML,我们介绍了读取、创建和写入 XML 文件的方法;对于 JSON,则展示了如何使用 Newtonsoft.Json 库进行数据解析和序列化。此外,文章还总结了常见问题及其解决方案,帮助开发者更好地应对实际项目中的挑战。
195 61
C# 中的 XML 与 JSON 数据处理
|
5月前
|
小程序 前端开发
生活商城app微信小程序模板源码
生活商城app微信小程序模板源码
65 6
|
2月前
|
XML JSON 数据可视化
数据集学习笔记(二): 转换不同类型的数据集用于模型训练(XML、VOC、YOLO、COCO、JSON、PNG)
本文详细介绍了不同数据集格式之间的转换方法,包括YOLO、VOC、COCO、JSON、TXT和PNG等格式,以及如何可视化验证数据集。
268 1
数据集学习笔记(二): 转换不同类型的数据集用于模型训练(XML、VOC、YOLO、COCO、JSON、PNG)
|
2月前
|
小程序
java--微信小程序发送模板消息
java--微信小程序发送模板消息
139 0
|
2月前
|
XML JSON 前端开发
C#使用HttpClient四种请求数据格式:json、表单数据、文件上传、xml格式
C#使用HttpClient四种请求数据格式:json、表单数据、文件上传、xml格式
519 0
|
4月前
|
XML JSON Java
使用IDEA+Maven搭建整合一个Struts2+Spring4+Hibernate4项目,混合使用传统Xml与@注解,返回JSP视图或JSON数据,快来给你的SSH老项目翻新一下吧
本文介绍了如何使用IntelliJ IDEA和Maven搭建一个整合了Struts2、Spring4、Hibernate4的J2EE项目,并配置了项目目录结构、web.xml、welcome.jsp以及多个JSP页面,用于刷新和学习传统的SSH框架。
114 0
使用IDEA+Maven搭建整合一个Struts2+Spring4+Hibernate4项目,混合使用传统Xml与@注解,返回JSP视图或JSON数据,快来给你的SSH老项目翻新一下吧
|
4月前
|
Java Spring 容器
彻底改变你的编程人生!揭秘 Spring 框架依赖注入的神奇魔力,让你的代码瞬间焕然一新!
【8月更文挑战第31天】本文介绍 Spring 框架中的依赖注入(DI),一种降低代码耦合度的设计模式。通过 Spring 的 DI 容器,开发者可专注业务逻辑而非依赖管理。文中详细解释了 DI 的基本概念及其实现方式,如构造器注入、字段注入与 setter 方法注入,并提供示例说明如何在实际项目中应用这些技术。通过 Spring 的 @Configuration 和 @Bean 注解,可轻松定义与管理应用中的组件及其依赖关系,实现更简洁、易维护的代码结构。
61 0
|
5月前
|
小程序
同城拼车社交微信小程序模板源码
同城拼车社交微信小程序模板源码
93 6