企业微信推送suite 您所在的位置:网站首页 企业微信cache 企业微信推送suite

企业微信推送suite

2024-06-12 19:11| 来源: 网络整理| 查看: 265

企业微信推送suite_ticket对接,由于微信文档不详细,很多地方还有错误,所以对接的时候很是痛苦。通过查阅各种文档,加上整合demo才最终对接成功,拿到了suite_ticket。

推送suite_ticket的文档说是一个POST接口,其实还有一个验证的GET接口,而且需要URL一致的。比如我的接口都是“/suite/receive”。

下面接对接通过代码展示,首先是对接参数:

private final String sToken = "Token"; private final String sCorpID = "CorpID"; private final String suiteID = "SuiteID"; private final String sEncodingAESKey = "EncodingAESKey";

这些参数都是可以通过企业微信管理后台拿到的,比如 在这里插入图片描述 然后是企业微信参数解析类

import javax.crypto.Cipher; import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.SecretKeySpec; import java.nio.charset.StandardCharsets; import java.security.MessageDigest; import java.util.Arrays; import java.util.Base64; /** * 描述:微信参数解密工具 * * @author 罗锅 * @date 2021/9/2 11:44 */ public class WXBizMsgCrypt { byte[] aesKey; String token; String receiveId; /** * 构造函数 * * @param token 企业微信后台,开发者设置的token * @param encodingAesKey 企业微信后台,开发者设置的EncodingAESKey * @param receiveId, 不同场景含义不同,详见文档 */ public WXBizMsgCrypt(String token, String encodingAesKey, String receiveId) { this.token = token; this.receiveId = receiveId; aesKey = Base64.getDecoder().decode(encodingAesKey + "="); } /** * 验证并获取解密后数据 * * @param msgSignature 签名串,对应URL参数的msg_signature * @param timeStamp 时间戳,对应URL参数的timestamp * @param nonce 随机串,对应URL参数的nonce * @param echoStr 随机串,对应URL参数的echostr * @return 解密之后的echoString * @throws Exception 执行失败,请查看该异常的错误码和具体的错误信息 */ public String verifyAndGetData(String msgSignature, String timeStamp, String nonce, String echoStr) throws Exception { String signature = getSignature(token, timeStamp, nonce, echoStr); if (!signature.equals(msgSignature)) { throw new Exception("参数验签不通过"); } return decrypt(echoStr); } /** * 获取参数签名 * * @param token * @param timestamp * @param nonce * @param encrypt * @return * @throws Exception */ private String getSignature(String token, String timestamp, String nonce, String encrypt) throws Exception { String[] array = new String[]{token, timestamp, nonce, encrypt}; StringBuilder sb = new StringBuilder(); // 字符串排序 Arrays.sort(array); for (String s : array) { sb.append(s); } String str = sb.toString(); // SHA1签名生成 MessageDigest md = MessageDigest.getInstance("SHA-1"); md.update(str.getBytes()); byte[] digest = md.digest(); StringBuilder hexStringBuilder = new StringBuilder(); String shaHex; for (byte b : digest) { shaHex = Integer.toHexString(b & 0xFF); if (shaHex.length() // 设置解密模式为AES的CBC模式 Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding"); SecretKeySpec secretKeySpec = new SecretKeySpec(aesKey, "AES"); IvParameterSpec ivParameterSpec = new IvParameterSpec(Arrays.copyOfRange(aesKey, 0, 16)); cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, ivParameterSpec); // 使用BASE64对密文进行解码 byte[] encrypted = Base64.getDecoder().decode(text); // 解密 byte[] original = cipher.doFinal(encrypted); // 去除补位字符 byte[] bytes = decode(original); // 分离16位随机字符串,网络字节序和receiveId byte[] networkOrder = Arrays.copyOfRange(bytes, 16, 20); int xmlLength = recoverNetworkBytesOrder(networkOrder); String xmlContent = new String(Arrays.copyOfRange(bytes, 20, 20 + xmlLength), StandardCharsets.UTF_8); String fromReceiveId = new String(Arrays.copyOfRange(bytes, 20 + xmlLength, bytes.length), StandardCharsets.UTF_8); // receiveId不相同的情况 if (!fromReceiveId.equals(receiveId)) { throw new Exception("receiveId不相同"); } return xmlContent; } /** * 还原4个字节的网络字节序 * * @param orderBytes * @return */ int recoverNetworkBytesOrder(byte[] orderBytes) { int sourceNumber = 0; int length = 4; for (int i = 0; i int pad = decrypted[decrypted.length - 1]; int min = 1; int max = 32; if (pad max) { pad = 0; } return Arrays.copyOfRange(decrypted, 0, decrypted.length - pad); } }

然后是验证接口,推送suite_ticket是这样的,要先用GET请求验证接口,验证通过了以后才可以保存并推送suite_ticket。

@GetMapping("/suite/receive") public String suiteReceive(@RequestParam(value = "msg_signature") String msgSignature, @RequestParam(value = "timestamp") String timestamp, @RequestParam(value = "nonce") String nonce, @RequestParam(value = "echostr") String data) { System.out.println("GET################################"); System.out.println("msgSignature:" + msgSignature); System.out.println("timestamp:" + timestamp); System.out.println("nonce:" + nonce); System.out.println("data:" + data); try { WXBizMsgCrypt wxcpt = new WXBizMsgCrypt(sToken, sEncodingAESKey, sCorpID); String sEchoStr = wxcpt.verifyAndGetData(msgSignature, timestamp, nonce, data); System.out.println("aesDecode:" + sEchoStr); // 将解密后获取的参数直接返回就行 return sEchoStr; } catch (Exception e) { e.printStackTrace(); } }

验证通过后,就可以刷新Ticket了。

@PostMapping("/suite/receive") public String suiteReceivePost(HttpServletRequest request, @RequestParam(value = "msg_signature") String msgSignature, @RequestParam(value = "timestamp") String timestamp, @RequestParam(value = "nonce") String nonce) { System.out.println("POST################################"); System.out.println("msgSignature:" + msgSignature); System.out.println("timestamp:" + timestamp); System.out.println("nonce:" + nonce); String result = null; try { String xmlString = getXMLString(request); System.out.println("data:" + xmlString); String encryptData = XML.toJSONObject(xmlString).getJSONObject("xml").getStr("Encrypt"); System.out.println("encryptData:" + encryptData); WXBizMsgCrypt wxcpt = new WXBizMsgCrypt(sToken, sEncodingAESKey, suiteID); String sEchoStr = wxcpt.verifyAndGetData(msgSignature, timestamp, nonce, encryptData); ; System.out.println("sEchoStr:" + sEchoStr); JSONObject jsonObject = XML.toJSONObject(sEchoStr).getJSONObject("xml"); System.out.println("jsonObject:" + jsonObject.toString()); String infoType = jsonObject.getStr("InfoType"); System.out.println("infoType:" + infoType); // 获取到的suiteTicket String suiteTicket = jsonObject.getStr("SuiteTicket"); System.out.println("suiteTicket:" + suiteTicket); } catch (Exception e) { e.printStackTrace(); } // 该接口返回success return "success"; }

可以看到,GET和POST接口的URI是一致的,不同的是参数和返回内容。验证接口是GET请求,加密内容是URL里获取的,接口直接返回解密内容就行。推送suite_ticket接口是POST请求,加密内容是在请求体里的,接口返回“success”表示成功。

推送suite_ticket接口回调成功以后,每半小时推送一次,注意保存suite_ticket后续接口调用。



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有