Skip to content

Commit 89280ab

Browse files
authored
🎨 #3547【微信支付】修复验证器未正确初始化导致的v3请求构造异常问题
1 parent 0423e68 commit 89280ab

File tree

2 files changed

+139
-20
lines changed

2 files changed

+139
-20
lines changed
Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
package com.github.binarywang.wxpay.config;
2+
3+
import com.github.binarywang.wxpay.exception.WxPayException;
4+
import com.github.binarywang.wxpay.v3.auth.*;
5+
import lombok.AccessLevel;
6+
import lombok.NoArgsConstructor;
7+
import org.apache.commons.lang3.StringUtils;
8+
9+
import java.nio.charset.StandardCharsets;
10+
import java.security.PrivateKey;
11+
import java.security.PublicKey;
12+
13+
/**
14+
* 验证器构建.
15+
*
16+
* @author holy
17+
*/
18+
@NoArgsConstructor(access = AccessLevel.PRIVATE)
19+
class VerifierBuilder {
20+
/**
21+
* 构建验证器.
22+
* <p>
23+
* 场景
24+
* <pre>
25+
* 1. 老商户号,只有平台证书,未开通公钥 (已验证)
26+
* 2. 新商户号,被强制开通公钥,没有平台证书 (已验证)
27+
* 3. 老商户号,有平台证书,主动开通公钥 (未验证,具备条件的朋友,可以帮忙验证下)
28+
* ...
29+
* </pre>
30+
*
31+
* @param certSerialNo c
32+
* @param mchId m
33+
* @param apiV3Key a
34+
* @param merchantPrivateKey m
35+
* @param wxPayHttpProxy w
36+
* @param certAutoUpdateTime c
37+
* @param payBaseUrl p
38+
* @param publicKeyId p
39+
* @param publicKey p
40+
* @return v
41+
* @throws WxPayException e
42+
*/
43+
@SuppressWarnings("java:S107")
44+
static Verifier build(
45+
// 平台证书 - 依赖参数
46+
String certSerialNo,
47+
String mchId,
48+
String apiV3Key,
49+
PrivateKey merchantPrivateKey,
50+
WxPayHttpProxy wxPayHttpProxy,
51+
int certAutoUpdateTime,
52+
String payBaseUrl,
53+
// 公钥 - 依赖参数
54+
String publicKeyId,
55+
PublicKey publicKey
56+
) throws WxPayException {
57+
Verifier certificatesVerifier = null;
58+
Exception ex = null;
59+
60+
// 构建平台证书验证器
61+
// (沿用旧逻辑)优先构建平台证书验证器,因为公钥验证器需要平台证书验证器 (见以下 .setOtherVerifier )
62+
// 新商户号默认无平台证书,已确认无法构建平台证书验证器,会抛出异常;老商户号,有平台证书主动开通公钥的情况,待具备条件的朋友验证
63+
// 建议公钥模式稳定后,优先构建公钥验证器,以免每次都尝试构建平台证书验证器,且失败 {@link com.github.binarywang.wxpay.v3.auth.PublicCertificateVerifier.verify}
64+
if (merchantPrivateKey != null && StringUtils.isNoneBlank(certSerialNo, apiV3Key)) {
65+
try {
66+
certificatesVerifier = getCertificatesVerifier(
67+
certSerialNo, mchId, apiV3Key, merchantPrivateKey, wxPayHttpProxy, certAutoUpdateTime, payBaseUrl
68+
);
69+
} catch (Exception e) {
70+
ex = e;
71+
}
72+
}
73+
74+
// 构建公钥验证器
75+
if (publicKey != null && StringUtils.isNotBlank(publicKeyId)) {
76+
try {
77+
certificatesVerifier = getPublicCertVerifier(publicKeyId, publicKey, certificatesVerifier);
78+
} catch (Exception e) {
79+
ex = e;
80+
}
81+
}
82+
if (certificatesVerifier != null) {
83+
return certificatesVerifier;
84+
}
85+
86+
// 有异常时抛出
87+
if (ex != null) {
88+
throw new WxPayException(ex.getMessage(), ex);
89+
}
90+
91+
// 没有证书验证器时。不确定是否抛出异常,沿用之前逻辑,返回 null
92+
return null;
93+
}
94+
95+
/**
96+
* 获取证书验证器.
97+
*
98+
* @param certSerialNo certSerialNo
99+
* @param mchId mchId
100+
* @param apiV3Key apiV3Key
101+
* @param merchantPrivateKey merchantPrivateKey
102+
* @param wxPayHttpProxy wxPayHttpProxy
103+
* @param certAutoUpdateTime certAutoUpdateTime
104+
* @param payBaseUrl payBaseUrl
105+
* @return verifier
106+
*/
107+
private static AutoUpdateCertificatesVerifier getCertificatesVerifier(
108+
String certSerialNo, String mchId, String apiV3Key, PrivateKey merchantPrivateKey,
109+
WxPayHttpProxy wxPayHttpProxy, int certAutoUpdateTime, String payBaseUrl
110+
) {
111+
return new AutoUpdateCertificatesVerifier(
112+
new WxPayCredentials(mchId, new PrivateKeySigner(certSerialNo, merchantPrivateKey)),
113+
apiV3Key.getBytes(StandardCharsets.UTF_8), certAutoUpdateTime,
114+
payBaseUrl, wxPayHttpProxy);
115+
}
116+
117+
/**
118+
* 获取公钥验证器.
119+
*
120+
* @param publicKeyId id
121+
* @param publicKey key
122+
* @param certificatesVerifier verifier
123+
* @return verifier
124+
*/
125+
private static Verifier getPublicCertVerifier(String publicKeyId, PublicKey publicKey, Verifier certificatesVerifier) {
126+
Verifier publicCertificatesVerifier = new PublicCertificateVerifier(publicKey, publicKeyId);
127+
publicCertificatesVerifier.setOtherVerifier(certificatesVerifier);
128+
certificatesVerifier = publicCertificatesVerifier;
129+
return certificatesVerifier;
130+
}
131+
}

weixin-java-pay/src/main/java/com/github/binarywang/wxpay/config/WxPayConfig.java

Lines changed: 8 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@
44
import com.github.binarywang.wxpay.util.HttpProxyUtils;
55
import com.github.binarywang.wxpay.util.ResourcesUtils;
66
import com.github.binarywang.wxpay.v3.WxPayV3HttpClientBuilder;
7-
import com.github.binarywang.wxpay.v3.auth.*;
7+
import com.github.binarywang.wxpay.v3.auth.Verifier;
8+
import com.github.binarywang.wxpay.v3.auth.WxPayValidator;
89
import com.github.binarywang.wxpay.v3.util.PemUtils;
910
import lombok.Data;
1011
import lombok.EqualsAndHashCode;
@@ -19,7 +20,6 @@
1920
import javax.net.ssl.SSLContext;
2021
import java.io.*;
2122
import java.net.URL;
22-
import java.nio.charset.StandardCharsets;
2323
import java.security.KeyStore;
2424
import java.security.PrivateKey;
2525
import java.security.PublicKey;
@@ -320,7 +320,12 @@ public CloseableHttpClient initApiV3HttpClient() throws WxPayException {
320320
//构造Http Proxy正向代理
321321
WxPayHttpProxy wxPayHttpProxy = getWxPayHttpProxy();
322322

323-
Verifier certificatesVerifier = getVerifier(merchantPrivateKey, wxPayHttpProxy, publicKey);
323+
// 构造证书验签器
324+
Verifier certificatesVerifier = VerifierBuilder.build(
325+
this.getCertSerialNo(), this.getMchId(), this.getApiV3Key(), merchantPrivateKey, wxPayHttpProxy,
326+
this.getCertAutoUpdateTime(), this.getPayBaseUrl(),
327+
this.getPublicKeyId(), publicKey
328+
);
324329

325330
WxPayV3HttpClientBuilder wxPayV3HttpClientBuilder = WxPayV3HttpClientBuilder.create()
326331
.withMerchant(mchId, certSerialNo, merchantPrivateKey)
@@ -346,23 +351,6 @@ public CloseableHttpClient initApiV3HttpClient() throws WxPayException {
346351
}
347352
}
348353

349-
private Verifier getVerifier(PrivateKey merchantPrivateKey, WxPayHttpProxy wxPayHttpProxy, PublicKey publicKey) {
350-
Verifier certificatesVerifier = null;
351-
// 如果配置了平台证书,则初始化验证器以备v2版本接口验签(公钥灰度实现)
352-
if (this.getPrivateCertPath() != null && this.getPrivateKeyPath() != null) {
353-
certificatesVerifier = new AutoUpdateCertificatesVerifier(
354-
new WxPayCredentials(mchId, new PrivateKeySigner(certSerialNo, merchantPrivateKey)),
355-
this.getApiV3Key().getBytes(StandardCharsets.UTF_8), this.getCertAutoUpdateTime(),
356-
this.getPayBaseUrl(), wxPayHttpProxy);
357-
}
358-
if (publicKey != null) {
359-
Verifier publicCertificatesVerifier = new PublicCertificateVerifier(publicKey, publicKeyId);
360-
publicCertificatesVerifier.setOtherVerifier(certificatesVerifier);
361-
certificatesVerifier = publicCertificatesVerifier;
362-
}
363-
return certificatesVerifier;
364-
}
365-
366354
/**
367355
* 初始化一个WxPayHttpProxy对象
368356
*

0 commit comments

Comments
 (0)