Conversation
Co-authored-by: binarywang <1343140+binarywang@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
此 PR 修复了在公钥模式下(使用 publicKeyId + publicKeyPath)配置并启用 strictlyNeedWechatPaySerial=true 时,SDK 初始化失败并在每次请求时都报错"无可用的平台证书"的问题。根本原因是 AutoUpdateCertificatesVerifier 构造函数立即尝试下载平台证书,对于仅使用公钥的新商户号,下载失败导致初始化异常。
主要改动:
- 增强了
AutoUpdateCertificatesVerifier的容错性,允许证书下载失败而不影响初始化 - 改进了
WxPayService实现类中的异常处理,使证书获取失败时请求仍可继续 - 新增单元测试验证公钥模式下的健壮性
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 5 comments.
| File | Description |
|---|---|
| AutoUpdateCertificatesVerifier.java | 构造函数增加异常容错,verify() 和 getValidCertificate() 方法增加空值检查和有意义的错误提示 |
| WxPayServiceHttpComponentsImpl.java | getWechatPaySerial() 方法捕获异常并返回空字符串,允许请求继续 |
| WxPayServiceApacheHttpImpl.java | getWechatPaySerial() 方法捕获异常并返回空字符串,允许请求继续 |
| AutoUpdateCertificatesVerifierPublicKeyModeTest.java | 新增单元测试,验证公钥模式下构造函数、verify() 和 getValidCertificate() 的行为 |
...ava/com/github/binarywang/wxpay/v3/auth/AutoUpdateCertificatesVerifierPublicKeyModeTest.java
Outdated
Show resolved
Hide resolved
...va-pay/src/main/java/com/github/binarywang/wxpay/v3/auth/AutoUpdateCertificatesVerifier.java
Outdated
Show resolved
Hide resolved
| public void testVerifyShouldReturnFalseWhenNoCertificateAvailable() { | ||
| String invalidMchId = "invalid_mch_id"; | ||
| String invalidApiV3Key = "invalid_api_v3_key_must_be_32_b"; | ||
| String invalidCertSerialNo = "invalid_serial_no"; | ||
| String payBaseUrl = "https://api.mch.weixin.qq.com"; | ||
|
|
||
| WxPayCredentials credentials = new WxPayCredentials( | ||
| invalidMchId, | ||
| new PrivateKeySigner(invalidCertSerialNo, null) | ||
| ); | ||
|
|
||
| AutoUpdateCertificatesVerifier verifier = new AutoUpdateCertificatesVerifier( | ||
| credentials, | ||
| invalidApiV3Key.getBytes(StandardCharsets.UTF_8), | ||
| 60, | ||
| payBaseUrl, | ||
| null | ||
| ); | ||
|
|
||
| // verify 方法应该返回 false,而不是抛出异常 | ||
| boolean result = verifier.verify("test_serial", "test_message".getBytes(), "test_signature"); | ||
| assertFalse(result, "当没有有效证书时,verify 应该返回 false"); | ||
| } | ||
|
|
||
| /** | ||
| * 测试当没有有效证书时,getValidCertificate 方法应该抛出有意义的异常 | ||
| */ | ||
| @Test(expectedExceptions = me.chanjar.weixin.common.error.WxRuntimeException.class, | ||
| expectedExceptionsMessageRegExp = ".*No valid certificate available.*") | ||
| public void testGetValidCertificateShouldThrowMeaningfulException() { | ||
| String invalidMchId = "invalid_mch_id"; | ||
| String invalidApiV3Key = "invalid_api_v3_key_must_be_32_b"; | ||
| String invalidCertSerialNo = "invalid_serial_no"; | ||
| String payBaseUrl = "https://api.mch.weixin.qq.com"; | ||
|
|
||
| WxPayCredentials credentials = new WxPayCredentials( | ||
| invalidMchId, | ||
| new PrivateKeySigner(invalidCertSerialNo, null) | ||
| ); | ||
|
|
||
| AutoUpdateCertificatesVerifier verifier = new AutoUpdateCertificatesVerifier( | ||
| credentials, | ||
| invalidApiV3Key.getBytes(StandardCharsets.UTF_8), | ||
| 60, | ||
| payBaseUrl, | ||
| null | ||
| ); |
There was a problem hiding this comment.
三个测试方法中都重复了相同的测试数据初始化代码(invalidMchId、invalidApiV3Key、invalidCertSerialNo、payBaseUrl、credentials)。建议考虑将这些通用的测试数据提取到 @BeforeMethod 或私有辅助方法中,以减少代码重复并提高可维护性。
...ava/com/github/binarywang/wxpay/v3/auth/AutoUpdateCertificatesVerifierPublicKeyModeTest.java
Outdated
Show resolved
Hide resolved
| WxPayCredentials credentials = new WxPayCredentials( | ||
| invalidMchId, | ||
| new PrivateKeySigner(invalidCertSerialNo, null) |
There was a problem hiding this comment.
测试中直接将 null 传递给 PrivateKeySigner 构造函数的第二个参数(应该是 PrivateKey 类型)。这可能在实际调用时导致空指针异常,虽然这个测试的目的是验证构造函数不抛异常,但从测试设计角度来说,应该提供一个虽然无效但至少类型正确的对象,而不是 null。建议考虑生成一个模拟的 PrivateKey 对象或者在注释中说明为何这里使用 null 是安全的。
🤖 Augment PR SummarySummary: 本 PR 修复微信支付 V3 在公钥模式下因平台证书自动更新失败而导致 SDK 初始化/请求阶段报“无可用的平台证书”的问题。 Changes:
🤖 Was this summary useful? React with 👍 or 👎 |
| instant = Instant.now(); | ||
| } catch (IOException | GeneralSecurityException e) { | ||
| throw new WxRuntimeException(e); | ||
| log.warn("Auto update cert failed during initialization, will retry later, exception = {}", e.getMessage()); |
| String invalidMchId = "invalid_mch_id"; | ||
| String invalidApiV3Key = "invalid_api_v3_key_must_be_32_b"; | ||
| String invalidCertSerialNo = "invalid_serial_no"; | ||
| String payBaseUrl = "https://api.mch.weixin.qq.com"; |
…uth/AutoUpdateCertificatesVerifier.java Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
…uth/AutoUpdateCertificatesVerifierPublicKeyModeTest.java Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
…uth/AutoUpdateCertificatesVerifierPublicKeyModeTest.java Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
|
@copilot apply changes based on the comments in this thread |
Co-authored-by: binarywang <1343140+binarywang@users.noreply.github.com>
已完成重构,将三个测试方法中重复的测试数据初始化代码提取到 |
修复计划
问题说明
用户在使用 4.7.7.B 版本时,配置了公钥模式(
publicKeyId+publicKeyPath)并设置strictlyNeedWechatPaySerial=true,导致以下问题:Auto update cert failed, statusCode = 404, body = {"code":"RESOURCE_NOT_EXISTS","message":"无可用的平台证书"}根本原因
当用户未设置
fullPublicKeyModel=true时(默认为 false),SDK 会尝试同时构建平台证书验证器和公钥验证器。在构建AutoUpdateCertificatesVerifier时,构造函数会立即尝试下载平台证书。对于只使用公钥模式的新商户号,没有平台证书,导致下载失败并抛出异常,中断了整个初始化过程。解决方案
1. 修改 AutoUpdateCertificatesVerifier 构造函数
instant = null,后续每次使用时都会尝试下载证书直到成功2. 增强 verify 方法
3. 增强 getValidCertificate 方法
4. 修改 getWechatPaySerial 方法(两个实现类)
5. 重构单元测试
@BeforeMethod中影响范围
测试验证
使用建议
对于只使用公钥的场景,建议设置
fullPublicKeyModel=true,这样可以完全避免尝试下载平台证书,提升性能。Original prompt
💬 We'd love your input! Share your thoughts on Copilot coding agent in our 2 minute survey.