Przeglądaj źródła

fix: 微信消息解密支持,修复公众号安全模式下事件无法处理

- handleWxMPNotify 检测 Encrypt 字段并用 WxMpXmlMessage.fromEncryptedXml 解密
- 修复后关注/取消关注/扫码事件在安全模式下也能正常处理
- 故障订阅二维码绑定功能在安全模式下可用

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
skyline 1 dzień temu
rodzic
commit
ebaa5f56e8

+ 23 - 0
car-wash-service/src/main/java/com/kym/service/wechat/impl/WeixinMPServiceImpl.java

@@ -15,6 +15,7 @@ import jakarta.servlet.http.HttpServletResponse;
 import lombok.extern.slf4j.Slf4j;
 import lombok.extern.slf4j.Slf4j;
 import me.chanjar.weixin.common.error.WxErrorException;
 import me.chanjar.weixin.common.error.WxErrorException;
 import me.chanjar.weixin.mp.api.WxMpService;
 import me.chanjar.weixin.mp.api.WxMpService;
+import me.chanjar.weixin.mp.bean.message.WxMpXmlMessage;
 import me.chanjar.weixin.mp.bean.template.WxMpTemplateData;
 import me.chanjar.weixin.mp.bean.template.WxMpTemplateData;
 import me.chanjar.weixin.mp.bean.template.WxMpTemplateMessage;
 import me.chanjar.weixin.mp.bean.template.WxMpTemplateMessage;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.beans.factory.annotation.Value;
@@ -67,7 +68,29 @@ public class WeixinMPServiceImpl implements WeixinMPService {
             String xml = IoUtil.read(request.getInputStream(), CharsetUtil.CHARSET_UTF_8);
             String xml = IoUtil.read(request.getInputStream(), CharsetUtil.CHARSET_UTF_8);
             log.info("收到微信公众号通知:xml message:{}", xml);
             log.info("收到微信公众号通知:xml message:{}", xml);
 
 
+            // 处理加密消息:公众号安全模式下推送的消息需要先解密
             Map<String, Object> ret = XmlUtil.xmlToMap(xml);
             Map<String, Object> ret = XmlUtil.xmlToMap(xml);
+            if (ret.containsKey("Encrypt")) {
+                String timestamp = request.getParameter("timestamp");
+                String nonce = request.getParameter("nonce");
+                String msgSignature = request.getParameter("msg_signature");
+                WxMpXmlMessage decrypted = WxMpXmlMessage.fromEncryptedXml(
+                        xml, wxMpService.getWxMpConfigStorage(), timestamp, nonce, msgSignature);
+                log.info("消息已解密: FromUser={}, MsgType={}, Event={}",
+                        decrypted.getFromUser(), decrypted.getMsgType(), decrypted.getEvent());
+                // 将解密后的字段回填到 ret map,后续逻辑无需改动
+                ret.clear();
+                ret.put("ToUserName", decrypted.getToUser());
+                ret.put("FromUserName", decrypted.getFromUser());
+                ret.put("CreateTime", String.valueOf(decrypted.getCreateTime()));
+                ret.put("MsgType", decrypted.getMsgType());
+                ret.put("Content", decrypted.getContent());
+                ret.put("MsgId", decrypted.getMsgId());
+                if (decrypted.getEvent() != null) {
+                    ret.put("Event", decrypted.getEvent());
+                    ret.put("EventKey", decrypted.getEventKey());
+                }
+            }
             log.info("收到微信公众号通知:map message:{}", ret);
             log.info("收到微信公众号通知:map message:{}", ret);
 
 
             if (!CommUtil.isEmptyOrNull(ret)) {
             if (!CommUtil.isEmptyOrNull(ret)) {