Skip to content

Commit

Permalink
自动下载证书支持代理 (#124)
Browse files Browse the repository at this point in the history
  • Loading branch information
xy-peng authored Feb 7, 2023
1 parent e9b5ee2 commit c25c725
Show file tree
Hide file tree
Showing 12 changed files with 304 additions and 125 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,8 @@

import com.wechat.pay.java.core.certificate.CertificateProvider;
import com.wechat.pay.java.core.certificate.RSAAutoCertificateProvider;
import com.wechat.pay.java.core.cipher.AeadAesCipher;
import com.wechat.pay.java.core.cipher.AeadCipher;
import com.wechat.pay.java.core.cipher.RSAVerifier;
import com.wechat.pay.java.core.cipher.Verifier;
import com.wechat.pay.java.core.cipher.*;
import com.wechat.pay.java.core.http.AbstractHttpClientBuilder;
import com.wechat.pay.java.core.http.HttpClient;
import com.wechat.pay.java.core.notification.NotificationConfig;
import java.nio.charset.StandardCharsets;
Expand Down Expand Up @@ -75,6 +73,7 @@ public static class Builder extends AbstractRSAConfigBuilder<Builder> {
protected HttpClient httpClient;
protected byte[] apiV3Key;
protected CertificateProvider certificateProvider;
protected AbstractHttpClientBuilder<?> httpClientBuilder;

public Builder apiV3Key(String apiV3key) {
this.apiV3Key = apiV3key.getBytes(StandardCharsets.UTF_8);
Expand All @@ -86,6 +85,11 @@ public Builder httpClient(HttpClient httpClient) {
return this;
}

public Builder httpClientBuilder(AbstractHttpClientBuilder<?> builder) {
httpClientBuilder = builder;
return this;
}

@Override
protected Builder self() {
return this;
Expand All @@ -98,10 +102,15 @@ public RSAAutoCertificateConfig build() {
.apiV3Key(requireNonNull(apiV3Key))
.privateKey(requireNonNull(privateKey))
.merchantSerialNumber(requireNonNull(merchantSerialNumber));

if (httpClient != null) {
providerBuilder.httpClient(httpClient);
}

if (httpClientBuilder != null) {
providerBuilder.httpClientBuilder(httpClientBuilder);
}

certificateProvider = providerBuilder.build();

return new RSAAutoCertificateConfig(this);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import com.wechat.pay.java.core.cipher.AeadAesCipher;
import com.wechat.pay.java.core.cipher.AeadCipher;
import com.wechat.pay.java.core.cipher.RSASigner;
import com.wechat.pay.java.core.http.AbstractHttpClientBuilder;
import com.wechat.pay.java.core.http.DefaultHttpClientBuilder;
import com.wechat.pay.java.core.http.HttpClient;
import com.wechat.pay.java.core.http.HttpHeaders;
Expand Down Expand Up @@ -45,6 +46,7 @@ public static class Builder {
private PrivateKey privateKey;
private String merchantSerialNumber;
private HttpClient httpClient;
private AbstractHttpClientBuilder<?> httpClientBuilder;

public Builder merchantId(String merchantId) {
this.merchantId = merchantId;
Expand Down Expand Up @@ -76,6 +78,12 @@ public Builder merchantSerialNumber(String merchantSerialNumber) {
return this;
}

public Builder httpClientBuilder(AbstractHttpClientBuilder<?> builder) {
// httpClientBuilder 不是不可变的,所以为了避免过程中修改入参或者值发生变化,这里制作了一个副本
this.httpClientBuilder = builder.newInstance();
return this;
}

private final Validator emptyValidator =
new Validator() {
@Override
Expand All @@ -86,15 +94,18 @@ public boolean validate(HttpHeaders responseHeaders, String body) {

public RSAAutoCertificateProvider build() {
if (httpClient == null) {
DefaultHttpClientBuilder httpClientBuilder =
new DefaultHttpClientBuilder().validator(emptyValidator);
if (credential == null) {
if (httpClientBuilder == null) {
httpClientBuilder = new DefaultHttpClientBuilder();
}

if (credential == null && privateKey != null) {
credential =
new WechatPay2Credential(
requireNonNull(merchantId),
new RSASigner(requireNonNull(merchantSerialNumber), requireNonNull(privateKey)));
new RSASigner(requireNonNull(merchantSerialNumber), privateKey));
}
httpClient = httpClientBuilder.credential(credential).build();

httpClient = httpClientBuilder.credential(credential).validator(emptyValidator).build();
}
return new RSAAutoCertificateProvider(
merchantId, new AeadAesCipher(requireNonNull(apiV3Key)), httpClient);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package com.wechat.pay.java.core.http;

import com.wechat.pay.java.core.auth.Credential;
import com.wechat.pay.java.core.auth.Validator;

public interface AbstractHttpClientBuilder<T extends AbstractHttpClientBuilder<T>> {

/**
* 复制工厂,复制一个当前对象
*
* @return 对象的副本
*/
T newInstance();

/**
* 设置验证器
*
* @param validator 验证器
* @return the AbstractHttpClientBuilder
*/
T validator(Validator validator);

/**
* 设置凭据生成器
*
* @param credential 凭据生成器
* @return the AbstractHttpClientBuilder
*/
T credential(Credential credential);

/**
* 构建 AbstractHttpClient
*
* @return AbstractHttpClient
*/
AbstractHttpClient build();
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@
import java.util.concurrent.TimeUnit;

/** 默认HttpClient构造器 */
public class DefaultHttpClientBuilder {
public class DefaultHttpClientBuilder
implements AbstractHttpClientBuilder<DefaultHttpClientBuilder> {

private Credential credential;
private Validator validator;
Expand All @@ -21,6 +22,24 @@ public class DefaultHttpClientBuilder {
private int connectTimeoutMs = -1;
private Proxy proxy;

/**
* 复制工厂,复制一个当前对象
*
* @return 对象的副本
*/
@Override
public DefaultHttpClientBuilder newInstance() {
DefaultHttpClientBuilder result = new DefaultHttpClientBuilder();
result.credential = this.credential;
result.validator = this.validator;
result.customizeOkHttpClient = this.customizeOkHttpClient;
result.readTimeoutMs = this.readTimeoutMs;
result.writeTimeoutMs = this.writeTimeoutMs;
result.connectTimeoutMs = this.connectTimeoutMs;
result.proxy = this.proxy;
return result;
}

/**
* 设置读超时
*
Expand Down Expand Up @@ -60,6 +79,7 @@ public DefaultHttpClientBuilder connectTimeoutMs(int connectTimeoutMs) {
* @param credential 凭据生成器
* @return defaultHttpClientBuilder
*/
@Override
public DefaultHttpClientBuilder credential(Credential credential) {
this.credential = credential;
return this;
Expand All @@ -71,6 +91,7 @@ public DefaultHttpClientBuilder credential(Credential credential) {
* @param validator 验证器
* @return defaultHttpClientBuilder
*/
@Override
public DefaultHttpClientBuilder validator(Validator validator) {
this.validator = validator;
return this;
Expand Down Expand Up @@ -104,7 +125,8 @@ public DefaultHttpClientBuilder proxy(Proxy proxy) {
*
* @return httpClient
*/
public HttpClient build() {
@Override
public AbstractHttpClient build() {
requireNonNull(credential);
requireNonNull(validator);
okhttp3.OkHttpClient.Builder okHttpClientBuilder =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,13 @@
import com.wechat.pay.java.core.http.HttpClient;
import java.nio.charset.StandardCharsets;

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

private AutoCertificateNotificationConfig(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,14 @@
import com.wechat.pay.java.core.certificate.model.DownloadCertificateResponse;
import com.wechat.pay.java.core.certificate.model.EncryptCertificate;
import com.wechat.pay.java.core.cipher.RSASigner;
import com.wechat.pay.java.core.http.DefaultHttpClientBuilder;
import com.wechat.pay.java.core.http.HttpClient;
import com.wechat.pay.java.core.http.HttpHeaders;
import com.wechat.pay.java.core.http.okhttp.OkHttpClientAdapter;
import com.wechat.pay.java.core.util.GsonUtil;
import com.wechat.pay.java.core.util.NonceUtil;
import java.net.InetSocketAddress;
import java.net.Proxy;
import java.util.ArrayList;
import java.util.stream.Stream;
import okhttp3.MediaType;
Expand All @@ -31,13 +34,15 @@
import okhttp3.Response;
import okhttp3.ResponseBody;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.MethodSource;

class RSAAutoCertificateConfigTest implements ConfigTest {

static HttpClient httpClient;
static OkHttpClient okHttpClient;

@BeforeAll
static void initHttpClient() {
Expand All @@ -48,7 +53,7 @@ public <T> boolean validate(HttpHeaders responseHeaders, String body) {
return true;
}
};
OkHttpClient okHttpClient =
okHttpClient =
new OkHttpClient.Builder()
.addInterceptor(
chain -> {
Expand Down Expand Up @@ -121,7 +126,16 @@ static Stream<Builder> BuilderProvider() {
.privateKeyFromPath(MERCHANT_PRIVATE_KEY_PATH)
.merchantSerialNumber(MERCHANT_CERTIFICATE_SERIAL_NUMBER)
.httpClient(httpClient)
.apiV3Key(API_V3_KEY));
.apiV3Key(API_V3_KEY),

// with http client builder
new Builder()
.merchantId("1123456")
.privateKeyFromPath(MERCHANT_PRIVATE_KEY_PATH)
.merchantSerialNumber(MERCHANT_CERTIFICATE_SERIAL_NUMBER)
.apiV3Key(API_V3_KEY)
.httpClientBuilder(
new DefaultHttpClientBuilder().writeTimeoutMs(1000).okHttpClient(okHttpClient)));
}

@Test
Expand All @@ -144,4 +158,23 @@ public Config createConfig() {
.httpClient(httpClient)
.build();
}

@Disabled("only available in production environment")
@Test
void testAutoCertificateWithProxy() {
DefaultHttpClientBuilder clientBuilder =
new DefaultHttpClientBuilder()
.proxy(new Proxy(Proxy.Type.HTTP, new InetSocketAddress("127.0.0.1", 12639)));

RSAAutoCertificateConfig config =
new Builder()
.merchantId("")
.privateKey("")
.merchantSerialNumber("")
.httpClientBuilder(clientBuilder)
.apiV3Key("")
.build();

assertNotNull(config.createValidator());
}
}

This file was deleted.

Loading

0 comments on commit c25c725

Please sign in to comment.