Skip to content

Commit dba8893

Browse files
authored
RSAAutoCertificateConfig实现 NotificationConfig (#94)
1 parent 09a3983 commit dba8893

File tree

3 files changed

+84
-22
lines changed

3 files changed

+84
-22
lines changed

README.md

+9-8
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
![Maven Central](https://img.shields.io/maven-central/v/com.github.wechatpay-apiv3/wechatpay-java?versionPrefix=0.2.3)
33
[![Coverage](https://sonarcloud.io/api/project_badges/measure?project=wechatpay-apiv3_wechatpay-java&metric=coverage)](https://sonarcloud.io/summary/new_code?id=wechatpay-apiv3_wechatpay-java)
44

5-
#微信支付 APIv3 Java SDK
5+
# 微信支付 APIv3 Java SDK
66

77
[微信支付 APIv3](https://wechatpay-api.gitbook.io/wechatpay-api-v3/) 官方 Java 语言客户端开发库。
88

@@ -184,7 +184,7 @@ Config config =
184184
同时,`RSAAutoCertificateProvider` 会启动一个后台线程,定时更新证书(目前设计为60分钟),以实现证书过期时的新老证书平滑切换。
185185

186186
> **Note**
187-
> 每个商户号只能创建一个 `RSAAutoCertificateConfig`。我们建议你将配置类作为全局变量。
187+
> 每个商户号只能创建一个 `RSAAutoCertificateConfig`。我们建议你将配置类作为全局变量。同一个商户号构造多个实例,会抛出 `IllegalStateException` 异常。
188188
189189
### 使用本地的微信支付平台证书
190190

@@ -207,7 +207,7 @@ Config config =
207207
1. 获取HTTP请求头中的 `Wechatpay-Signature``Wechatpay-Nonce``Wechatpay-Timestamp``Wechatpay-Serial``Request-ID``Wechatpay-Signature-Type` 对应的值,构建 `RequestParam`
208208
2. 获取 HTTP 请求体的 `JSON` 纯文本。
209209
3. 根据解密后的通知数据数据结构,构造解密对象类 `DecryptObject` 。支付结果通知解密对象类为 [`Transaction`](service/src/main/java/com/wechat/pay/java/service/payments/model/Transaction.java),退款结果通知解密对象类为 [RefundNotification](service/src/main/java/com/wechat/pay/java/service/refund/model/RefundNotification.java)
210-
4. 初始化 `AutoCertificateNotificationConfig`。微信支付平台证书由 SDK 的自动更新平台能力提供,也可以使用本地证书。
210+
4. 初始化 `RSAAutoCertificateConfig`。微信支付平台证书由 SDK 的自动更新平台能力提供,也可以使用本地证书。
211211
5. 初始化 `NotificationParser`
212212
6. 使用请求参数 `requestParam``DecryptObject.class` ,调用 `parser.parse` 验签并解密报文。
213213

@@ -223,16 +223,17 @@ RequestParam requestParam = new Builder()
223223
.body(requestBody)
224224
.build();
225225

226-
// 初始化 NotificationConfig 使用自动更新平台证书能力,需要设置 APIv3 密钥、商户号、商户证书序列号、商户私钥。
227-
NotificationConfig rsaNotificationConfig = new RSAAutoCertificateNotificationConfig.Builder()
228-
.apiV3Key(apiV3Key)
226+
// 如果已经初始化了 RSAAutoCertificateConfig,可直接使用
227+
// 没有的话,则构造一个
228+
Config config = new RSAAutoCertificateConfig.Builder()
229229
.merchantId(merchantId)
230+
.privateKeyFromPath(privateKeyPath)
230231
.merchantSerialNumber(merchantSerialNumber)
231-
.autoUpdateCertWithKeyStr(privateKey)
232+
.apiV3Key(apiV3key)
232233
.build();
233234

234235
// 初始化 NotificationParser
235-
NotificationParser parser=new NotificationParser(rsaNotificationConfig);
236+
NotificationParser parser = new NotificationParser(config);
236237

237238
// 验签并解密报文
238239
DecryptObject decryptObject = parser.parse(requestParam,DecryptObject.class);

core/src/main/java/com/wechat/pay/java/core/RSAAutoCertificateConfig.java

+66-11
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,80 @@
11
package com.wechat.pay.java.core;
22

3+
import static com.wechat.pay.java.core.notification.Constant.AES_CIPHER_ALGORITHM;
4+
import static com.wechat.pay.java.core.notification.Constant.RSA_SIGN_TYPE;
35
import static java.util.Objects.requireNonNull;
46

57
import com.wechat.pay.java.core.certificate.CertificateProvider;
68
import com.wechat.pay.java.core.certificate.RSAAutoCertificateProvider;
9+
import com.wechat.pay.java.core.cipher.AeadAesCipher;
10+
import com.wechat.pay.java.core.cipher.AeadCipher;
11+
import com.wechat.pay.java.core.cipher.RSAVerifier;
12+
import com.wechat.pay.java.core.cipher.Verifier;
713
import com.wechat.pay.java.core.http.HttpClient;
14+
import com.wechat.pay.java.core.notification.NotificationConfig;
815
import java.nio.charset.StandardCharsets;
9-
import java.security.PrivateKey;
1016

1117
/** 具有自动下载平台证书能力的RSA配置类 */
12-
public final class RSAAutoCertificateConfig extends AbstractRSAConfig {
13-
14-
private RSAAutoCertificateConfig(
15-
String merchantId,
16-
PrivateKey privateKey,
17-
String merchantSerialNumber,
18-
CertificateProvider certificateProvider) {
19-
super(merchantId, privateKey, merchantSerialNumber, certificateProvider);
18+
public final class RSAAutoCertificateConfig extends AbstractRSAConfig
19+
implements NotificationConfig {
20+
21+
private final CertificateProvider certificateProvider;
22+
private final AeadCipher aeadCipher;
23+
24+
private RSAAutoCertificateConfig(Builder builder) {
25+
super(
26+
builder.merchantId,
27+
builder.privateKey,
28+
builder.merchantSerialNumber,
29+
builder.certificateProvider);
30+
this.certificateProvider = builder.certificateProvider;
31+
this.aeadCipher = new AeadAesCipher(builder.apiV3Key);
32+
}
33+
34+
/**
35+
* 获取签名类型
36+
*
37+
* @return 签名类型
38+
*/
39+
@Override
40+
public String getSignType() {
41+
return RSA_SIGN_TYPE;
42+
}
43+
44+
/**
45+
* 获取认证加解密器类型
46+
*
47+
* @return 认证加解密器类型
48+
*/
49+
@Override
50+
public String getCipherType() {
51+
return AES_CIPHER_ALGORITHM;
52+
}
53+
54+
/**
55+
* 创建验签器
56+
*
57+
* @return 验签器
58+
*/
59+
@Override
60+
public Verifier createVerifier() {
61+
return new RSAVerifier(certificateProvider);
62+
}
63+
64+
/**
65+
* 创建认证加解密器
66+
*
67+
* @return 认证加解密器
68+
*/
69+
@Override
70+
public AeadCipher createAeadCipher() {
71+
return aeadCipher;
2072
}
2173

2274
public static class Builder extends AbstractRSAConfigBuilder<Builder> {
2375
protected HttpClient httpClient;
2476
protected byte[] apiV3Key;
77+
protected CertificateProvider certificateProvider;
2578

2679
public Builder apiV3Key(String apiV3key) {
2780
this.apiV3Key = apiV3key.getBytes(StandardCharsets.UTF_8);
@@ -48,8 +101,10 @@ public RSAAutoCertificateConfig build() {
48101
if (httpClient != null) {
49102
providerBuilder.httpClient(httpClient);
50103
}
51-
return new RSAAutoCertificateConfig(
52-
merchantId, privateKey, merchantSerialNumber, providerBuilder.build());
104+
105+
certificateProvider = providerBuilder.build();
106+
107+
return new RSAAutoCertificateConfig(this);
53108
}
54109
}
55110
}

core/src/test/java/com/wechat/pay/java/core/RSAAutoCertificateConfigTest.java

+9-3
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,10 @@
66
import static com.wechat.pay.java.core.model.TestConfig.MERCHANT_PRIVATE_KEY;
77
import static com.wechat.pay.java.core.model.TestConfig.MERCHANT_PRIVATE_KEY_PATH;
88
import static com.wechat.pay.java.core.model.TestConfig.MERCHANT_PRIVATE_KEY_STRING;
9+
import static com.wechat.pay.java.core.notification.Constant.AES_CIPHER_ALGORITHM;
10+
import static com.wechat.pay.java.core.notification.Constant.RSA_SIGN_TYPE;
911
import static java.net.HttpURLConnection.HTTP_OK;
10-
import static org.junit.jupiter.api.Assertions.assertNotNull;
11-
import static org.junit.jupiter.api.Assertions.assertThrows;
12+
import static org.junit.jupiter.api.Assertions.*;
1213

1314
import com.wechat.pay.java.core.RSAAutoCertificateConfig.Builder;
1415
import com.wechat.pay.java.core.auth.Validator;
@@ -92,11 +93,16 @@ public <T> boolean validate(HttpHeaders responseHeaders, String body) {
9293
@ParameterizedTest
9394
@MethodSource("BuilderProvider")
9495
void testConfigWithBuilderProvider(Builder builder) {
95-
Config config = builder.build();
96+
RSAAutoCertificateConfig config = builder.build();
9697
assertNotNull(config.createValidator());
9798
assertNotNull(config.createCredential());
9899
assertNotNull(config.createEncryptor());
99100
assertNotNull(config.createDecryptor());
101+
assertNotNull(config.createAeadCipher());
102+
assertNotNull(config.createVerifier());
103+
104+
assertEquals(RSA_SIGN_TYPE, config.getSignType());
105+
assertEquals(AES_CIPHER_ALGORITHM, config.getCipherType());
100106
}
101107

102108
static Stream<Builder> BuilderProvider() {

0 commit comments

Comments
 (0)