When developing internal applications, we need to achieve two-way synchronization between internal applications and enterprise wechat, that is, interconnection.
for instance
Synchronization 1: when modifying the internal address book, the enterprise internal OA system can synchronize the enterprise wechat (directly call the API interface)
Synchronization 2: when modifying the address book in the enterprise wechat background, feed it back to the internal OA system (explained in this article)
Generally speaking, the process of realizing address book callback is divided into four steps:
Step 1: the administrator modifies the address book information in the enterprise wechat in the background (all except API interface modification)
Step 2: after the enterprise wechat modifies the address book, send the modification details to the internal system of the enterprise in the form of XML
Step 3: after receiving the XML information, the enterprise internal system decrypts the information
Step 4: for the decrypted information, modify the address book of the enterprise's internal system
Concrete implementation
1, Guide Package
Decryption tool download address
Download the decryption tool provided by enterprise wechat and put it into your own project.
Note that the name of the com package cannot be changed
If the 1.9 package fails to compile, you can use the 1.4 package
<dependency> <groupId>commons-codec</groupId> <artifactId>commons-codec</artifactId> <version>1.4</version> </dependency>
2, Verify URL
Configure the URL in the enterprise wechat management background
The test method is the template for verifying the URL, which can be used immediately
ParameterSettings is the class where I put fixed fields, and the corresponding parameters can be replaced
import com.qq.weixin.mp.aes.AesException; import com.qq.weixin.mp.aes.WXBizMsgCrypt; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.PrintWriter; /** * Verify URL * @param request * @param response * @throws Exception */ public void test(HttpServletRequest request, HttpServletResponse response) throws Exception { // Wechat encryption signature String msg_signature = request.getParameter("msg_signature"); // time stamp String timestamp = request.getParameter("timestamp"); // random number String nonce = request.getParameter("nonce"); // Random string String echostr = request.getParameter("echostr"); System.out.println("request=" + request.getRequestURL()); PrintWriter out = response.getWriter(); // Pass inspection msg_signature verifies the request. If the verification is successful, it returns echostr as it is, indicating that the access is successful, otherwise the access fails String result = null; try { WXBizMsgCrypt wxcpt = new WXBizMsgCrypt(ParameterSettings.YHHD_TOKEN, ParameterSettings.YHHD_EAK, ParameterSettings.AS_CORPID); result = wxcpt.VerifyURL(msg_signature, timestamp, nonce, echostr); } catch (AesException e) { e.printStackTrace(); } if (result == null) { result = ParameterSettings.YHHD_TOKEN; } out.print(result); out.close(); out = null; }
Original CSDN link: https://zwz99.blog.csdn.net/article/details/113818974
3, Declassify
After verifying the URL, replace the interface method of the URL with the code of the callBack method below
When the enterprise wechat sends a callback notice, this method will receive it
The template will convert the data in XML format into standard JSON for subsequent processing
JSON uses Alibaba's fastjson. maven depends on the following:
<dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.9</version> </dependency>
import com.alibaba.fastjson.JSONObject; import com.qq.weixin.mp.aes.AesException; import com.qq.weixin.mp.aes.WXBizMsgCrypt; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import javax.servlet.ServletInputStream; 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; /** * Enterprise wechat sends XML to this method * @param request * @param response * @throws Exception */ @RequestMapping(value = "/callBack", method = RequestMethod.POST) public void callBack(HttpServletRequest request, HttpServletResponse response) throws Exception { request.setCharacterEncoding("UTF-8"); response.setCharacterEncoding("UTF-8"); String respMessage = ""; respMessage=getDecryptMsg(request); //Callback processing dealCallBackEvent(respMessage); PrintWriter out = response.getWriter(); out.print(respMessage); out.close(); } /** * Decrypt XML data conversion JSON * @param request * @return */ public String getDecryptMsg(HttpServletRequest request) { String postData=""; // Ciphertext, corresponding to the data requested by POST String result=""; // Plaintext, the result after decryption String msg_signature = request.getParameter("msg_signature"); // Wechat encryption signature String timestamp = request.getParameter("timestamp"); // time stamp String nonce = request.getParameter("nonce"); // random number try { //1. Get the encrypted request message: use the input stream to get the encrypted request message postData ServletInputStream in = request.getInputStream(); BufferedReader reader =new BufferedReader(new InputStreamReader(in)); String tempStr=""; //As a temporary string of output string, it is used to judge whether the reading is completed while(null!=(tempStr=reader.readLine())){ postData+=tempStr; } //2. Obtain message plaintext: decrypt the encrypted request message to obtain plaintext WXBizMsgCrypt wxcpt = new WXBizMsgCrypt(ParameterSettings.YHHD_TOKEN, ParameterSettings.YHHD_EAK, ParameterSettings.YH_CORPID); result = wxcpt.DecryptMsg(msg_signature, timestamp, nonce, postData); } catch (IOException e) { e.printStackTrace(); } catch (AesException e) { e.printStackTrace(); } return result; } /** * Conduct business logic processing on the decrypted data * @param text */ private void dealCallBackEvent(String text) { JSONObject json = XmlTool.documentToJSONObject(text); String event = json.getString("Event"); String changeType = json.getString("ChangeType"); if (event.equals("change_contact")) { if (changeType.equals("create_user")) { // Create user callback String name = json.getString("Name"); String userID = json.getString("UserID"); String departmentStr = json.getString("Department"); // Comma separated string for Department String[] departmentList = departmentStr.split(","); String corpID = json.getString("ToUserName"); String mobile = json.getString("Mobile"); if (corpID.equals(ParameterSettings.YH_CORPID)) { // Replace enterprise ID // Business logic code } } } }
That's the end of the core code. Here are all the other codes
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 To org dom4j. Document * @param xml * @return * @throws DocumentException */ public static Document strToDocument(String xml){ try { //The xml tag is added to get the outermost tag, which can be removed if not needed return DocumentHelper.parseText(xml); } catch (DocumentException e) { return null; } } /** * org.dom4j.Document Transfer to com alibaba. fastjson. JSONObject * @param xml * @return * @throws DocumentException */ public static JSONObject documentToJSONObject(String xml){ return elementToJSONObject(strToDocument(xml).getRootElement()); } /** * org.dom4j.Element Transfer to com alibaba. fastjson. JSONObject * @param node * @return */ public static JSONObject elementToJSONObject(Element node) { JSONObject result = new JSONObject(); // The name, text content, and attributes of the current node List<Attribute> listAttr = node.attributes();// list of all attributes of the current node for (Attribute attr : listAttr) {// Traverse all attributes of the current node result.put(attr.getName(), attr.getValue()); } // Recursively traverse all child nodes of the current node List<Element> listElement = node.elements();// list of all first level child nodes if (!listElement.isEmpty()) { for (Element e : listElement) {// Traverse all first level child nodes if (e.attributes().isEmpty() && e.elements().isEmpty()) // Judge whether the primary node has attributes and child nodes result.put(e.getName(), e.getTextTrim());// If not, the current node will be treated as the attribute of the parent node else { if (!result.containsKey(e.getName())) // Judge whether the parent node has the attribute of the first level node name result.put(e.getName(), new JSONArray());// Not created ((JSONArray) result.get(e.getName())).add(elementToJSONObject(e));// Put the primary node into the value corresponding to the attribute of the node name } } } return result; } }
import lombok.Data; import java.util.List; @Data public class Items { List<Item> item; }
import lombok.Data; import java.util.List; @Data public class Item { private String type; private List<TextValue> text; private String name; private List<WebValue> web; }
import lombok.Data; import java.util.List; @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<Items> extAttr; }
import lombok.Data; @Data public class TextValue { private String Value; }
import lombok.Data; @Data public class WebValue { private String Title; private String Url; }