From 8a1b729e91929ea1babdadf2f620103fab1f71ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=B5=B5=E5=BF=A0=E6=9E=97?= <170083662@qq.com> Date: Mon, 6 Apr 2026 22:02:53 +0800 Subject: [PATCH] =?UTF-8?q?refactor(wxsdk):=20=E4=BC=98=E5=8C=96=E5=BE=AE?= =?UTF-8?q?=E4=BF=A1=E6=B6=88=E6=81=AF=E8=A7=A3=E5=AF=86=E6=B5=81=E7=A8=8B?= =?UTF-8?q?=E5=92=8C=E6=8E=A5=E5=8F=A3=E9=80=82=E9=85=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增 DecryptXmlMsg 方法,支持公众号/服务号 XML 回调加密消息的验签与解密 - 将解密逻辑抽取到 decryptByCipherText 私有方法,减少重复代码 - 修改 WxOfficialController,使用 XmlUtil 解析 XML 并提取 Encrypt 节点的加密信息 - 在控制器中调用 DecryptXmlMsg 进行消息解密,提升解密流程的健壮性 - 添加对 Encrypt 节点缺失或空内容的错误日志和处理 - 优化日志打印格式,增强调试信息的可读性 --- .../controller/WxOfficialController.java | 11 +++++++++- .../qq/weixin/mp/aes/WXBizJsonMsgCrypt.java | 22 ++++++++++++------- 2 files changed, 24 insertions(+), 9 deletions(-) diff --git a/src/main/java/com/gxwebsoft/common/system/controller/WxOfficialController.java b/src/main/java/com/gxwebsoft/common/system/controller/WxOfficialController.java index 4b1dedb..1721d05 100644 --- a/src/main/java/com/gxwebsoft/common/system/controller/WxOfficialController.java +++ b/src/main/java/com/gxwebsoft/common/system/controller/WxOfficialController.java @@ -139,8 +139,17 @@ public class WxOfficialController extends BaseController { // 如果有加密参数,进行解密 if (StrUtil.isNotBlank(msg_signature) && StrUtil.isNotBlank(xmlData) && xmlData.contains("Encrypt")) { try { + Document encryptedDocument = XmlUtil.parseXml(xmlData); + Element encryptedRoot = XmlUtil.getRootElement(encryptedDocument); + Element encryptElement = XmlUtil.getElement(encryptedRoot, "Encrypt"); + String encryptedMessage = encryptElement != null ? encryptElement.getTextContent() : ""; + if (StrUtil.isBlank(encryptedMessage)) { + log.error("消息解密失败: 未从XML报文中提取到Encrypt节点"); + return "error"; + } + WXBizJsonMsgCrypt crypt = new WXBizJsonMsgCrypt(getOfficialToken(), getOfficialEncodingAESKey(), getOfficialAppId(tenantId)); - xmlData = crypt.DecryptMsg(msg_signature, timestamp, nonce, xmlData); + xmlData = crypt.DecryptXmlMsg(msg_signature, timestamp, nonce, encryptedMessage); System.out.println("解密后xmlData = " + xmlData); } catch (Exception e) { log.error("消息解密失败: {}", e.getMessage()); diff --git a/src/main/java/com/qq/weixin/mp/aes/WXBizJsonMsgCrypt.java b/src/main/java/com/qq/weixin/mp/aes/WXBizJsonMsgCrypt.java index 74ef144..d04ad13 100644 --- a/src/main/java/com/qq/weixin/mp/aes/WXBizJsonMsgCrypt.java +++ b/src/main/java/com/qq/weixin/mp/aes/WXBizJsonMsgCrypt.java @@ -248,20 +248,26 @@ public class WXBizJsonMsgCrypt { // 密钥,公众账号的app secret // 提取密文 Object[] encrypt = JsonParse.extract(postData); + return decryptByCipherText(msgSignature, timeStamp, nonce, encrypt[1].toString()); + } - // 验证安全签名 - String signature = SHA1.getSHA1(token, timeStamp, nonce, encrypt[1].toString()); + /** + * 适配公众号/服务号 XML 回调:直接传入 节点中的密文进行验签与解密。 + */ + public String DecryptXmlMsg(String msgSignature, String timeStamp, String nonce, String encryptedMsg) + throws AesException { + return decryptByCipherText(msgSignature, timeStamp, nonce, encryptedMsg); + } + + private String decryptByCipherText(String msgSignature, String timeStamp, String nonce, String encryptedMsg) + throws AesException { + String signature = SHA1.getSHA1(token, timeStamp, nonce, encryptedMsg); - // 和URL中的签名比较是否相等 - // System.out.println("第三方收到URL中的签名:" + msg_sign); - // System.out.println("第三方校验签名:" + signature); if (!signature.equals(msgSignature)) { throw new AesException(AesException.ValidateSignatureError); } - // 解密 - String result = decrypt(encrypt[1].toString()); - return result; + return decrypt(encryptedMsg); } /**