参考:企业微信-回调配置(一)
官方demo参考:
使用企业微信提供了解密、加密、验证URL三个接口

1、数据回调校验和指令回调校验

这个都是GET请求校验。
参考:官方API文档:3.1 支持Http Get请求验证URL有效性
注意点:在1秒内响应GET请求,响应内容为上一步得到的明文消息内容(不能加引号,不能带bom头,不能带换行符)
这里必须使用HttpServletResponse来响应,使用@RestController的return返回值不能识别,可能是因为加了引号的原因。

  1. HttpServletResponse.write(sEchoStr);

2、刷新Ticket

参考:官方API文档:3.2 支持Http Post请求接收业务数据
注意点:

  1. CorpID = “SuiteID”; //这里要使用SuiteID第三方应用的id。
  2. 官方提供的工具类里,获取参数名称的不对,最新的ToUserName,AgentID,Encrypt是驼峰名称,原来的都是小写的。
  3. post请求体的格式xml,使用官方工具类是,需要先把xml转换成JSON字符串,再给工具类处理
  4. 解密Encrypt,得到明文的消息结构体也是xml格式的,如果要获取里面的数据,也需要进行解析。
  5. 响应也必须使用HttpServletResponse.write();

参数说明:

参数 类型 说明
msg_signature String 企业微信加密签名,msg_signature结合了企业填写的token、请求中的timestamp、nonce参数、加密的消息体
timestamp Integer 时间戳。与nonce结合使用,用于防止请求重放攻击。
nonce String 随机数。与timestamp结合使用,用于防止请求重放攻击。
ToUserName String 企业微信的CorpID,当为第三方应用回调事件时,CorpID的内容为suiteid
AgentID String 接收的应用id,可在应用的设置页面获取。仅应用相关的回调会带该字段。
Encrypt String 消息结构体加密后的字符串

附录:JAVA代码

  1. package com.tj.qywx.controller;
  2. import com.alibaba.fastjson.JSON;
  3. import com.github.wxpay.sdk.WXPayUtil;
  4. import com.qq.weixin.mp.aes.AesException;
  5. import com.qq.weixin.mp.aes.WXBizJsonMsgCrypt;
  6. import com.tj.base.service.BaseNumvarService;
  7. import lombok.extern.slf4j.Slf4j;
  8. import org.springframework.beans.factory.annotation.Autowired;
  9. import org.springframework.web.bind.annotation.*;
  10. import javax.servlet.http.HttpServletResponse;
  11. import java.io.IOException;
  12. import java.io.PrintWriter;
  13. import java.util.Map;
  14. @Slf4j //日志
  15. @RestController //RESTful风格写法
  16. @RequestMapping("/wxCallback") //定义API接口
  17. public class WxCallbackCtrl {
  18. @Autowired
  19. private BaseNumvarService baseNumvarService;
  20. /**
  21. * 数据回调
  22. *
  23. * @param msg_signature 企业微信加密签名,msg_signature计算结合了企业填写的token、请求中的timestamp、nonce、加密的消息体。签名计算方法参考 消息体签名检验
  24. * @param timestamp 时间戳。与nonce结合使用,用于防止请求重放攻击
  25. * @param nonce 随机数。与timestamp结合使用,用于防止请求重放攻击。
  26. * @param echostr 加密的字符串。需要解密得到消息内容明文,解密后有random、msg_len、msg、receiveid四个字段,其中msg即为消息内容明文
  27. */
  28. @GetMapping
  29. void getDataCheck(String msg_signature,
  30. String timestamp,
  31. String nonce,
  32. String echostr,
  33. HttpServletResponse response) throws AesException, IOException {
  34. String sToken = "应用设置的token";
  35. String sCorpID = baseNumvarService.getCorpid();
  36. String sEncodingAESKey = "应用设置的key";
  37. PrintWriter out = response.getWriter();
  38. //调用微信官方提供的工具类
  39. WXBizJsonMsgCrypt wxcpt = new WXBizJsonMsgCrypt(sToken, sEncodingAESKey, sCorpID);
  40. String sEchoStr; //需要返回的明文
  41. try {
  42. sEchoStr = wxcpt.VerifyURL(msg_signature, timestamp,
  43. nonce, echostr);
  44. log.info("verifyurl echostr: {}", sEchoStr);
  45. // 验证URL成功,将sEchoStr返回,这个地方必须这样返回,什么都不要加,不能加引号
  46. out.write(sEchoStr);
  47. out.close();
  48. } catch (Exception e) {
  49. //验证URL失败,错误原因请查看异常
  50. e.printStackTrace();
  51. }
  52. }
  53. /**
  54. * 刷新Ticket
  55. *
  56. * @param msg_signature 企业微信加密签名,msg_signature结合了企业填写的token、请求中的timestamp、nonce参数、加密的消息体
  57. * @param timestamp 时间戳。与nonce结合使用,用于防止请求重放攻击。
  58. * @param nonce 随机数。与timestamp结合使用,用于防止请求重放攻击。
  59. * @param xmlData ToUserName String 企业微信的CorpID,当为第三方应用回调事件时,CorpID的内容为suiteid
  60. * AgentID String 接收的应用id,可在应用的设置页面获取。仅应用相关的回调会带该字段。
  61. * Encrypt String 消息结构体加密后的字符串
  62. * @return
  63. * @throws AesException
  64. */
  65. @PostMapping
  66. void postActionCheck(String msg_signature,
  67. String timestamp,
  68. String nonce,
  69. @RequestBody String xmlData,
  70. HttpServletResponse response) throws IOException {
  71. String sToken = "应用设置的token";
  72. String sCorpID = "SuiteID"; //这里要使用SuiteID第三方应用的id
  73. String sEncodingAESKey = "应用设置的key";
  74. log.info("msg_signature:{}", msg_signature);
  75. log.info("timestamp:{}", timestamp);
  76. log.info("nonce:{}", nonce);
  77. log.info("xmldata的值:{}", xmlData);
  78. PrintWriter out = response.getWriter();
  79. try {
  80. //调用微信官方提供的工具类
  81. WXBizJsonMsgCrypt wxcpt = new WXBizJsonMsgCrypt(sToken, sEncodingAESKey, sCorpID);
  82. //把xml转换成json格式
  83. Map<String, String> map = WXPayUtil.xmlToMap(xmlData);
  84. String jsonString = JSON.toJSONString(map);
  85. log.info("xml转JSON后的字符串的值:{}", jsonString);
  86. /* 官方工具类解析这个几个字符的时候,需要注意,字段名称大小写不一样了。要改成下面的这样的
  87. String encrypt_msg = json.getString("Encrypt");
  88. String tousername = json.getString("ToUserName");
  89. String agentid = json.getString("AgentID");
  90. */
  91. String sMsg = wxcpt.DecryptMsg(msg_signature, timestamp, nonce, jsonString);
  92. log.info("解密后的xml信息:{} ", sMsg);
  93. // 获取SuiteTicket
  94. Map<String, String> msgMap = WXPayUtil.xmlToMap(sMsg);
  95. String SuiteTicket = msgMap.get("SuiteTicket");
  96. log.info("SuiteTicket:{}", SuiteTicket);
  97. } catch (Exception e) {
  98. // TODO
  99. // 解密失败,失败原因请查看异常
  100. e.printStackTrace();
  101. }
  102. out.write("success");
  103. out.close();
  104. }
  105. }