🎨 #3547【微信支付】修复验证器未正确初始化导致的v3请求构造异常问题

This commit is contained in:
Holy 2025-04-14 11:32:34 +08:00 committed by GitHub
parent 0423e6849d
commit 89280abd00
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 139 additions and 20 deletions

View File

@ -0,0 +1,131 @@
package com.github.binarywang.wxpay.config;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.github.binarywang.wxpay.v3.auth.*;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import java.nio.charset.StandardCharsets;
import java.security.PrivateKey;
import java.security.PublicKey;
/**
* 验证器构建.
*
* @author holy
*/
@NoArgsConstructor(access = AccessLevel.PRIVATE)
class VerifierBuilder {
/**
* 构建验证器.
* <p>
* 场景
* <pre>
* 1. 老商户号只有平台证书未开通公钥 已验证
* 2. 新商户号被强制开通公钥没有平台证书 已验证
* 3. 老商户号有平台证书主动开通公钥 未验证具备条件的朋友可以帮忙验证下
* ...
* </pre>
*
* @param certSerialNo c
* @param mchId m
* @param apiV3Key a
* @param merchantPrivateKey m
* @param wxPayHttpProxy w
* @param certAutoUpdateTime c
* @param payBaseUrl p
* @param publicKeyId p
* @param publicKey p
* @return v
* @throws WxPayException e
*/
@SuppressWarnings("java:S107")
static Verifier build(
// 平台证书 - 依赖参数
String certSerialNo,
String mchId,
String apiV3Key,
PrivateKey merchantPrivateKey,
WxPayHttpProxy wxPayHttpProxy,
int certAutoUpdateTime,
String payBaseUrl,
// 公钥 - 依赖参数
String publicKeyId,
PublicKey publicKey
) throws WxPayException {
Verifier certificatesVerifier = null;
Exception ex = null;
// 构建平台证书验证器
// 沿用旧逻辑优先构建平台证书验证器因为公钥验证器需要平台证书验证器 (见以下 .setOtherVerifier )
// 新商户号默认无平台证书已确认无法构建平台证书验证器会抛出异常老商户号有平台证书主动开通公钥的情况待具备条件的朋友验证
// 建议公钥模式稳定后优先构建公钥验证器以免每次都尝试构建平台证书验证器且失败 {@link com.github.binarywang.wxpay.v3.auth.PublicCertificateVerifier.verify}
if (merchantPrivateKey != null && StringUtils.isNoneBlank(certSerialNo, apiV3Key)) {
try {
certificatesVerifier = getCertificatesVerifier(
certSerialNo, mchId, apiV3Key, merchantPrivateKey, wxPayHttpProxy, certAutoUpdateTime, payBaseUrl
);
} catch (Exception e) {
ex = e;
}
}
// 构建公钥验证器
if (publicKey != null && StringUtils.isNotBlank(publicKeyId)) {
try {
certificatesVerifier = getPublicCertVerifier(publicKeyId, publicKey, certificatesVerifier);
} catch (Exception e) {
ex = e;
}
}
if (certificatesVerifier != null) {
return certificatesVerifier;
}
// 有异常时抛出
if (ex != null) {
throw new WxPayException(ex.getMessage(), ex);
}
// 没有证书验证器时不确定是否抛出异常沿用之前逻辑返回 null
return null;
}
/**
* 获取证书验证器.
*
* @param certSerialNo certSerialNo
* @param mchId mchId
* @param apiV3Key apiV3Key
* @param merchantPrivateKey merchantPrivateKey
* @param wxPayHttpProxy wxPayHttpProxy
* @param certAutoUpdateTime certAutoUpdateTime
* @param payBaseUrl payBaseUrl
* @return verifier
*/
private static AutoUpdateCertificatesVerifier getCertificatesVerifier(
String certSerialNo, String mchId, String apiV3Key, PrivateKey merchantPrivateKey,
WxPayHttpProxy wxPayHttpProxy, int certAutoUpdateTime, String payBaseUrl
) {
return new AutoUpdateCertificatesVerifier(
new WxPayCredentials(mchId, new PrivateKeySigner(certSerialNo, merchantPrivateKey)),
apiV3Key.getBytes(StandardCharsets.UTF_8), certAutoUpdateTime,
payBaseUrl, wxPayHttpProxy);
}
/**
* 获取公钥验证器.
*
* @param publicKeyId id
* @param publicKey key
* @param certificatesVerifier verifier
* @return verifier
*/
private static Verifier getPublicCertVerifier(String publicKeyId, PublicKey publicKey, Verifier certificatesVerifier) {
Verifier publicCertificatesVerifier = new PublicCertificateVerifier(publicKey, publicKeyId);
publicCertificatesVerifier.setOtherVerifier(certificatesVerifier);
certificatesVerifier = publicCertificatesVerifier;
return certificatesVerifier;
}
}

View File

@ -4,7 +4,8 @@ import com.github.binarywang.wxpay.exception.WxPayException;
import com.github.binarywang.wxpay.util.HttpProxyUtils; import com.github.binarywang.wxpay.util.HttpProxyUtils;
import com.github.binarywang.wxpay.util.ResourcesUtils; import com.github.binarywang.wxpay.util.ResourcesUtils;
import com.github.binarywang.wxpay.v3.WxPayV3HttpClientBuilder; import com.github.binarywang.wxpay.v3.WxPayV3HttpClientBuilder;
import com.github.binarywang.wxpay.v3.auth.*; import com.github.binarywang.wxpay.v3.auth.Verifier;
import com.github.binarywang.wxpay.v3.auth.WxPayValidator;
import com.github.binarywang.wxpay.v3.util.PemUtils; import com.github.binarywang.wxpay.v3.util.PemUtils;
import lombok.Data; import lombok.Data;
import lombok.EqualsAndHashCode; import lombok.EqualsAndHashCode;
@ -19,7 +20,6 @@ import org.apache.http.ssl.SSLContexts;
import javax.net.ssl.SSLContext; import javax.net.ssl.SSLContext;
import java.io.*; import java.io.*;
import java.net.URL; import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.security.KeyStore; import java.security.KeyStore;
import java.security.PrivateKey; import java.security.PrivateKey;
import java.security.PublicKey; import java.security.PublicKey;
@ -320,7 +320,12 @@ public class WxPayConfig {
//构造Http Proxy正向代理 //构造Http Proxy正向代理
WxPayHttpProxy wxPayHttpProxy = getWxPayHttpProxy(); WxPayHttpProxy wxPayHttpProxy = getWxPayHttpProxy();
Verifier certificatesVerifier = getVerifier(merchantPrivateKey, wxPayHttpProxy, publicKey); // 构造证书验签器
Verifier certificatesVerifier = VerifierBuilder.build(
this.getCertSerialNo(), this.getMchId(), this.getApiV3Key(), merchantPrivateKey, wxPayHttpProxy,
this.getCertAutoUpdateTime(), this.getPayBaseUrl(),
this.getPublicKeyId(), publicKey
);
WxPayV3HttpClientBuilder wxPayV3HttpClientBuilder = WxPayV3HttpClientBuilder.create() WxPayV3HttpClientBuilder wxPayV3HttpClientBuilder = WxPayV3HttpClientBuilder.create()
.withMerchant(mchId, certSerialNo, merchantPrivateKey) .withMerchant(mchId, certSerialNo, merchantPrivateKey)
@ -346,23 +351,6 @@ public class WxPayConfig {
} }
} }
private Verifier getVerifier(PrivateKey merchantPrivateKey, WxPayHttpProxy wxPayHttpProxy, PublicKey publicKey) {
Verifier certificatesVerifier = null;
// 如果配置了平台证书则初始化验证器以备v2版本接口验签公钥灰度实现
if (this.getPrivateCertPath() != null && this.getPrivateKeyPath() != null) {
certificatesVerifier = new AutoUpdateCertificatesVerifier(
new WxPayCredentials(mchId, new PrivateKeySigner(certSerialNo, merchantPrivateKey)),
this.getApiV3Key().getBytes(StandardCharsets.UTF_8), this.getCertAutoUpdateTime(),
this.getPayBaseUrl(), wxPayHttpProxy);
}
if (publicKey != null) {
Verifier publicCertificatesVerifier = new PublicCertificateVerifier(publicKey, publicKeyId);
publicCertificatesVerifier.setOtherVerifier(certificatesVerifier);
certificatesVerifier = publicCertificatesVerifier;
}
return certificatesVerifier;
}
/** /**
* 初始化一个WxPayHttpProxy对象 * 初始化一个WxPayHttpProxy对象
* *