Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

微信支付成功后,异步通知 NotificationParser.parse 解密数据异常 #112

Closed
pyrange opened this issue Jan 5, 2023 · 6 comments · Fixed by #113
Closed

微信支付成功后,异步通知 NotificationParser.parse 解密数据异常 #112

pyrange opened this issue Jan 5, 2023 · 6 comments · Fixed by #113

Comments

@pyrange
Copy link

pyrange commented Jan 5, 2023

错误描述

微信支付成功,异步通知解密数据异常

运行环境

java:JDK17
依赖微信sdk:wechatpay-java;0.2.4版本

示例代码

image


    // 使用自动更新平台证书的RSA配置
    // 一个商户号只能初始化一个配置,否则会因为重复的下载任务报错
    RSAAutoCertificateConfig config = new RSAAutoCertificateConfig.Builder()
            .merchantId(WeiXinPayConstant.MCH_ID)
            .privateKey(WeiXinPayConstant.MCH_PRIVATE_KEY)
            .merchantSerialNumber(WeiXinPayConstant.MCH_SERIAL_NO)
            .apiV3Key(WeiXinPayConstant.API_V3_KEY)
            .build();

异常信息:

com.wechat.pay.java.core.exception.ValidationException: Processing WechatPay notification,signature verification failed,signType[WECHATPAY2-SHA256-RSA2048]	serial[72A58B94F5350B13A124585D15BF88C1E55AB350]	message[1672906824
WYDi5b6dyyi36Cry6Vd95cYW5EOrwwNo
{"summary":"支付成功","event_type":"TRANSACTION.SUCCESS","create_time":"2023-01-05T16:16:20+08:00","resource":{"original_type":"transaction","algorithm":"AEAD_AES_256_GCM","ciphertext":"dFZoL6Qa18H3/R0fpBvviskQ1xVaXQDkRSJETChAtBcYfmNvBOqmipI8u1yTTl5ddgjarOdAuK5npSjMjfc1/OEPaNx91R2kG82e3NFaXP3csvtSLCNRN6h1MFBlMPqHVGk8SoOKqgGQAxAmzeLUzUlRI9gQm8GDRvJYzsIkTdWs//2yZZAdEOLXe29Uu+Zj41Te+/iHR0JkmHup9XXMSOZ+cjwmoTlycYd9b0u7j1O4f54fG78jsP76jt6YhniJPhi1nN9Mb2v4wYzH6LHA3wWN4oPLQmXMORL8F+gqm88yyrf79XlcZgovTXM1cUIklDb0pGyennQXSfrzz7Z8dxPmmiLo8zp8XHMUtsb81W8lV6oC4c/nykd7j6NPoI8F6VUYDptCH6aZu/nvsMyCRRvalSFHvLYwIIRtNc1/VB49KKF1H4EncY/lx3gOdI4FSrt8Q/wYt+QPqZ/1QEs0QlFYW98TlXPtCC9pgveR4gZRUHdrvYwxwJT2Gn5rQn18vhZDfxrFaBZLxLYruNyyGRXkBMPqsa9i0Exu6e/gcEcvylo9yQUoJ1GDliOIBJ8eF9rELEos","associated_data":"transaction","nonce":"Zs7DNh4Njdvf"},"resource_type":"encrypt-resource","id":"a179bbb2-257f-5c07-826a-287d39b995f6"}
]	sign[hpq6R1V4LO25TYN97VnhkPrRheXyn7WrtmYDLkeI4eF7O248YXYJC6TLCp/T57lNZBAyPtHz+4K0Rm7SqXAQzmGh/OvlAi3FTvXk/Wm8FOp59VqOerxw7HYD3UFItAS0rpozoIC5ha5b2FHqmGCp5l7OGIXLf9PnGW2s551im2BkBLb+1WW2f6udJywoGL/YGVZ4Jl7bwMFYf64GZAc0AIGQqRWBrL7zIiL8Nw4ajBZTiwDOlZiSJg9vzVaHJyj4nSKe8wPy5ZcPq2Hd4JZ0VUvakhiqyxjsz4KJE8nB8HQicMgBSZpuJPRPzxaWd/DB9x73XmCY2A26DRFfs0mZNA==]
	at com.wechat.pay.java.core.notification.NotificationParser.validateRequest(NotificationParser.java:93)
	at com.wechat.pay.java.core.notification.NotificationParser.parse(NotificationParser.java:49)
	at com.pyrange.app.main.web.service.payment.weixin.WeixinPaymentServiceImpl.paymentSuccessNotify(WeixinPaymentServiceImpl.java:367)
	at com.pyrange.app.main.web.controller.WeixinPaymentController.paymentSuccessNotify(WeixinPaymentController.java:37)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:568)
	at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:343)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:196)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
	at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:752)
	at org.springframework.aop.framework.adapter.AfterReturningAdviceInterceptor.invoke(AfterReturningAdviceInterceptor.java:57)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:173)
	at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:752)
	at org.springframework.aop.framework.adapter.MethodBeforeAdviceInterceptor.invoke(MethodBeforeAdviceInterceptor.java:58)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:173)
	at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:752)
	at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:97)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184)
	at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:752)
	at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:703)
	at com.pyrange.app.main.web.controller.WeixinPaymentController$$SpringCGLIB$$0.paymentSuccessNotify(<generated>)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:568)
	at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:207)
	at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:152)
	at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:117)
	at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:884)
	at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:797)
	at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
	at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1080)
	at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:973)
	at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1003)
	at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:906)
	at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:731)
	at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:880)
	at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:814)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:223)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:158)
	at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:185)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:158)
	at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100)
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:185)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:158)
	at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93)
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:185)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:158)
	at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201)
	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:185)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:158)
	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:197)
	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97)
	at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:542)
	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:119)
	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)
	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78)
	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:357)
	at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:400)
	at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65)
	at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:861)
	at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1739)
	at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:52)
	at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1191)
	at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659)
	at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
	at java.base/java.lang.Thread.run(Thread.java:833)

重现bug的步骤

  1. 微信小程序支付
  2. 收到微信通知

预期行为

正常解析密文

导致错误的代码片段

Transaction parse = parser.parse(requestParam, Transaction.class);

操作系统

win10

Java 版本

java 17

wechatpay-java 版本

0.2.4

其他信息

@pyrange pyrange added the bug Something isn't working label Jan 5, 2023
@xy-peng
Copy link
Contributor

xy-peng commented Jan 5, 2023

body要使用原始的报文,而不是 toJSONString() 的字符串。经过序列化和反序列化之后,跟原文不一致。

@xy-peng xy-peng removed the bug Something isn't working label Jan 5, 2023
@xy-peng xy-peng mentioned this issue Jan 5, 2023
@402626224
Copy link

public ResponseEntity<WxResultInfoVo> wxNotify(
        @RequestHeader("wechatpay-serial") String serialNumber,
        @RequestHeader("wechatpay-nonce") String nonce,
        @RequestHeader("wechatpay-signature") String signature,
        @RequestHeader("wechatpay-timestamp") String timestamp,
        @RequestHeader("wechatpay-signature-type") String signType,
        HttpServletRequest request
) {
        String body = IOUtils.toString(request.getInputStream());
        RequestParam requestParam = new RequestParam.Builder()
                .serialNumber(serialNumber.trim())
                .nonce(nonce.trim())
                .signature(signature.trim())
                .timestamp(timestamp.trim())
                // 若未设置signType,默认值为 WECHATPAY2-SHA256-RSA2048
                .signType(signType.trim())
                .body(body)
                .build();
            NotificationParser parser = new NotificationParser(config);
            Map map = parser.parse(requestParam, Map.class);

这样子也是验签不通过

@Roc1991x
Copy link

Roc1991x commented Nov 5, 2023

能给一个获取原始body的例子么?

@liguangling-lgl
Copy link

private String getRequestBody(HttpServletRequest request) {
    ByteArrayOutputStream body = new ByteArrayOutputStream();
    try {
        ServletInputStream inputStream = request.getInputStream();
        byte[] buffer = new byte[1024];
        for (int length; (length = inputStream.read(buffer)) != -1; ) {
            body.write(buffer, 0, length);
        }
    } catch (IOException ex) {
        log.error("支付回调,读取数据流异常", ex);
    }
    log.info("支付回调,通知消息体:{}", body);
    return body.toString();
}

有的极少订单回调会报这个解签错误,大部分订单可以成功,这个是body读取的代码示例,不清楚为什么会这样,微信sdk版本是0.2.7

@AndromedaX7
Copy link

感谢大佬们先踩坑了,让咱吃了现成的了

@helloWorld233333333
Copy link

private String getRequestBody(HttpServletRequest request) {
    ByteArrayOutputStream body = new ByteArrayOutputStream();
    try {
        ServletInputStream inputStream = request.getInputStream();
        byte[] buffer = new byte[1024];
        for (int length; (length = inputStream.read(buffer)) != -1; ) {
            body.write(buffer, 0, length);
        }
    } catch (IOException ex) {
        log.error("支付回调,读取数据流异常", ex);
    }
    log.info("支付回调,通知消息体:{}", body);
    return body.toString();
}

有的极少订单回调会报这个解签错误,大部分订单可以成功,这个是body读取的代码示例,不清楚为什么会这样,微信sdk版本是0.2.7

我猜你要找的是‘签名探测流量’,https://pay.weixin.qq.com/docs/merchant/development/interface-rules/signature-verification.html

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

7 participants