|
@@ -1,8 +1,22 @@
|
|
|
package com.github.binarywang.wxpay.v3.auth;
|
|
|
|
|
|
+import com.fasterxml.jackson.databind.JsonNode;
|
|
|
+import com.fasterxml.jackson.databind.ObjectMapper;
|
|
|
+import com.github.binarywang.wxpay.v3.Credentials;
|
|
|
+import com.github.binarywang.wxpay.v3.WechatPayHttpClientBuilder;
|
|
|
+import com.github.binarywang.wxpay.v3.util.AesUtils;
|
|
|
+import com.github.binarywang.wxpay.v3.util.PemUtils;
|
|
|
+import lombok.Getter;
|
|
|
+import lombok.RequiredArgsConstructor;
|
|
|
+import lombok.extern.slf4j.Slf4j;
|
|
|
+import org.apache.http.client.methods.CloseableHttpResponse;
|
|
|
+import org.apache.http.client.methods.HttpGet;
|
|
|
+import org.apache.http.impl.client.CloseableHttpClient;
|
|
|
+import org.apache.http.util.EntityUtils;
|
|
|
|
|
|
import java.io.ByteArrayInputStream;
|
|
|
import java.io.IOException;
|
|
|
+import java.nio.charset.StandardCharsets;
|
|
|
import java.security.GeneralSecurityException;
|
|
|
import java.security.cert.CertificateExpiredException;
|
|
|
import java.security.cert.CertificateNotYetValidException;
|
|
@@ -13,57 +27,56 @@ import java.util.ArrayList;
|
|
|
import java.util.List;
|
|
|
import java.util.concurrent.locks.ReentrantLock;
|
|
|
|
|
|
-import com.fasterxml.jackson.databind.JsonNode;
|
|
|
-import com.fasterxml.jackson.databind.ObjectMapper;
|
|
|
-import com.github.binarywang.wxpay.v3.Credentials;
|
|
|
-import com.github.binarywang.wxpay.v3.WechatPayHttpClientBuilder;
|
|
|
-import com.github.binarywang.wxpay.v3.util.AesUtils;
|
|
|
-import com.github.binarywang.wxpay.v3.util.PemUtils;
|
|
|
-import org.apache.http.client.methods.CloseableHttpResponse;
|
|
|
-import org.apache.http.client.methods.HttpGet;
|
|
|
-import org.apache.http.impl.client.CloseableHttpClient;
|
|
|
-import org.apache.http.util.EntityUtils;
|
|
|
-
|
|
|
-import org.slf4j.Logger;
|
|
|
-import org.slf4j.LoggerFactory;
|
|
|
-
|
|
|
/**
|
|
|
* 在原有CertificatesVerifier基础上,增加自动更新证书功能
|
|
|
+ *
|
|
|
+ * @author doger.wang
|
|
|
*/
|
|
|
+@Slf4j
|
|
|
public class AutoUpdateCertificatesVerifier implements Verifier {
|
|
|
+ /**
|
|
|
+ * 证书下载地址
|
|
|
+ */
|
|
|
+ private static final String CERT_DOWNLOAD_PATH = "https://api.mch.weixin.qq.com/v3/certificates";
|
|
|
|
|
|
- private static final Logger log = LoggerFactory.getLogger(AutoUpdateCertificatesVerifier.class);
|
|
|
-
|
|
|
- //证书下载地址
|
|
|
- private static final String CertDownloadPath = "https://api.mch.weixin.qq.com/v3/certificates";
|
|
|
-
|
|
|
- //上次更新时间
|
|
|
+ /**
|
|
|
+ * 上次更新时间
|
|
|
+ */
|
|
|
private volatile Instant instant;
|
|
|
|
|
|
- //证书更新间隔时间,单位为分钟
|
|
|
- private int minutesInterval;
|
|
|
+ /**
|
|
|
+ * 证书更新间隔时间,单位为分钟
|
|
|
+ */
|
|
|
+ private final int minutesInterval;
|
|
|
|
|
|
private CertificatesVerifier verifier;
|
|
|
|
|
|
- private Credentials credentials;
|
|
|
+ private final Credentials credentials;
|
|
|
|
|
|
- private byte[] apiV3Key;
|
|
|
+ private final byte[] apiV3Key;
|
|
|
|
|
|
- private ReentrantLock lock = new ReentrantLock();
|
|
|
+ private final ReentrantLock lock = new ReentrantLock();
|
|
|
|
|
|
- //时间间隔枚举,支持一小时、六小时以及十二小时
|
|
|
+ /**
|
|
|
+ * 时间间隔枚举,支持一小时、六小时以及十二小时
|
|
|
+ */
|
|
|
+ @Getter
|
|
|
+ @RequiredArgsConstructor
|
|
|
public enum TimeInterval {
|
|
|
- OneHour(60), SixHours(60 * 6), TwelveHours(60 * 12);
|
|
|
-
|
|
|
- private int minutes;
|
|
|
-
|
|
|
- TimeInterval(int minutes) {
|
|
|
- this.minutes = minutes;
|
|
|
- }
|
|
|
-
|
|
|
- public int getMinutes() {
|
|
|
- return minutes;
|
|
|
- }
|
|
|
+ /**
|
|
|
+ * 一小时
|
|
|
+ */
|
|
|
+ OneHour(60),
|
|
|
+ /**
|
|
|
+ * 六小时
|
|
|
+ */
|
|
|
+ SixHours(60 * 6),
|
|
|
+ /**
|
|
|
+ * 十二小时
|
|
|
+ */
|
|
|
+ TwelveHours(60 * 12);
|
|
|
+
|
|
|
+ private final int minutes;
|
|
|
}
|
|
|
|
|
|
public AutoUpdateCertificatesVerifier(Credentials credentials, byte[] apiV3Key) {
|
|
@@ -103,11 +116,11 @@ public class AutoUpdateCertificatesVerifier implements Verifier {
|
|
|
|
|
|
private void autoUpdateCert() throws IOException, GeneralSecurityException {
|
|
|
CloseableHttpClient httpClient = WechatPayHttpClientBuilder.create()
|
|
|
- .withCredentials(credentials)
|
|
|
- .withValidator(verifier == null ? (response) -> true : new WechatPay2Validator(verifier))
|
|
|
- .build();
|
|
|
+ .withCredentials(credentials)
|
|
|
+ .withValidator(verifier == null ? (response) -> true : new WechatPay2Validator(verifier))
|
|
|
+ .build();
|
|
|
|
|
|
- HttpGet httpGet = new HttpGet(CertDownloadPath);
|
|
|
+ HttpGet httpGet = new HttpGet(CERT_DOWNLOAD_PATH);
|
|
|
httpGet.addHeader("Accept", "application/json");
|
|
|
|
|
|
CloseableHttpResponse response = httpClient.execute(httpGet);
|
|
@@ -125,12 +138,10 @@ public class AutoUpdateCertificatesVerifier implements Verifier {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-
|
|
|
/**
|
|
|
* 反序列化证书并解密
|
|
|
*/
|
|
|
- private List<X509Certificate> deserializeToCerts(byte[] apiV3Key, String body)
|
|
|
- throws GeneralSecurityException, IOException {
|
|
|
+ private List<X509Certificate> deserializeToCerts(byte[] apiV3Key, String body) throws GeneralSecurityException, IOException {
|
|
|
AesUtils decryptor = new AesUtils(apiV3Key);
|
|
|
ObjectMapper mapper = new ObjectMapper();
|
|
|
JsonNode dataNode = mapper.readTree(body).get("data");
|
|
@@ -140,14 +151,14 @@ public class AutoUpdateCertificatesVerifier implements Verifier {
|
|
|
JsonNode encryptCertificateNode = dataNode.get(i).get("encrypt_certificate");
|
|
|
//解密
|
|
|
String cert = decryptor.decryptToString(
|
|
|
- encryptCertificateNode.get("associated_data").toString().replaceAll("\"", "")
|
|
|
- .getBytes("utf-8"),
|
|
|
- encryptCertificateNode.get("nonce").toString().replaceAll("\"", "")
|
|
|
- .getBytes("utf-8"),
|
|
|
- encryptCertificateNode.get("ciphertext").toString().replaceAll("\"", ""));
|
|
|
+ encryptCertificateNode.get("associated_data").toString().replaceAll("\"", "")
|
|
|
+ .getBytes(StandardCharsets.UTF_8),
|
|
|
+ encryptCertificateNode.get("nonce").toString().replaceAll("\"", "")
|
|
|
+ .getBytes(StandardCharsets.UTF_8),
|
|
|
+ encryptCertificateNode.get("ciphertext").toString().replaceAll("\"", ""));
|
|
|
|
|
|
X509Certificate x509Cert = PemUtils
|
|
|
- .loadCertificate(new ByteArrayInputStream(cert.getBytes("utf-8")));
|
|
|
+ .loadCertificate(new ByteArrayInputStream(cert.getBytes(StandardCharsets.UTF_8)));
|
|
|
try {
|
|
|
x509Cert.checkValidity();
|
|
|
} catch (CertificateExpiredException | CertificateNotYetValidException e) {
|
|
@@ -156,6 +167,7 @@ public class AutoUpdateCertificatesVerifier implements Verifier {
|
|
|
newCertList.add(x509Cert);
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
return newCertList;
|
|
|
}
|
|
|
}
|