Giter Club home page Giter Club logo

wechatpay-apache-httpclient's People

Contributors

codeplayer avatar eric-lee-handyman avatar lddssxy avatar lianup avatar vacuityv avatar xy-peng avatar z1cheng avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

wechatpay-apache-httpclient's Issues

和RestTemplate配合使用时,POST请求返回401

版本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出来起来很反感

java.lang.NoSuchMethodError: org.apache.http.client.methods.HttpRequestWrapper.getTarget()

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”)解决该问题。

wechatpayCertificates是从哪里来的?

`如果你使用的是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 也是私有的。目前我是采用反射的方式获取平台证书的。

使用spring restTemplate 中文乱码(APIV3)

//具体配置
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的注入类方式进行实现, 但是觉得不是一个很好的实现方式。

  • org.springframework.http.client.HttpComponentsClientHttpRequest#executeInternal

微信这一侧默认的是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 如何更新平台证书

平台证书是会不定期更新。 但是httpclient build 之后,httpclient 的平台证书固定下来了,那如何将平台证书更新?

自动更新平台证书,旧证书失效后,下载新证书验签失败

在AutoUpdateCertificatesVerifier实例初始还首次下载微信平台证书,下次更新平台证书是发现距离上次更新时间超过1小时后就下载新证书列表更新;但并没有定时间隔刷新
假如有如下场景:应用程序已启动,程序也首次自动下载并更新了平台证书,在旧证书失效微信平台会在更新证书,在新旧证书都有效期间,没有用户使用程序(实际是没有触发下载最新证书),但在旧证书完全失效后只有新证书有效,这时有用户使用,触发验签去调下载证书接口,但此时verifier非空(有旧证书),会使用缓存的旧证书来验签,这时验签失败,不能更新证书,除非重启程序重新实例化AutoUpdateCertificatesVerifier对象。 不知道是不是一个bug。

image

README.MD 文件中示例代码小问题

如JSAPI示例:
原代码:
httpPost.setEntity(new StringEntity(bos.toString("UTF-8")));
调整为:
httpPost.setEntity(new StringEntity(bos.toString("utf-8"),"utf-8"));
原代码会导致 entity 中文 乱码

签名失败

这个sdk的签名只代理了 .mch.wexin.qq.com的域名,现在我这边接入的好几个接口都是pay.weixin.qq.com 请问这种要怎么处理

调用敏感信息解密报 解密失败

调用微信人脸认证 获取实名认证信息的接口 时,接口调用成功 但是在解密敏感信息的时候失败了,报错 ,这个是什么原因
image

使用自动更新平台证书AutoUpdateCertificatesVerifier,返回的平台证书序列号有误

在调用V3特约商户进件时,使用AutoUpdateCertificatesVerifier类的 verifier.getValidCertificate().getSerialNumber() 得到的序列号为635238570496275507415531946499716226189925931457,请求微信返回{"code":"PARAM_ERROR","message":"平台证书序列号Wechatpay-Serial错误"};调试发现还有一个参数SerialNumber: [ 6f451529 9b63e8b3 ddfeef69 da0f5f98 8b89d9c1],将其中空格去掉后写死放入header中微信返回成功,麻烦帮忙看看是不是序列号返回有误?
2

1

JDK 1.8.0_121 版本 在做证书密文解密出现异常

  • 在使用jdk 1.8.0_121版本,对响应的敏感数据数据做AES-256-GCM解密(调试时测试【获取微信证书接口】)出现如下异常
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中没有现成的验签方法

在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()返回的序列号与上述接口返回的序列号不一致。

异步回调验签,校验请求头补充 javax.servlet.http.HttpServletRequest 类

    /**
     * {@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));
        }
    }

如何支持sandbox沙箱环境

我看到官网有介绍沙箱环境的使用,可是我没有看到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

验签文档中说明的是使用Wechatpay-Timestamp

实际在处理同步返回时是没有问题的,因为大多数取header时是会ignoreCase,但是建议还是按文档的来,否则容易引起误解,尤其是在处理回调时,比如使用spring mvc @RequestHeader获取header的Map,拿到的是Wechatpay-Timestamp,此时就拿不到Wechatpay-TimeStamp会导致验签失败

微信支付V3接口有沙箱环境吗?

微信支付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 的代码从开发到现在也有两年多了,文档居然还如此不完善。

httpclint 设置 RetryHandler后 重试报空指针

抛出异常:
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,再次重试,抛出此异常

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.