Skip to content

Commit c25c725

Browse files
authored
自动下载证书支持代理 (#124)
1 parent e9b5ee2 commit c25c725

12 files changed

+304
-125
lines changed

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

+13-4
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,8 @@
66

77
import com.wechat.pay.java.core.certificate.CertificateProvider;
88
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;
9+
import com.wechat.pay.java.core.cipher.*;
10+
import com.wechat.pay.java.core.http.AbstractHttpClientBuilder;
1311
import com.wechat.pay.java.core.http.HttpClient;
1412
import com.wechat.pay.java.core.notification.NotificationConfig;
1513
import java.nio.charset.StandardCharsets;
@@ -75,6 +73,7 @@ public static class Builder extends AbstractRSAConfigBuilder<Builder> {
7573
protected HttpClient httpClient;
7674
protected byte[] apiV3Key;
7775
protected CertificateProvider certificateProvider;
76+
protected AbstractHttpClientBuilder<?> httpClientBuilder;
7877

7978
public Builder apiV3Key(String apiV3key) {
8079
this.apiV3Key = apiV3key.getBytes(StandardCharsets.UTF_8);
@@ -86,6 +85,11 @@ public Builder httpClient(HttpClient httpClient) {
8685
return this;
8786
}
8887

88+
public Builder httpClientBuilder(AbstractHttpClientBuilder<?> builder) {
89+
httpClientBuilder = builder;
90+
return this;
91+
}
92+
8993
@Override
9094
protected Builder self() {
9195
return this;
@@ -98,10 +102,15 @@ public RSAAutoCertificateConfig build() {
98102
.apiV3Key(requireNonNull(apiV3Key))
99103
.privateKey(requireNonNull(privateKey))
100104
.merchantSerialNumber(requireNonNull(merchantSerialNumber));
105+
101106
if (httpClient != null) {
102107
providerBuilder.httpClient(httpClient);
103108
}
104109

110+
if (httpClientBuilder != null) {
111+
providerBuilder.httpClientBuilder(httpClientBuilder);
112+
}
113+
105114
certificateProvider = providerBuilder.build();
106115

107116
return new RSAAutoCertificateConfig(this);

core/src/main/java/com/wechat/pay/java/core/certificate/RSAAutoCertificateProvider.java

+16-5
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import com.wechat.pay.java.core.cipher.AeadAesCipher;
99
import com.wechat.pay.java.core.cipher.AeadCipher;
1010
import com.wechat.pay.java.core.cipher.RSASigner;
11+
import com.wechat.pay.java.core.http.AbstractHttpClientBuilder;
1112
import com.wechat.pay.java.core.http.DefaultHttpClientBuilder;
1213
import com.wechat.pay.java.core.http.HttpClient;
1314
import com.wechat.pay.java.core.http.HttpHeaders;
@@ -45,6 +46,7 @@ public static class Builder {
4546
private PrivateKey privateKey;
4647
private String merchantSerialNumber;
4748
private HttpClient httpClient;
49+
private AbstractHttpClientBuilder<?> httpClientBuilder;
4850

4951
public Builder merchantId(String merchantId) {
5052
this.merchantId = merchantId;
@@ -76,6 +78,12 @@ public Builder merchantSerialNumber(String merchantSerialNumber) {
7678
return this;
7779
}
7880

81+
public Builder httpClientBuilder(AbstractHttpClientBuilder<?> builder) {
82+
// httpClientBuilder 不是不可变的,所以为了避免过程中修改入参或者值发生变化,这里制作了一个副本
83+
this.httpClientBuilder = builder.newInstance();
84+
return this;
85+
}
86+
7987
private final Validator emptyValidator =
8088
new Validator() {
8189
@Override
@@ -86,15 +94,18 @@ public boolean validate(HttpHeaders responseHeaders, String body) {
8694

8795
public RSAAutoCertificateProvider build() {
8896
if (httpClient == null) {
89-
DefaultHttpClientBuilder httpClientBuilder =
90-
new DefaultHttpClientBuilder().validator(emptyValidator);
91-
if (credential == null) {
97+
if (httpClientBuilder == null) {
98+
httpClientBuilder = new DefaultHttpClientBuilder();
99+
}
100+
101+
if (credential == null && privateKey != null) {
92102
credential =
93103
new WechatPay2Credential(
94104
requireNonNull(merchantId),
95-
new RSASigner(requireNonNull(merchantSerialNumber), requireNonNull(privateKey)));
105+
new RSASigner(requireNonNull(merchantSerialNumber), privateKey));
96106
}
97-
httpClient = httpClientBuilder.credential(credential).build();
107+
108+
httpClient = httpClientBuilder.credential(credential).validator(emptyValidator).build();
98109
}
99110
return new RSAAutoCertificateProvider(
100111
merchantId, new AeadAesCipher(requireNonNull(apiV3Key)), httpClient);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
package com.wechat.pay.java.core.http;
2+
3+
import com.wechat.pay.java.core.auth.Credential;
4+
import com.wechat.pay.java.core.auth.Validator;
5+
6+
public interface AbstractHttpClientBuilder<T extends AbstractHttpClientBuilder<T>> {
7+
8+
/**
9+
* 复制工厂,复制一个当前对象
10+
*
11+
* @return 对象的副本
12+
*/
13+
T newInstance();
14+
15+
/**
16+
* 设置验证器
17+
*
18+
* @param validator 验证器
19+
* @return the AbstractHttpClientBuilder
20+
*/
21+
T validator(Validator validator);
22+
23+
/**
24+
* 设置凭据生成器
25+
*
26+
* @param credential 凭据生成器
27+
* @return the AbstractHttpClientBuilder
28+
*/
29+
T credential(Credential credential);
30+
31+
/**
32+
* 构建 AbstractHttpClient
33+
*
34+
* @return AbstractHttpClient
35+
*/
36+
AbstractHttpClient build();
37+
}

core/src/main/java/com/wechat/pay/java/core/http/DefaultHttpClientBuilder.java

+24-2
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@
1010
import java.util.concurrent.TimeUnit;
1111

1212
/** 默认HttpClient构造器 */
13-
public class DefaultHttpClientBuilder {
13+
public class DefaultHttpClientBuilder
14+
implements AbstractHttpClientBuilder<DefaultHttpClientBuilder> {
1415

1516
private Credential credential;
1617
private Validator validator;
@@ -21,6 +22,24 @@ public class DefaultHttpClientBuilder {
2122
private int connectTimeoutMs = -1;
2223
private Proxy proxy;
2324

25+
/**
26+
* 复制工厂,复制一个当前对象
27+
*
28+
* @return 对象的副本
29+
*/
30+
@Override
31+
public DefaultHttpClientBuilder newInstance() {
32+
DefaultHttpClientBuilder result = new DefaultHttpClientBuilder();
33+
result.credential = this.credential;
34+
result.validator = this.validator;
35+
result.customizeOkHttpClient = this.customizeOkHttpClient;
36+
result.readTimeoutMs = this.readTimeoutMs;
37+
result.writeTimeoutMs = this.writeTimeoutMs;
38+
result.connectTimeoutMs = this.connectTimeoutMs;
39+
result.proxy = this.proxy;
40+
return result;
41+
}
42+
2443
/**
2544
* 设置读超时
2645
*
@@ -60,6 +79,7 @@ public DefaultHttpClientBuilder connectTimeoutMs(int connectTimeoutMs) {
6079
* @param credential 凭据生成器
6180
* @return defaultHttpClientBuilder
6281
*/
82+
@Override
6383
public DefaultHttpClientBuilder credential(Credential credential) {
6484
this.credential = credential;
6585
return this;
@@ -71,6 +91,7 @@ public DefaultHttpClientBuilder credential(Credential credential) {
7191
* @param validator 验证器
7292
* @return defaultHttpClientBuilder
7393
*/
94+
@Override
7495
public DefaultHttpClientBuilder validator(Validator validator) {
7596
this.validator = validator;
7697
return this;
@@ -104,7 +125,8 @@ public DefaultHttpClientBuilder proxy(Proxy proxy) {
104125
*
105126
* @return httpClient
106127
*/
107-
public HttpClient build() {
128+
@Override
129+
public AbstractHttpClient build() {
108130
requireNonNull(credential);
109131
requireNonNull(validator);
110132
okhttp3.OkHttpClient.Builder okHttpClientBuilder =

core/src/main/java/com/wechat/pay/java/core/notification/AutoCertificateNotificationConfig.java

+7
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,13 @@
1212
import com.wechat.pay.java.core.http.HttpClient;
1313
import java.nio.charset.StandardCharsets;
1414

15+
/**
16+
* 通知回调配置类
17+
*
18+
* @deprecated 请使用 RSAAutoCertificateConfig。 从版本 v0.2.4 起, 该类是多余的,而且功能不完整。
19+
* 开发者应尽快迁移。我们将在未来某个时间移除这段废弃的代码。
20+
*/
21+
@Deprecated
1522
public final class AutoCertificateNotificationConfig extends AbstractNotificationConfig {
1623

1724
private AutoCertificateNotificationConfig(

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

+35-2
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,14 @@
1818
import com.wechat.pay.java.core.certificate.model.DownloadCertificateResponse;
1919
import com.wechat.pay.java.core.certificate.model.EncryptCertificate;
2020
import com.wechat.pay.java.core.cipher.RSASigner;
21+
import com.wechat.pay.java.core.http.DefaultHttpClientBuilder;
2122
import com.wechat.pay.java.core.http.HttpClient;
2223
import com.wechat.pay.java.core.http.HttpHeaders;
2324
import com.wechat.pay.java.core.http.okhttp.OkHttpClientAdapter;
2425
import com.wechat.pay.java.core.util.GsonUtil;
2526
import com.wechat.pay.java.core.util.NonceUtil;
27+
import java.net.InetSocketAddress;
28+
import java.net.Proxy;
2629
import java.util.ArrayList;
2730
import java.util.stream.Stream;
2831
import okhttp3.MediaType;
@@ -31,13 +34,15 @@
3134
import okhttp3.Response;
3235
import okhttp3.ResponseBody;
3336
import org.junit.jupiter.api.BeforeAll;
37+
import org.junit.jupiter.api.Disabled;
3438
import org.junit.jupiter.api.Test;
3539
import org.junit.jupiter.params.ParameterizedTest;
3640
import org.junit.jupiter.params.provider.MethodSource;
3741

3842
class RSAAutoCertificateConfigTest implements ConfigTest {
3943

4044
static HttpClient httpClient;
45+
static OkHttpClient okHttpClient;
4146

4247
@BeforeAll
4348
static void initHttpClient() {
@@ -48,7 +53,7 @@ public <T> boolean validate(HttpHeaders responseHeaders, String body) {
4853
return true;
4954
}
5055
};
51-
OkHttpClient okHttpClient =
56+
okHttpClient =
5257
new OkHttpClient.Builder()
5358
.addInterceptor(
5459
chain -> {
@@ -121,7 +126,16 @@ static Stream<Builder> BuilderProvider() {
121126
.privateKeyFromPath(MERCHANT_PRIVATE_KEY_PATH)
122127
.merchantSerialNumber(MERCHANT_CERTIFICATE_SERIAL_NUMBER)
123128
.httpClient(httpClient)
124-
.apiV3Key(API_V3_KEY));
129+
.apiV3Key(API_V3_KEY),
130+
131+
// with http client builder
132+
new Builder()
133+
.merchantId("1123456")
134+
.privateKeyFromPath(MERCHANT_PRIVATE_KEY_PATH)
135+
.merchantSerialNumber(MERCHANT_CERTIFICATE_SERIAL_NUMBER)
136+
.apiV3Key(API_V3_KEY)
137+
.httpClientBuilder(
138+
new DefaultHttpClientBuilder().writeTimeoutMs(1000).okHttpClient(okHttpClient)));
125139
}
126140

127141
@Test
@@ -144,4 +158,23 @@ public Config createConfig() {
144158
.httpClient(httpClient)
145159
.build();
146160
}
161+
162+
@Disabled("only available in production environment")
163+
@Test
164+
void testAutoCertificateWithProxy() {
165+
DefaultHttpClientBuilder clientBuilder =
166+
new DefaultHttpClientBuilder()
167+
.proxy(new Proxy(Proxy.Type.HTTP, new InetSocketAddress("127.0.0.1", 12639)));
168+
169+
RSAAutoCertificateConfig config =
170+
new Builder()
171+
.merchantId("")
172+
.privateKey("")
173+
.merchantSerialNumber("")
174+
.httpClientBuilder(clientBuilder)
175+
.apiV3Key("")
176+
.build();
177+
178+
assertNotNull(config.createValidator());
179+
}
147180
}

core/src/test/java/com/wechat/pay/java/core/certificate/AbstractAutoCertificateProviderTest.java

-95
This file was deleted.

0 commit comments

Comments
 (0)