wechatpay-apiv3 / wechatpay-apache-httpclient Goto Github PK
View Code? Open in Web Editor NEW微信支付 APIv3 Apache HttpClient装饰器(decorator)
Home Page: https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/pages/index.shtml
License: Apache License 2.0
微信支付 APIv3 Apache HttpClient装饰器(decorator)
Home Page: https://pay.weixin.qq.com/wiki/doc/apiv3/wxpay/pages/index.shtml
License: Apache License 2.0
版本0.2.1签名默认的实现 WechatPay2Credentials ,使用如下代码获取body用于签名:
body = EntityUtils.toString(((HttpEntityEnclosingRequest) request).getEntity());
但RestTemplate创建的是BufferedHttpEntity,里面没有编码信息。编码信息是存在request的Header里的,所以导致无法获取编码而使用缺省的ISO_8859_1,如果body里有中文,就会导致签名验证失败,返回401.
暂时的解决方案是实现自己的Credentials,改为从request里获取编码。希望下个版本能解决这个问题。
mchid、openid 、notify_url、out_trade_no这类命名有的是全小写,有的是下划线分割。7、8年前就是这样,v3版还是这吊样。用java出来起来很反感
已经实现了go语言版本的apiv3的实现,我看官方文档中的示例代码等都不全。
该项目已经能跑通,并验证了获取商户实名状态的查询。希望可以合作。
地址如下:
https://github.com/aosfather/bingo_wx/tree/master/apiv3
jar version: 0.1.6
请求地址:v3/billdownload/file?token=xxxxxx&tartype=gzip
异常:h.auth.WechatPay2Validator : parameter error: empty Request-ID
请教下,apiv3有官方sdk吗,旧版本还有sdk,https://pay.weixin.qq.com/wiki/doc/api/micropay.php?chapter=11_1,
这个wechatpay-apache-httpclient算sdk吗?
java.lang.NoSuchMethodError: org.apache.http.client.methods.HttpRequestWrapper.getTarget()Lorg/apache/http/HttpHost;
at com.wechat.pay.contrib.apache.httpclient.SignatureExec.execute(SignatureExec.java:48)
at org.apache.http.impl.execchain.RetryExec.execute(RetryExec.java:85)
at org.apache.http.impl.execchain.RedirectExec.execute(RedirectExec.java:108)
at org.apache.http.impl.client.InternalHttpClient.doExecute(InternalHttpClient.java:186)
at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:82)
at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:106)
本地实测时发现WechatPay2Credentials.java中方法buildMessage(String nonce, long timestamp, HttpUriRequest request)在签名处理的时候会产生中文乱码问题
将EntityUtils.toString(xxx) 修改成EntityUtils.toString(xxx,“utf-8”)解决该问题。
`如果你使用的是HttpClientBuilder或者HttpClients#custom()来构造HttpClient,你可以直接替换为WechatPayHttpClientBuilder。我们提供相应的方法,可以方便的传入商户私钥和微信支付平台证书等信息。
import com.wechat.pay.contrib.apache.httpclient.WechatPayHttpClientBuilder;
//...
WechatPayHttpClientBuilder builder = WechatPayHttpClientBuilder.create()
.withMerchant(merchantId, merchantSerialNumber, merchantPrivateKey)
.withWechatpay(wechatpayCertificates);
// ... 接下来,你仍然可以通过builder设置各种参数,来配置你的HttpClient
// 通过WechatPayHttpClientBuilder构造的HttpClient,会自动的处理签名和验签
HttpClient httpClient = builder.build();
// 后面跟使用Apache HttpClient一样
HttpResponse response = httpClient.execute(...);
参数说明:
merchantId商户号。
merchantSerialNumber商户证书的证书序列号,请参考什么是证书序列号和如何查看证书序列号。
merchantPrivateKey字符串格式的商户私钥,也就是通过证书工具得到的apiclient_key.pem文件中的内容。
wechatpayCertificates微信支付平台证书的实例列表,用于应答签名的验证。你也可以使用后面章节提到的“自动更新证书功能”。`
从公众平台的哪个功能有设置的,没有找到(mp.weixin.qq.com)
”开发者应当使用微信支付平台证书中的公钥,对上送的敏感信息进行加密。“
我采用AutoUpdateCertificatesVerifier自动更新证书,我需要拿到证书才能进行加密,但是AutoUpdateCertificatesVerifier中的verifier字段是private的,CertificatesVerifier中的private final HashMap<BigInteger, X509Certificate> certificates 也是私有的。目前我是采用反射的方式获取平台证书的。
//具体配置
CloseableHttpClient httpClient = WechatPayHttpClientBuilder.create()
.withMerchant(wxConfig.getMchId(), certSerialNo, privateKeys)
.withValidator(new WechatPay2Validator(verifier))
.build();
HttpComponentsClientHttpRequestFactory clientHttpRequestFactory = new HttpComponentsClientHttpRequestFactory(httpClient);
this.restTemplate = new RestTemplate(clientHttpRequestFactory);
尝试过使用转换器进行转换, 但是是没有效果的。
可以通过更改spring的注入类方式进行实现, 但是觉得不是一个很好的实现方式。
微信这一侧默认的是UFT-8, 我认为最好的解决思路是, 更改WechatPay2Credentials.buildMessage, 将默认的方式ISO-8859-1转换为UTF-8, 避免中文乱码。
if (request.getOriginal() instanceof WechatPayUploadHttpPost) {
body = ((WechatPayUploadHttpPost) request.getOriginal()).getMeta();
} else if (request instanceof HttpEntityEnclosingRequest) {
body = EntityUtils.toString(((HttpEntityEnclosingRequest) request).getEntity());
}
平台证书是会不定期更新。 但是httpclient build 之后,httpclient 的平台证书固定下来了,那如何将平台证书更新?
在AutoUpdateCertificatesVerifier实例初始还首次下载微信平台证书,下次更新平台证书是发现距离上次更新时间超过1小时后就下载新证书列表更新;但并没有定时间隔刷新。
假如有如下场景:应用程序已启动,程序也首次自动下载并更新了平台证书,在旧证书失效微信平台会在更新证书,在新旧证书都有效期间,没有用户使用程序(实际是没有触发下载最新证书),但在旧证书完全失效后只有新证书有效,这时有用户使用,触发验签去调下载证书接口,但此时verifier非空(有旧证书),会使用缓存的旧证书来验签,这时验签失败,不能更新证书,除非重启程序重新实例化AutoUpdateCertificatesVerifier对象。 不知道是不是一个bug。
如题,调试的时候很不方便,如果能以异常的信息或者log的形式带出关键信息就好了
不知道你提供那么多调用方式我到底用哪一个,
如JSAPI示例:
原代码:
httpPost.setEntity(new StringEntity(bos.toString("UTF-8")));
调整为:
httpPost.setEntity(new StringEntity(bos.toString("utf-8"),"utf-8"));
原代码会导致 entity 中文 乱码
serialNo是什么含义,从哪儿获取啊?
这个sdk的签名只代理了 .mch.wexin.qq.com的域名,现在我这边接入的好几个接口都是pay.weixin.qq.com 请问这种要怎么处理
具体原因是WechatPay2Credentials类中的buildMessage方法,EntityUtils.toString会将utf-8默认转换成GBK,再拼接签名,就会导致签名不一致
在HttpClientBuilderTest.getCertificateTest()这个测试代码中,只在请求头中设置了Accept,而官方文档https://wechatpay-api.gitbook.io/wechatpay-api-v3/jie-kou-wen-dang/ping-tai-zheng-shu
明确需要设置Authorization,和User-Agent
在调用V3特约商户进件时,使用AutoUpdateCertificatesVerifier类的 verifier.getValidCertificate().getSerialNumber() 得到的序列号为635238570496275507415531946499716226189925931457,请求微信返回{"code":"PARAM_ERROR","message":"平台证书序列号Wechatpay-Serial错误"};调试发现还有一个参数SerialNumber: [ 6f451529 9b63e8b3 ddfeef69 da0f5f98 8b89d9c1],将其中空格去掉后写死放入header中微信返回成功,麻烦帮忙看看是不是序列号返回有误?
java.security.InvalidKeyException: Illegal key size
java.lang.IllegalArgumentException: java.security.InvalidKeyException: Illegal key size
at com.wechat.pay.contrib.apache.httpclient.util.AesUtil.decryptToString(AesUtil.java:42)
at com.wechat.pay.contrib.apache.httpclient.auth.AutoUpdateCertificatesVerifier.deserializeToCerts(AutoUpdateCertificatesVerifier.java:139)
at com.wechat.pay.contrib.apache.httpclient.auth.AutoUpdateCertificatesVerifier.autoUpdateCert(AutoUpdateCertificatesVerifier.java:109)
at com.wechat.pay.contrib.apache.httpclient.auth.AutoUpdateCertificatesVerifier.<init>(AutoUpdateCertificatesVerifier.java:62)
at com.wechat.pay.contrib.apache.httpclient.auth.AutoUpdateCertificatesVerifier.<init>(AutoUpdateCertificatesVerifier.java:52)
at com.wechat.pay.contrib.apache.httpclient.AutoUpdateVerifierTest.setup(AutoUpdateVerifierTest.java:77)
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.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:24)
at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecutor.runTestClass(JUnitTestClassExecutor.java:110)
at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecutor.execute(JUnitTestClassExecutor.java:58)
at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecutor.execute(JUnitTestClassExecutor.java:38)
at org.gradle.api.internal.tasks.testing.junit.AbstractJUnitTestClassProcessor.processTestClass(AbstractJUnitTestClassProcessor.java:62)
at org.gradle.api.internal.tasks.testing.SuiteTestClassProcessor.processTestClass(SuiteTestClassProcessor.java:51)
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.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:36)
at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
at org.gradle.internal.dispatch.ContextClassLoaderDispatch.dispatch(ContextClassLoaderDispatch.java:33)
at org.gradle.internal.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:94)
at com.sun.proxy.$Proxy2.processTestClass(Unknown Source)
at org.gradle.api.internal.tasks.testing.worker.TestWorker.processTestClass(TestWorker.java:118)
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.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:36)
at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
at org.gradle.internal.remote.internal.hub.MessageHubBackedObjectConnection$DispatchWrapper.dispatch(MessageHubBackedObjectConnection.java:182)
at org.gradle.internal.remote.internal.hub.MessageHubBackedObjectConnection$DispatchWrapper.dispatch(MessageHubBackedObjectConnection.java:164)
at org.gradle.internal.remote.internal.hub.MessageHub$Handler.run(MessageHub.java:413)
at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:64)
at org.gradle.internal.concurrent.ManagedExecutorImpl$1.run(ManagedExecutorImpl.java:48)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at org.gradle.internal.concurrent.ThreadFactoryImpl$ManagedThreadRunnable.run(ThreadFactoryImpl.java:56)
at java.lang.Thread.run(Thread.java:745)
Caused by: java.security.InvalidKeyException: Illegal key size
public String decryptToString(byte[] associatedData, byte[] nonce, String ciphertext)
throws GeneralSecurityException, IOException {
try {
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
SecretKeySpec key = new SecretKeySpec(aesKey, "AES");
GCMParameterSpec spec = new GCMParameterSpec(TAG_LENGTH_BIT, nonce);
cipher.init(Cipher.DECRYPT_MODE, key, spec);
cipher.updateAAD(associatedData);
return new String(cipher.doFinal(Base64.getDecoder().decode(ciphertext)), "utf-8");
} catch (NoSuchAlgorithmException | NoSuchPaddingException e) {
throw new IllegalStateException(e);
} catch (InvalidKeyException | InvalidAlgorithmParameterException e) {
throw new IllegalArgumentException(e);
}
}
此处使用JDK的原始函数,所以尝试切换JDK版本(本地环境只有jdk1.8.0_256 & jdk 14)
切换至 jdk1.8.0_256&jdk14异常均消失
猜测该异常可能和jdk有关
查阅JDK发行版本文档 Java 8 发行版要点说明
其中有文案描述关于AES的关键字
期望官方SDK可以考虑使用第三方或者其他方案解决该问题,SDK切换有可能不适用于生产
在SDK中看到了验签的逻辑,但是貌似没有看到提供现成的验签方法。如果存在的话,麻烦说明一下
自动更新证书只保存最新的,支付回调通知里证书序列号可能是旧的,这样回调通知找不到适配的证书。是否应该把最近的旧证书保留?
误提
你看你写的什么破玩意
环境如下
` public void init() throws IOException {
// 加载商户私钥
PrivateKey merchantPrivateKey = PemUtil.loadPrivateKey(new ByteArrayInputStream(priKey.getBytes("utf-8")));
// 加载平台证书(mchId:商户号,mchSerialNo:商户证书序列号,apiV3Key:V3秘钥)
AutoUpdateCertificatesVerifier verifier = new AutoUpdateCertificatesVerifier(
new WechatPay2Credentials(MCH_ID, new PrivateKeySigner(mchSerialNo, merchantPrivateKey)), MCH_KEY.getBytes("utf-8"));
MinipayTest.verifier = verifier;
// 初始化httpClient
httpClient = WechatPayHttpClientBuilder.create()
.withMerchant(MCH_ID, mchSerialNo, merchantPrivateKey)
.withValidator(new WechatPay2Validator(verifier)).build();
}`
微信支付普通服务商模式下,特约商户进件《提交申请单》接口需要上送平台证书序列号,通过AutoUpdateCertificatesVerifier 获取到的证书(X509Certificate)并没有包含序列号(或者说包含的序列号不是微信接口所需要的的序列号)
https://wechatpay-api.gitbook.io/wechatpay-api-v3/jie-kou-wen-dang/ping-tai-zheng-shu
verifier.getValidCertificate().getSerialNumber()返回的序列号与上述接口返回的序列号不一致。
PrivateKey merchantPrivateKey = PemUtil .loadPrivateKey(new ByteArrayInputStream(privateKey.getBytes("utf-8")));
应该用这个,不说的话完全不知道要用哪个PrivateKey
java.lang.IllegalArgumentException: Entity may not be null
at org.apache.http.util.Args.notNull(Args.java:54) ~[httpcore-4.4.13.jar!/:4.4.13]
at org.apache.http.util.EntityUtils.toString(EntityUtils.java:307) ~[httpcore-4.4.13.jar!/:4.4.13]
但是相同的参数, 在经过重试后, 又可以请求成功!
/**
* {@link com.wechat.pay.contrib.apache.httpclient.auth.WechatPay2Validator#validateParameters(CloseableHttpResponse)}
*/
@SuppressWarnings("all")
protected final void validateParameters(HttpServletRequest request) {
final String requestId = Optional.ofNullable(request.getHeader("Request-ID"))
.orElseThrow(() -> new IllegalArgumentException("empty Request-ID"));
Stream.of("Wechatpay-Serial", "Wechatpay-Signature", "Wechatpay-Timestamp", "Wechatpay-Nonce")
.forEach(name -> Optional.ofNullable(request.getHeader(name))
.orElseThrow(() -> new IllegalArgumentException(String.format("empty [%s], request-id=[%s]", name, requestId))));
final String timestamp = request.getHeader("Wechatpay-Timestamp");
try {
Instant instant = Instant.ofEpochSecond(Long.parseLong(timestamp));
// 拒绝5分钟之外的应答
if (Duration.between(instant, Instant.now()).abs().toMinutes() >= 5) {
throw new IllegalArgumentException(String.format("timestamp=[%s] expires, request-id=[%s]", timestamp, requestId));
}
} catch (DateTimeException | NumberFormatException e) {
throw new IllegalArgumentException(String.format("invalid timestamp=[%s], request-id=[%s]", timestamp, requestId));
}
}
接收回调时如何验证签名
商户号 1534072691
用postman调所有接口都正常,但是使用AutoUpdateCertificatesVerifier 这个类就会报:证书过期。通过这个接口https://api.mch.weixin.qq.com/v3/certificates 查出来2个证书其中一个过期了的。
在 nodev14.4.0 上,十来分钟前刚用 /v3/pay/partner/transactions/native
付了1分钱 😄
项目地址: https://github.com/TheNorthMemory/wechatpay-axios-plugin
我看到官网有介绍沙箱环境的使用,可是我没有看到sdk中有相关配置,请问如何支持sandbox沙箱环境
Connected to the target VM, address: '127.0.0.1:65173', transport: 'socket'
================================装载setup()=============================
22:13:53.053 logback [main] WARN c.w.p.c.a.h.auth.WechatPay2Validator - signature verify fail:
================================装载 after()=============================
org.apache.http.client.ClientProtocolException
at org.apache.http.impl.client.InternalHttpClient.doExecute(InternalHttpClient.java:187)
at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:83)
at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:108)
at com.keesail.klh.utils.WxV3Util.getCertificateTest(WxV3Util.java:130)
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.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:59)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:56)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27)
at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
at org.junit.runners.BlockJUnit4ClassRunner$1.evaluate(BlockJUnit4ClassRunner.java:100)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:366)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:103)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:63)
at org.junit.runners.ParentRunner$4.run(ParentRunner.java:331)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:79)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:329)
at org.junit.runners.ParentRunner.access$100(ParentRunner.java:66)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:293)
at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
at org.junit.runners.ParentRunner.run(ParentRunner.java:413)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:69)
at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:33)
at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:220)
at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:53)
Caused by: org.apache.http.HttpException: 应答的微信支付签名验证失败
at com.wechat.pay.contrib.apache.httpclient.SignatureExec.executeWithSignature(SignatureExec.java:73)
at com.wechat.pay.contrib.apache.httpclient.SignatureExec.execute(SignatureExec.java:49)
at org.apache.http.impl.execchain.RetryExec.execute(RetryExec.java:89)
at org.apache.http.impl.execchain.RedirectExec.execute(RedirectExec.java:110)
at org.apache.http.impl.client.InternalHttpClient.doExecute(InternalHttpClient.java:185)
... 30 more
如题
实际在处理同步返回时是没有问题的,因为大多数取header时是会ignoreCase,但是建议还是按文档的来,否则容易引起误解,尤其是在处理回调时,比如使用spring mvc @RequestHeader获取header的Map,拿到的是Wechatpay-Timestamp,此时就拿不到Wechatpay-TimeStamp会导致验签失败
微信支付V3接口有沙箱环境吗?找遍了官方文档,也没看到有所提及。
1、如果有的话,请求地址也是加 /sandboxnew 前缀吗?比如:"/sandboxnew/v3/pay/transactions/jsapi"?
2、获取平台证书的接口"https://api.mch.weixin.qq.com/v3/certificates",也需要加 "'/sandboxnew/" 前缀吗?
比如 "https://api.mch.weixin.qq.com/sandboxnew/v3/certificates"?
3、沙箱环境获取密钥的专属接口"https://api.mch.weixin.qq.com/sandboxnew/pay/getsignkey",里面需要加 "/v3" 吗?
比如 "https://api.mch.weixin.qq.com/sandboxnew/v3/pay/getsignkey" ?
你们的接口文档感觉做得真差劲,经常是东一榔头、西一棒槌的。看你们 v3 的代码从开发到现在也有两年多了,文档居然还如此不完善。
微信支付请求 请问有碰到nginx 400的问题吗
什么情况下商户会将APIV2升级到V3?感觉两套API区别很大,签名也不一样,社区文档APIV2的单,APIV3还退不了,
如题,望解答
您好😁,请教两个问题:
疑问1:申请退款API是v3/refund/domestic/refunds,我可以不选择微信主动通知,不传notify_url,而是被动拉取查询退款v3/refund/domestic/refunds/{out_refund_no} 可以吗?
疑问2:银行卡支付的退款1-3个工作日到账,那么回调通知也是1-3工作日吗?😊
抛出异常:
java.lang.NullPointerException: null
at com.wechat.pay.contrib.apache.httpclient.SignatureExec.execute(SignatureExec.java:48)
at org.apache.http.impl.execchain.RetryExec.execute(RetryExec.java:89)
at org.apache.http.impl.execchain.RedirectExec.execute(RedirectExec.java:110)
源码:
if (request.getURI().getHost().endsWith(".mch.weixin.qq.com")) {
return executeWithSignature(route, request, context, execAware);
} else {
return mainExec.execute(route, request, context, execAware);
}
原因
当执行第一次后,request中 uri的host被置为null,再次重试,抛出此异常
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.