1
1
package com .github .binarywang .wxpay .v3 .auth ;
2
2
3
+ import com .fasterxml .jackson .databind .JsonNode ;
4
+ import com .fasterxml .jackson .databind .ObjectMapper ;
5
+ import com .github .binarywang .wxpay .v3 .Credentials ;
6
+ import com .github .binarywang .wxpay .v3 .WechatPayHttpClientBuilder ;
7
+ import com .github .binarywang .wxpay .v3 .util .AesUtils ;
8
+ import com .github .binarywang .wxpay .v3 .util .PemUtils ;
9
+ import lombok .Getter ;
10
+ import lombok .RequiredArgsConstructor ;
11
+ import lombok .extern .slf4j .Slf4j ;
12
+ import org .apache .http .client .methods .CloseableHttpResponse ;
13
+ import org .apache .http .client .methods .HttpGet ;
14
+ import org .apache .http .impl .client .CloseableHttpClient ;
15
+ import org .apache .http .util .EntityUtils ;
3
16
4
17
import java .io .ByteArrayInputStream ;
5
18
import java .io .IOException ;
19
+ import java .nio .charset .StandardCharsets ;
6
20
import java .security .GeneralSecurityException ;
7
21
import java .security .cert .CertificateExpiredException ;
8
22
import java .security .cert .CertificateNotYetValidException ;
13
27
import java .util .List ;
14
28
import java .util .concurrent .locks .ReentrantLock ;
15
29
16
- import com .fasterxml .jackson .databind .JsonNode ;
17
- import com .fasterxml .jackson .databind .ObjectMapper ;
18
- import com .github .binarywang .wxpay .v3 .Credentials ;
19
- import com .github .binarywang .wxpay .v3 .WechatPayHttpClientBuilder ;
20
- import com .github .binarywang .wxpay .v3 .util .AesUtils ;
21
- import com .github .binarywang .wxpay .v3 .util .PemUtils ;
22
- import org .apache .http .client .methods .CloseableHttpResponse ;
23
- import org .apache .http .client .methods .HttpGet ;
24
- import org .apache .http .impl .client .CloseableHttpClient ;
25
- import org .apache .http .util .EntityUtils ;
26
-
27
- import org .slf4j .Logger ;
28
- import org .slf4j .LoggerFactory ;
29
-
30
30
/**
31
31
* 在原有CertificatesVerifier基础上,增加自动更新证书功能
32
+ *
33
+ * @author doger.wang
32
34
*/
35
+ @ Slf4j
33
36
public class AutoUpdateCertificatesVerifier implements Verifier {
37
+ /**
38
+ * 证书下载地址
39
+ */
40
+ private static final String CERT_DOWNLOAD_PATH = "https://api.mch.weixin.qq.com/v3/certificates" ;
34
41
35
- private static final Logger log = LoggerFactory .getLogger (AutoUpdateCertificatesVerifier .class );
36
-
37
- //证书下载地址
38
- private static final String CertDownloadPath = "https://api.mch.weixin.qq.com/v3/certificates" ;
39
-
40
- //上次更新时间
42
+ /**
43
+ * 上次更新时间
44
+ */
41
45
private volatile Instant instant ;
42
46
43
- //证书更新间隔时间,单位为分钟
44
- private int minutesInterval ;
47
+ /**
48
+ * 证书更新间隔时间,单位为分钟
49
+ */
50
+ private final int minutesInterval ;
45
51
46
52
private CertificatesVerifier verifier ;
47
53
48
- private Credentials credentials ;
54
+ private final Credentials credentials ;
49
55
50
- private byte [] apiV3Key ;
56
+ private final byte [] apiV3Key ;
51
57
52
- private ReentrantLock lock = new ReentrantLock ();
58
+ private final ReentrantLock lock = new ReentrantLock ();
53
59
54
- //时间间隔枚举,支持一小时、六小时以及十二小时
60
+ /**
61
+ * 时间间隔枚举,支持一小时、六小时以及十二小时
62
+ */
63
+ @ Getter
64
+ @ RequiredArgsConstructor
55
65
public enum TimeInterval {
56
- OneHour (60 ), SixHours (60 * 6 ), TwelveHours (60 * 12 );
57
-
58
- private int minutes ;
59
-
60
- TimeInterval (int minutes ) {
61
- this .minutes = minutes ;
62
- }
63
-
64
- public int getMinutes () {
65
- return minutes ;
66
- }
66
+ /**
67
+ * 一小时
68
+ */
69
+ OneHour (60 ),
70
+ /**
71
+ * 六小时
72
+ */
73
+ SixHours (60 * 6 ),
74
+ /**
75
+ * 十二小时
76
+ */
77
+ TwelveHours (60 * 12 );
78
+
79
+ private final int minutes ;
67
80
}
68
81
69
82
public AutoUpdateCertificatesVerifier (Credentials credentials , byte [] apiV3Key ) {
@@ -103,11 +116,11 @@ public boolean verify(String serialNumber, byte[] message, String signature) {
103
116
104
117
private void autoUpdateCert () throws IOException , GeneralSecurityException {
105
118
CloseableHttpClient httpClient = WechatPayHttpClientBuilder .create ()
106
- .withCredentials (credentials )
107
- .withValidator (verifier == null ? (response ) -> true : new WechatPay2Validator (verifier ))
108
- .build ();
119
+ .withCredentials (credentials )
120
+ .withValidator (verifier == null ? (response ) -> true : new WechatPay2Validator (verifier ))
121
+ .build ();
109
122
110
- HttpGet httpGet = new HttpGet (CertDownloadPath );
123
+ HttpGet httpGet = new HttpGet (CERT_DOWNLOAD_PATH );
111
124
httpGet .addHeader ("Accept" , "application/json" );
112
125
113
126
CloseableHttpResponse response = httpClient .execute (httpGet );
@@ -125,12 +138,10 @@ private void autoUpdateCert() throws IOException, GeneralSecurityException {
125
138
}
126
139
}
127
140
128
-
129
141
/**
130
142
* 反序列化证书并解密
131
143
*/
132
- private List <X509Certificate > deserializeToCerts (byte [] apiV3Key , String body )
133
- throws GeneralSecurityException , IOException {
144
+ private List <X509Certificate > deserializeToCerts (byte [] apiV3Key , String body ) throws GeneralSecurityException , IOException {
134
145
AesUtils decryptor = new AesUtils (apiV3Key );
135
146
ObjectMapper mapper = new ObjectMapper ();
136
147
JsonNode dataNode = mapper .readTree (body ).get ("data" );
@@ -140,14 +151,14 @@ private List<X509Certificate> deserializeToCerts(byte[] apiV3Key, String body)
140
151
JsonNode encryptCertificateNode = dataNode .get (i ).get ("encrypt_certificate" );
141
152
//解密
142
153
String cert = decryptor .decryptToString (
143
- encryptCertificateNode .get ("associated_data" ).toString ().replaceAll ("\" " , "" )
144
- .getBytes ("utf-8" ),
145
- encryptCertificateNode .get ("nonce" ).toString ().replaceAll ("\" " , "" )
146
- .getBytes ("utf-8" ),
147
- encryptCertificateNode .get ("ciphertext" ).toString ().replaceAll ("\" " , "" ));
154
+ encryptCertificateNode .get ("associated_data" ).toString ().replaceAll ("\" " , "" )
155
+ .getBytes (StandardCharsets . UTF_8 ),
156
+ encryptCertificateNode .get ("nonce" ).toString ().replaceAll ("\" " , "" )
157
+ .getBytes (StandardCharsets . UTF_8 ),
158
+ encryptCertificateNode .get ("ciphertext" ).toString ().replaceAll ("\" " , "" ));
148
159
149
160
X509Certificate x509Cert = PemUtils
150
- .loadCertificate (new ByteArrayInputStream (cert .getBytes ("utf-8" )));
161
+ .loadCertificate (new ByteArrayInputStream (cert .getBytes (StandardCharsets . UTF_8 )));
151
162
try {
152
163
x509Cert .checkValidity ();
153
164
} catch (CertificateExpiredException | CertificateNotYetValidException e ) {
@@ -156,6 +167,7 @@ private List<X509Certificate> deserializeToCerts(byte[] apiV3Key, String body)
156
167
newCertList .add (x509Cert );
157
168
}
158
169
}
170
+
159
171
return newCertList ;
160
172
}
161
173
}
0 commit comments