参考:企业微信-回调配置(一)
官方demo参考:
使用企业微信提供了解密、加密、验证URL三个接口
1、数据回调校验和指令回调校验
这个都是GET请求校验。
参考:官方API文档:3.1 支持Http Get请求验证URL有效性
注意点:在1秒内响应GET请求,响应内容为上一步得到的明文消息内容(不能加引号,不能带bom头,不能带换行符)
这里必须使用HttpServletResponse来响应,使用@RestController的return返回值不能识别,可能是因为加了引号的原因。
HttpServletResponse.write(sEchoStr);
2、刷新Ticket
参考:官方API文档:3.2 支持Http Post请求接收业务数据
注意点:
- CorpID = “SuiteID”; //这里要使用SuiteID第三方应用的id。
- 官方提供的工具类里,获取参数名称的不对,最新的ToUserName,AgentID,Encrypt是驼峰名称,原来的都是小写的。
- post请求体的格式xml,使用官方工具类是,需要先把xml转换成JSON字符串,再给工具类处理
- 解密Encrypt,得到明文的消息结构体也是xml格式的,如果要获取里面的数据,也需要进行解析。
- 响应也必须使用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代码
package com.tj.qywx.controller;import com.alibaba.fastjson.JSON;import com.github.wxpay.sdk.WXPayUtil;import com.qq.weixin.mp.aes.AesException;import com.qq.weixin.mp.aes.WXBizJsonMsgCrypt;import com.tj.base.service.BaseNumvarService;import lombok.extern.slf4j.Slf4j;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.web.bind.annotation.*;import javax.servlet.http.HttpServletResponse;import java.io.IOException;import java.io.PrintWriter;import java.util.Map;@Slf4j //日志@RestController //RESTful风格写法@RequestMapping("/wxCallback") //定义API接口public class WxCallbackCtrl {@Autowiredprivate BaseNumvarService baseNumvarService;/*** 数据回调** @param msg_signature 企业微信加密签名,msg_signature计算结合了企业填写的token、请求中的timestamp、nonce、加密的消息体。签名计算方法参考 消息体签名检验* @param timestamp 时间戳。与nonce结合使用,用于防止请求重放攻击* @param nonce 随机数。与timestamp结合使用,用于防止请求重放攻击。* @param echostr 加密的字符串。需要解密得到消息内容明文,解密后有random、msg_len、msg、receiveid四个字段,其中msg即为消息内容明文*/@GetMappingvoid getDataCheck(String msg_signature,String timestamp,String nonce,String echostr,HttpServletResponse response) throws AesException, IOException {String sToken = "应用设置的token";String sCorpID = baseNumvarService.getCorpid();String sEncodingAESKey = "应用设置的key";PrintWriter out = response.getWriter();//调用微信官方提供的工具类WXBizJsonMsgCrypt wxcpt = new WXBizJsonMsgCrypt(sToken, sEncodingAESKey, sCorpID);String sEchoStr; //需要返回的明文try {sEchoStr = wxcpt.VerifyURL(msg_signature, timestamp,nonce, echostr);log.info("verifyurl echostr: {}", sEchoStr);// 验证URL成功,将sEchoStr返回,这个地方必须这样返回,什么都不要加,不能加引号out.write(sEchoStr);out.close();} catch (Exception e) {//验证URL失败,错误原因请查看异常e.printStackTrace();}}/*** 刷新Ticket** @param msg_signature 企业微信加密签名,msg_signature结合了企业填写的token、请求中的timestamp、nonce参数、加密的消息体* @param timestamp 时间戳。与nonce结合使用,用于防止请求重放攻击。* @param nonce 随机数。与timestamp结合使用,用于防止请求重放攻击。* @param xmlData ToUserName String 企业微信的CorpID,当为第三方应用回调事件时,CorpID的内容为suiteid* AgentID String 接收的应用id,可在应用的设置页面获取。仅应用相关的回调会带该字段。* Encrypt String 消息结构体加密后的字符串* @return* @throws AesException*/@PostMappingvoid postActionCheck(String msg_signature,String timestamp,String nonce,@RequestBody String xmlData,HttpServletResponse response) throws IOException {String sToken = "应用设置的token";String sCorpID = "SuiteID"; //这里要使用SuiteID第三方应用的idString sEncodingAESKey = "应用设置的key";log.info("msg_signature:{}", msg_signature);log.info("timestamp:{}", timestamp);log.info("nonce:{}", nonce);log.info("xmldata的值:{}", xmlData);PrintWriter out = response.getWriter();try {//调用微信官方提供的工具类WXBizJsonMsgCrypt wxcpt = new WXBizJsonMsgCrypt(sToken, sEncodingAESKey, sCorpID);//把xml转换成json格式Map<String, String> map = WXPayUtil.xmlToMap(xmlData);String jsonString = JSON.toJSONString(map);log.info("xml转JSON后的字符串的值:{}", jsonString);/* 官方工具类解析这个几个字符的时候,需要注意,字段名称大小写不一样了。要改成下面的这样的String encrypt_msg = json.getString("Encrypt");String tousername = json.getString("ToUserName");String agentid = json.getString("AgentID");*/String sMsg = wxcpt.DecryptMsg(msg_signature, timestamp, nonce, jsonString);log.info("解密后的xml信息:{} ", sMsg);// 获取SuiteTicketMap<String, String> msgMap = WXPayUtil.xmlToMap(sMsg);String SuiteTicket = msgMap.get("SuiteTicket");log.info("SuiteTicket:{}", SuiteTicket);} catch (Exception e) {// TODO// 解密失败,失败原因请查看异常e.printStackTrace();}out.write("success");out.close();}}
