Skip to content

Commit 9ab6416

Browse files
authored
🎨 #3680 【微信支付】修复PEM格式的私钥和证书处理的问题
1 parent 28fac4e commit 9ab6416

File tree

2 files changed

+125
-1
lines changed

2 files changed

+125
-1
lines changed

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

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
import javax.net.ssl.SSLContext;
3434
import java.io.*;
3535
import java.net.URL;
36+
import java.nio.charset.StandardCharsets;
3637
import java.security.KeyStore;
3738
import java.security.PrivateKey;
3839
import java.security.PublicKey;
@@ -435,7 +436,14 @@ private InputStream loadConfigInputStream(String configString, String configPath
435436
}
436437

437438
if (StringUtils.isNotEmpty(configString)) {
438-
configContent = Base64.getDecoder().decode(configString);
439+
// 判断是否为PEM格式的字符串(包含-----BEGIN和-----END标记)
440+
if (configString.contains("-----BEGIN") && configString.contains("-----END")) {
441+
// PEM格式直接转为字节流,让PemUtils处理
442+
configContent = configString.getBytes(StandardCharsets.UTF_8);
443+
} else {
444+
// 纯Base64格式,需要先解码
445+
configContent = Base64.getDecoder().decode(configString);
446+
}
439447
return new ByteArrayInputStream(configContent);
440448
}
441449

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
package com.github.binarywang.wxpay.config;
2+
3+
import com.github.binarywang.wxpay.exception.WxPayException;
4+
import org.testng.annotations.Test;
5+
6+
import static org.testng.Assert.*;
7+
8+
/**
9+
* Test cases for private key format handling in WxPayConfig
10+
*/
11+
public class WxPayConfigPrivateKeyTest {
12+
13+
@Test
14+
public void testPrivateKeyStringFormat_PemFormat() {
15+
WxPayConfig config = new WxPayConfig();
16+
17+
// Set minimal required configuration
18+
config.setMchId("1234567890");
19+
config.setApiV3Key("test-api-v3-key-32-characters-long");
20+
config.setCertSerialNo("test-serial-number");
21+
22+
// Test with PEM format private key string that would previously fail
23+
String pemKey = "-----BEGIN PRIVATE KEY-----\n" +
24+
"MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQC2pK3buBufh8Vo\n" +
25+
"X4sfYbZ5CcPeGMnVQTGmj0b6\n" +
26+
"-----END PRIVATE KEY-----";
27+
28+
config.setPrivateKeyString(pemKey);
29+
30+
// This should not throw a "无效的密钥格式" exception immediately
31+
// The actual key validation will happen during HTTP client initialization
32+
// but at least the format parsing should not fail
33+
34+
try {
35+
// Try to initialize API V3 HTTP client - this might fail for other reasons
36+
// (like invalid key content) but should not fail due to format parsing
37+
config.initApiV3HttpClient();
38+
// If we get here without InvalidKeySpecException, the format detection worked
39+
} catch (WxPayException e) {
40+
// Check that it's not the specific "无效的密钥格式" error from PemUtils
41+
if (e.getCause() != null &&
42+
e.getCause().getMessage() != null &&
43+
e.getCause().getMessage().contains("无效的密钥格式")) {
44+
fail("Private key format detection failed - PEM format was not handled correctly: " + e.getMessage());
45+
}
46+
// Other exceptions are acceptable for this test since we're using a dummy key
47+
} catch (Exception e) {
48+
// Check for the specific InvalidKeySpecException that indicates format problems
49+
if (e.getCause() != null &&
50+
e.getCause().getMessage() != null &&
51+
e.getCause().getMessage().contains("无效的密钥格式")) {
52+
fail("Private key format detection failed - PEM format was not handled correctly: " + e.getMessage());
53+
}
54+
// Other exceptions are acceptable for this test since we're using a dummy key
55+
}
56+
}
57+
58+
@Test
59+
public void testPrivateKeyStringFormat_EmptyString() {
60+
WxPayConfig config = new WxPayConfig();
61+
62+
// Test with empty string - should not cause format errors
63+
config.setPrivateKeyString("");
64+
65+
// This should handle empty strings gracefully
66+
// No assertion needed, just ensuring no exceptions during object creation
67+
assertNotNull(config);
68+
}
69+
70+
@Test
71+
public void testPrivateKeyStringFormat_NullString() {
72+
WxPayConfig config = new WxPayConfig();
73+
74+
// Test with null string - should not cause format errors
75+
config.setPrivateKeyString(null);
76+
77+
// This should handle null strings gracefully
78+
assertNotNull(config);
79+
}
80+
81+
@Test
82+
public void testPrivateCertStringFormat_PemFormat() {
83+
WxPayConfig config = new WxPayConfig();
84+
85+
// Set minimal required configuration
86+
config.setMchId("1234567890");
87+
config.setApiV3Key("test-api-v3-key-32-characters-long");
88+
89+
// Test with PEM format certificate string that would previously fail
90+
String pemCert = "-----BEGIN CERTIFICATE-----\n" +
91+
"MIICdTCCAd4CAQAwDQYJKoZIhvcNAQEFBQAwRTELMAkGA1UEBhMCQVUxEzARBgNV\n" +
92+
"BAsKClRlc3QgQ2VydCBEYXRhMRswGQYDVQQDDBJUZXN0IENlcnRpZmljYXRlQ0Ew\n" +
93+
"-----END CERTIFICATE-----";
94+
95+
config.setPrivateCertString(pemCert);
96+
97+
// This should not throw a format parsing exception immediately
98+
// The actual certificate validation will happen during HTTP client initialization
99+
// but at least the format parsing should not fail
100+
101+
try {
102+
// Try to initialize API V3 HTTP client - this might fail for other reasons
103+
// (like invalid cert content) but should not fail due to format parsing
104+
config.initApiV3HttpClient();
105+
// If we get here without Base64 decoding issues, the format detection worked
106+
} catch (Exception e) {
107+
// Check that it's not the specific Base64 decoding error
108+
if (e.getCause() != null &&
109+
e.getCause().getMessage() != null &&
110+
e.getCause().getMessage().contains("Illegal base64 character")) {
111+
fail("Certificate format detection failed - PEM format was not handled correctly: " + e.getMessage());
112+
}
113+
// Other exceptions are acceptable for this test since we're using a dummy cert
114+
}
115+
}
116+
}

0 commit comments

Comments
 (0)