1 应用场景
审批回调,其实任何需要回调的接口逻辑相同,会一种即可
企业微信后台配置接口地址细心的同学已经发现了,这货的参数跟微信的差不了多少。
1.1 企微后台配置
1.2 配置配置项
其一是回调的接口地址,其二是需要验签用的token,其三是随机的key,然后我们看一下回调接口的回调参数
2 回调接口
2.1 请求方式get
这个是企微文档的回调接口
然后看到回调参数有
msg_signature=ASDFQWEXZCVAQFASDFASDFSS
timestamp=13500001234
nonce=123412323
echostr=ENCRYPT_STR
根据企微提供的加密类我们可以直接对该参数进行解密
post请求为企微验证通过之后发送的数据(接口地址与get请求一样)
接口实现
首先是get请求
/** * get 请求 验签. * * @param msgSignature 加密 * @param timestamp 时间戳 * @param nonce 随机 * @param echostr . * @param response . * @throws Exception . */ @GetMapping(value = "/callback") public void reveiceMsg(@RequestParam(name = "msg_signature") final String msgSignature, @RequestParam(name = "timestamp") final String timestamp, @RequestParam(name = "nonce") final String nonce, @RequestParam(name = "echostr") final String echostr, final HttpServletResponse response) throws Exception { //企业回调的url-----该url不做任何的业务逻辑,仅仅微信查看是否可以调通. WXBizMsgCrypt wxcpt = new WXBizMsgCrypt(token,corpid, encodingAesKey); // 随机字符串 String sEchoStr = wxcpt.verifyURL(msgSignature, timestamp, nonce, echostr); PrintWriter out = response.getWriter(); try { //必须要返回解密之后的明文 if (StringUtils.isBlank(sEchoStr)) { System.out.println("URL验证失败"); } else { System.out.println("验证成功!"); } } catch (Exception e) { e.printStackTrace(); } out.write(sEchoStr); out.flush(); }
get请求有可能解密失败
2.2 请求方式post
/** * 企业微信客户联系回调. * * @param request request * @param sMsgSignature 签名 * @param sTimestamp 时间戳 * @param sNonce 随机值 * @return success */ @ResponseBody @PostMapping(value = "/callback") public String callback(final HttpServletRequest request, @RequestParam(name = "msg_signature") final String sMsgSignature, @RequestParam(name = "timestamp") final String sTimestamp, @RequestParam(name = "nonce") final String sNonce) { try { InputStream inputStream = request.getInputStream(); String sPostData = IOUtils.toString(inputStream, "UTF-8"); WXBizMsgCrypt wxcpt = new WXBizMsgCrypt(token,corpid, encodingAesKey); //解密 String sMsg = msgCrypt.decryptMsg(msgSignature, timeStamp, String nonce, postData); //将post数据转换为map Map<String, String> dataMap = MessageUtil.parseXml(sMsg); //然后去操作你的业务逻辑 } catch (Exception e) { e.printStackTrace(); } return "success"; }
配置完成调试接口即可
3 解析xml代码
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); DocumentBuilder db = dbf.newDocumentBuilder(); StringReader sr = new StringReader(msg); InputSource is = new InputSource(sr); Document document = db.parse(is); Element root = document.getDocumentElement(); // 获取提交用户ID NodeList ApprovalInfo = root.getElementsByTagName("ApprovalInfo"); if (ApprovalInfo == null || ApprovalInfo.getLength() == 0) { logger.error("ApprovalInfo is null"); logger.error(msg); return; } // 获取审批状态 String spNo = ""; String spStatus = ""; NodeList nodes = ApprovalInfo.item(0).getChildNodes(); for (int i = 0; i < nodes.getLength(); i++) { Node node = nodes.item(i); String nodeName = node.getNodeName(); String text = node.getTextContent(); if ("SpNo".equals(nodeName)) { spNo = text; } else if ("SpStatus".equals(nodeName)) { spStatus = text; } }
可能有xml转java对象但是我用起来不是很好用,个人觉得还很差劲,所以我想用xml转jsonobject好一些
import org.apache.commons.lang.StringUtils; import org.jdom2.Document; import org.jdom2.JDOMException; import com.alibaba.fastjson.JSONObject; import org.jdom2.Element; import org.jdom2.input.SAXBuilder; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import java.util.LinkedList; import java.util.List; /** * Created by alany on 2018/7/10. */ public class XmlUtils { public static JSONObject xml2Json(String xmlStr) throws JDOMException, IOException { if (StringUtils.isEmpty(xmlStr)) { return null; } xmlStr = xmlStr.replaceAll("\\\n", ""); byte[] xml = xmlStr.getBytes("UTF-8"); JSONObject json = new JSONObject(); InputStream is = new ByteArrayInputStream(xml); SAXBuilder sb = new SAXBuilder(); Document doc = sb.build(is); Element root = doc.getRootElement(); json.put(root.getName(), iterateElement(root)); return json; } private static JSONObject iterateElement(Element element) { List<Element> node = element.getChildren(); JSONObject obj = new JSONObject(); List list = null; for (Element child : node) { list = new LinkedList(); String text = child.getTextTrim(); if (StringUtils.isBlank(text)) { if (child.getChildren().size() == 0) { continue; } if (obj.containsKey(child.getName())) { list = (List) obj.get(child.getName()); } list.add(iterateElement(child)); //遍历child的子节点 obj.put(child.getName(), list); } else { if (obj.containsKey(child.getName())) { Object value = obj.get(child.getName()); try { list = (List) value; } catch (ClassCastException e) { list.add(value); } } if (child.getChildren().size() == 0) { //child无子节点时直接设置text obj.put(child.getName(), text); } else { list.add(text); obj.put(child.getName(), list); } } } return obj; }
用到的依赖
<dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.32</version> </dependency> <dependency> <groupId>org.jdom</groupId> <artifactId>jdom</artifactId> <version>2.0.2</version> </dependency>