package org.jeecg.modules.qywx.message.controller;
|
|
import lombok.extern.slf4j.Slf4j;
|
import org.apache.commons.codec.digest.DigestUtils;
|
import org.jeecg.modules.qywx.message.utils.WXBizMsgCrypt;
|
import org.springframework.web.bind.annotation.*;
|
import org.w3c.dom.Document;
|
import org.w3c.dom.Element;
|
import org.w3c.dom.NodeList;
|
import org.xml.sax.InputSource;
|
|
import javax.crypto.Cipher;
|
import javax.crypto.spec.IvParameterSpec;
|
import javax.crypto.spec.SecretKeySpec;
|
import javax.xml.parsers.DocumentBuilder;
|
import javax.xml.parsers.DocumentBuilderFactory;
|
import java.io.StringReader;
|
import java.io.UnsupportedEncodingException;
|
import java.net.URLDecoder;
|
import java.nio.charset.StandardCharsets;
|
import java.util.*;
|
|
/**
|
* 企业微信消息回调接口(支持 URL 验证 + 消息接收)
|
*/
|
@RestController
|
@RequestMapping("/qywx/message/callback")
|
@Slf4j
|
public class WeComCallbackController {
|
|
// 替换为你的应用配置
|
private static final String TOKEN = "bPGpQimYTtjAfAj2uTE4fb";
|
private static final String AES_KEY = "hkbscaEtxWAydMIoWe8EW4drpHXaYroQPKBMoKCs2bf"; // EncodingAESKey
|
private static final String CORP_ID = "ww5999b2643c95fa75"; // 企业 ID 或 AppId
|
|
private static WXBizMsgCrypt wxBizMsgCrypt;
|
|
static {
|
try {
|
wxBizMsgCrypt = new WXBizMsgCrypt(TOKEN, AES_KEY, CORP_ID);
|
} catch (Exception e) {
|
throw new RuntimeException("初始化 WXBizMsgCrypt 失败,请检查 Token/AESKey/AppId 是否正确", e);
|
}
|
}
|
|
/**
|
* GET 请求:用于 URL 验证(Token 校验)
|
*/
|
@GetMapping(produces = "text/plain;charset=utf-8")
|
public String verifyUrl(
|
@RequestParam("msg_signature") String msgSignature,
|
@RequestParam("timestamp") String timestamp,
|
@RequestParam("nonce") String nonce,
|
@RequestParam("echostr") String echostr) {
|
try {
|
log.info("收到企业微信 URL 验证请求:msg_signature={}, timestamp={}, nonce={}, echostr={}", msgSignature, timestamp, nonce, echostr);
|
|
// 调用官方 SDK 验证并解密
|
String decryptedEchoStr = wxBizMsgCrypt.VerifyURL(msgSignature, timestamp, nonce, echostr);
|
log.info("解密后的 echostr: {}", decryptedEchoStr);
|
|
// 返回解密后的内容(企业微信要求必须原样返回)
|
return decryptedEchoStr;
|
} catch (Exception e) {
|
log.error("URL 验证失败", e);
|
return "fail";
|
}
|
}
|
|
/**
|
* POST 请求:接收企业微信推送的消息
|
*/
|
@PostMapping(produces = "text/xml;charset=utf-8")
|
public String handleWeComCallback(@RequestBody String xmlData,
|
@RequestParam("msg_signature") String msgSignature,
|
@RequestParam("timestamp") String timestamp,
|
@RequestParam("nonce") String nonce) {
|
try {
|
log.info("收到企业微信消息推送:msg_signature={}, timestamp={}, nonce={}", msgSignature, timestamp, nonce);
|
log.info("原始 XML 数据: {}", xmlData);
|
|
// Step 1: 解密消息
|
String plainXml = wxBizMsgCrypt.DecryptMsg(msgSignature, timestamp, nonce, xmlData);
|
log.info("解密后的明文消息: {}", plainXml);
|
|
// Step 2: 解析 XML 并处理业务逻辑
|
Map<String, String> msgMap = parseXmlToMap(plainXml);
|
String eventType = msgMap.get("Event");
|
String content = msgMap.get("Content");
|
|
log.info("事件类型: {}, 消息内容: {}", eventType, content);
|
|
// Step 3: 业务处理(示例:回复 success)
|
String responseXml = "<xml><returncode>0</returncode><returndata>success</returndata></xml>";
|
return responseXml;
|
} catch (Exception e) {
|
log.error("处理企业微信消息失败", e);
|
return "<xml><returncode>1</returncode><returndata>fail</returndata></xml>";
|
}
|
}
|
|
/**
|
* 将 XML 转为 Map
|
*/
|
private Map<String, String> parseXmlToMap(String xml) throws Exception {
|
Map<String, String> map = new HashMap<>();
|
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
|
DocumentBuilder builder = factory.newDocumentBuilder();
|
StringReader reader = new StringReader(xml);
|
InputSource source = new InputSource(reader);
|
Document doc = builder.parse(source);
|
Element root = doc.getDocumentElement();
|
NodeList list = root.getChildNodes();
|
|
for (int i = 0; i < list.getLength(); i++) {
|
if (list.item(i).getNodeType() == Document.ELEMENT_NODE) {
|
Element element = (Element) list.item(i);
|
map.put(element.getNodeName(), element.getTextContent());
|
}
|
}
|
return map;
|
}
|
|
//public static void main(String[] args) throws UnsupportedEncodingException {
|
// String msg_signature = "eae930cbae5d988ed29f8aac6cf221016f81669e";
|
// String timestamp = "1751356163";
|
// String nonce = "16ljuxd4gd8";
|
// String echostr = "Ax30h%2BharWss%2FeNNQl8x4KdzggrpmLFH8i%2F0mHqVGbcKcq1NeascovZV%2B08ooq5o0ng8RJ2WPyo69A8oGhKpxA%3D%3D";
|
//
|
// String decode = URLDecoder.decode(echostr, "UTF-8");
|
// //System.out.println(decode);
|
// WeComCallbackController weComCallbackController = new WeComCallbackController();
|
// String decryptedEchoStr = weComCallbackController.verifyUrl(msg_signature, timestamp, nonce, decode);
|
// System.out.println(decryptedEchoStr);
|
//}
|
}
|