// 第一个参数是transactionId 微信订单号, 第二个参数是outTradeNo 外部订单号 WxPayOrderQueryResult wxPayOrderQueryResult = wxPayService.queryOrder(null, order.getOrderNo());
报错
【响应数据】:<return_code></return_code>
<return_msg></return_msg>
创建交易是正常的,查询的时候报这个错误,是因为没配置公钥吗
异常信息
[2025-03-01 19:05:59.940]-[bf139d99-1129-4fe2-9a65-52ca80d8b5ba]-[]-[] [ERROR] - 查询微信订单失败, orderNo: 20250219153603746625438
com.github.binarywang.wxpay.exception.WxPayException: 返回代码:[FAIL],返回信息:[签名错误,请检查后再试],微信返回的原始报文:
<return_code></return_code>
<return_msg></return_msg>
at com.github.binarywang.wxpay.exception.WxPayException$Builder.build(WxPayException.java:207)
at com.github.binarywang.wxpay.exception.WxPayException.from(WxPayException.java:99)
at com.github.binarywang.wxpay.bean.result.BaseWxPayResult.checkResult(BaseWxPayResult.java:392)
at com.github.binarywang.wxpay.service.impl.BaseWxPayServiceImpl.queryOrder(BaseWxPayServiceImpl.java:493)
at com.github.binarywang.wxpay.service.impl.BaseWxPayServiceImpl.queryOrder(BaseWxPayServiceImpl.java:478)
at com.hailiang.interedu.starCompanion.component.task.QueryWechatOrderJob.queryWechatOrder(QueryWechatOrderJob.java:56)
at com.hailiang.interedu.starCompanion.controller.home.TestController.testQueryWechatOrder(TestController.java:56)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:190)
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:138)
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:105)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:878)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:792)
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1040)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:943)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006)
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:898)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:497)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:584)
at io.undertow.servlet.handlers.ServletHandler.handleRequest(ServletHandler.java:74)
at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:129)
at io.sentry.spring.SentryUserFilter.doFilterInternal(SentryUserFilter.java:56)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61)
at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:131)
at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61)
at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:131)
at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61)
at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:131)
at org.springframework.boot.actuate.metrics.web.servlet.WebMvcMetricsFilter.doFilterInternal(WebMvcMetricsFilter.java:93)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61)
at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:131)
at io.sentry.spring.tracing.SentryTracingFilter.doFilterWithTransaction(SentryTracingFilter.java:106)
at io.sentry.spring.tracing.SentryTracingFilter.doFilterInternal(SentryTracingFilter.java:86)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61)
at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:131)
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61)
at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:131)
at io.sentry.spring.SentrySpringFilter.doFilterInternal(SentrySpringFilter.java:71)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
at io.undertow.servlet.core.ManagedFilter.doFilter(ManagedFilter.java:61)
at io.undertow.servlet.handlers.FilterHandler$FilterChainImpl.doFilter(FilterHandler.java:131)
at io.undertow.servlet.handlers.FilterHandler.handleRequest(FilterHandler.java:84)
at io.undertow.servlet.handlers.security.ServletSecurityRoleHandler.handleRequest(ServletSecurityRoleHandler.java:62)
at io.undertow.servlet.handlers.ServletChain$1.handleRequest(ServletChain.java:68)
at io.undertow.servlet.handlers.ServletDispatchingHandler.handleRequest(ServletDispatchingHandler.java:36)
at io.undertow.servlet.handlers.RedirectDirHandler.handleRequest(RedirectDirHandler.java:68)
at io.undertow.servlet.handlers.security.SSLInformationAssociationHandler.handleRequest(SSLInformationAssociationHandler.java:132)
at io.undertow.servlet.handlers.security.ServletAuthenticationCallHandler.handleRequest(ServletAuthenticationCallHandler.java:57)
at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
at io.undertow.security.handlers.AbstractConfidentialityHandler.handleRequest(AbstractConfidentialityHandler.java:46)
at io.undertow.servlet.handlers.security.ServletConfidentialityConstraintHandler.handleRequest(ServletConfidentialityConstraintHandler.java:64)
at io.undertow.security.handlers.AuthenticationMechanismsHandler.handleRequest(AuthenticationMechanismsHandler.java:60)
at io.undertow.servlet.handlers.security.CachedAuthenticatedSessionHandler.handleRequest(CachedAuthenticatedSessionHandler.java:77)
at io.undertow.security.handlers.AbstractSecurityContextAssociationHandler.handleRequest(AbstractSecurityContextAssociationHandler.java:43)
at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:43)
at io.undertow.servlet.handlers.ServletInitialHandler.handleFirstRequest(ServletInitialHandler.java:269)
at io.undertow.servlet.handlers.ServletInitialHandler.access$100(ServletInitialHandler.java:78)
at io.undertow.servlet.handlers.ServletInitialHandler$2.call(ServletInitialHandler.java:133)
at io.undertow.servlet.handlers.ServletInitialHandler$2.call(ServletInitialHandler.java:130)
at io.undertow.servlet.core.ServletRequestContextThreadSetupAction$1.call(ServletRequestContextThreadSetupAction.java:48)
at io.undertow.servlet.core.ContextClassLoaderSetupAction$1.call(ContextClassLoaderSetupAction.java:43)
at io.undertow.servlet.handlers.ServletInitialHandler.dispatchRequest(ServletInitialHandler.java:249)
at io.undertow.servlet.handlers.ServletInitialHandler.access$000(ServletInitialHandler.java:78)
at io.undertow.servlet.handlers.ServletInitialHandler$1.handleRequest(ServletInitialHandler.java:99)
at io.undertow.server.Connectors.executeRootHandler(Connectors.java:370)
at io.undertow.server.HttpServerExchange$1.run(HttpServerExchange.java:830)
at org.jboss.threads.ContextClassLoaderSavingRunnable.run(ContextClassLoaderSavingRunnable.java:35)
at org.jboss.threads.EnhancedQueueExecutor.safeRun(EnhancedQueueExecutor.java:2019)
at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.doRunTask(EnhancedQueueExecutor.java:1558)
at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1423)
at java.lang.Thread.run(Thread.java:745)
您好!您遇到的“签名错误,请检查后再试”是在调用微信支付的订单查询接口时发生的。这个错误表示微信支付服务器无法验证您发送的查询请求的签名。
根据您提供的信息和堆栈跟踪:
-
创建交易是正常的:这通常意味着您用于V3接口(如创建交易)的配置,包括appId, mchId, apiV3Key, certSerialNo, privateCertPath, privateKeyPath 是正确的,并且商户私钥能够正确签名V3请求。
-
查询订单报错 “签名错误”:
-
您调用的方法是 wxPayService.queryOrder(null, order.getOrderNo()),即 queryOrder(String transactionId, String outTradeNo)。在 weixin-java-pay 这个库中,这个方法签名通常对应的是微信支付V2版本的订单查询API。
-
微信支付V2版本的API和V3版本的API使用不同的签名机制:
-
V2 API:通常使用商户在微信支付平台设置的「API密钥」(也称为
mchKey 或 partnerKey,不是 apiV3Key)进行签名,签名算法一般是MD5或HMAC-SHA256。
-
V3 API:使用商户的私钥进行RSA签名,并通过
apiV3Key对敏感信息进行加密和解密。
-
您提供的配置文件中,主要都是V3接口所需的参数,并没有看到V2接口所必需的 mchKey(API密钥)。
因此,最可能的原因是:
您正在尝试调用一个V2的订单查询接口,但是您的配置中缺少或未正确配置V2接口签名所需的 mchKey(API密钥)。由于缺少这个关键的密钥,SDK无法为V2请求生成正确的签名,导致微信支付服务器返回“签名错误”。
关于您的问题:“是因为没配置公钥吗”
- 这里的“签名错误”是指微信支付服务器无法验证您发过去的请求的签名。这与您用来签名请求的私钥(对于V3)或API密钥/mchKey(对于V2)有关,以及微信支付平台侧对应的您的商户公钥(对于V3)或API密钥/mchKey(对于V2)。
- 如果您指的是微信支付平台的公钥,那个公钥是用来给您的SDK验证微信支付响应的签名或解密平台证书的,与您发送请求时发生的“签名错误”不直接相关。
- 既然V3创建交易正常,说明您的V3相关的商户证书、私钥配置是能让微信支付验证通过的。
解决方案:
-
如果您打算继续使用V2接口查询订单:
- 您需要在您的
WxPayConfig 中正确配置 mchKey(API密钥)。这个密钥是在微信支付商户平台的「账户中心」->「API安全」中设置的那个32位的密钥。
- 确保
signType 配置也与V2接口要求一致(通常是MD5或HMAC-SHA256,默认为MD5)。
-
如果您希望统一使用V3接口(推荐):
- 您应该调用
weixin-java-pay 库中提供的V3版本的订单查询接口。例如,使用类似以下方式(具体方法名和参数可能因库版本而略有差异):
// 示例:按商户订单号查询
TransactionQueryRequest request = new TransactionQueryRequest();
request.setOutTradeNo("YOUR_OUT_TRADE_NO");
// request.setMchid("YOUR_MCHID"); // 通常WxPayConfig中已配置,会自动填充
// 根据你的 WxPayService 实现获取 V3 的 TransactionsService
// 这可能类似于 wxPayService.getPayService().getTransactionsService()
// 或者 wxPayService.v3().transactions().findByOutTradeNo() 等
// 请查阅您所用版本的 weixin-java-pay 的文档或源码确定确切的调用方式
TransactionsApiService transactionsApiService = wxPayService.getTransactionsApiService(); // 假设有这样的方法
Transaction result = transactionsApiService.queryOrderByOutTradeNo(request);
// 或者,某些版本可能直接在 WxPayService 上有 V3 的方法
// WxPayOrderQueryV3Result result = wxPayService.queryOrderV3(null, "YOUR_OUT_TRADE_NO");
- 使用V3接口查询订单,会沿用您已验证通过的V3配置(
apiV3Key、证书等),无需额外配置V2的 mchKey。
总结:
错误的核心在于您调用的 queryOrder 方法很可能是V2版本的API,而您的配置主要针对V3,缺少了V2签名所需的 mchKey。建议您检查代码,确认是需要补充V2的 mchKey 配置,还是改用库中提供的V3订单查询接口。考虑到您创建交易已经使用V3,统一使用V3接口会是更一致和推荐的做法。