10
10
import com .wechat .pay .contrib .apache .httpclient .auth .WechatPay2Validator ;
11
11
import com .wechat .pay .contrib .apache .httpclient .exception .HttpCodeException ;
12
12
import com .wechat .pay .contrib .apache .httpclient .exception .NotFoundException ;
13
+ import com .wechat .pay .contrib .apache .httpclient .proxy .HttpProxyFactory ;
13
14
import com .wechat .pay .contrib .apache .httpclient .util .CertSerializeUtil ;
14
15
import java .io .IOException ;
15
16
import java .math .BigInteger ;
25
26
import java .util .Base64 ;
26
27
import java .util .Map ;
27
28
import java .util .NoSuchElementException ;
29
+ import java .util .Objects ;
28
30
import java .util .concurrent .ConcurrentHashMap ;
29
31
import java .util .concurrent .ScheduledExecutorService ;
30
32
import java .util .concurrent .TimeUnit ;
33
+ import org .apache .http .HttpHost ;
31
34
import org .apache .http .client .methods .CloseableHttpResponse ;
32
35
import org .apache .http .client .methods .HttpGet ;
33
36
import org .apache .http .impl .client .CloseableHttpClient ;
34
37
import org .apache .http .util .EntityUtils ;
35
- import org .apache .http .HttpHost ;
36
38
import org .slf4j .Logger ;
37
39
import org .slf4j .LoggerFactory ;
38
40
44
46
*/
45
47
public class CertificatesManager {
46
48
47
- private static final Logger log = LoggerFactory .getLogger (CertificatesManager .class );
48
49
protected static final int UPDATE_INTERVAL_MINUTE = 1440 ;
50
+ private static final Logger log = LoggerFactory .getLogger (CertificatesManager .class );
49
51
/**
50
52
* 证书下载地址
51
53
*/
@@ -54,65 +56,18 @@ public class CertificatesManager {
54
56
private volatile static CertificatesManager instance = null ;
55
57
private ConcurrentHashMap <String , byte []> apiV3Keys = new ConcurrentHashMap <>();
56
58
59
+ private HttpProxyFactory proxyFactory ;
57
60
private HttpHost proxy ;
58
61
59
- private ConcurrentHashMap <String , ConcurrentHashMap <BigInteger , X509Certificate >> certificates = new ConcurrentHashMap <>();
62
+ private ConcurrentHashMap <String , ConcurrentHashMap <BigInteger , X509Certificate >> certificates =
63
+ new ConcurrentHashMap <>();
60
64
61
65
private ConcurrentHashMap <String , Credentials > credentialsMap = new ConcurrentHashMap <>();
62
66
/**
63
67
* 执行定时更新平台证书的线程池
64
68
*/
65
69
private ScheduledExecutorService executor ;
66
70
67
- /**
68
- * 内部验签器
69
- */
70
- private class DefaultVerifier implements Verifier {
71
-
72
- private String merchantId ;
73
-
74
- private DefaultVerifier (String merchantId ) {
75
- this .merchantId = merchantId ;
76
- }
77
-
78
- @ Override
79
- public boolean verify (String serialNumber , byte [] message , String signature ) {
80
- if (serialNumber .isEmpty () || message .length == 0 || signature .isEmpty ()) {
81
- throw new IllegalArgumentException ("serialNumber或message或signature为空" );
82
- }
83
- BigInteger serialNumber16Radix = new BigInteger (serialNumber , 16 );
84
- ConcurrentHashMap <BigInteger , X509Certificate > merchantCertificates = certificates .get (merchantId );
85
- X509Certificate certificate = merchantCertificates .get (serialNumber16Radix );
86
- if (certificate == null ) {
87
- log .error ("商户证书为空,serialNumber:{}" , serialNumber );
88
- return false ;
89
- }
90
- try {
91
- Signature sign = Signature .getInstance ("SHA256withRSA" );
92
- sign .initVerify (certificate );
93
- sign .update (message );
94
- return sign .verify (Base64 .getDecoder ().decode (signature ));
95
- } catch (NoSuchAlgorithmException e ) {
96
- throw new RuntimeException ("当前Java环境不支持SHA256withRSA" , e );
97
- } catch (SignatureException e ) {
98
- throw new RuntimeException ("签名验证过程发生了错误" , e );
99
- } catch (InvalidKeyException e ) {
100
- throw new RuntimeException ("无效的证书" , e );
101
- }
102
- }
103
-
104
- @ Override
105
- public X509Certificate getValidCertificate () {
106
- X509Certificate certificate ;
107
- try {
108
- certificate = CertificatesManager .this .getLatestCertificate (merchantId );
109
- } catch (NotFoundException e ) {
110
- throw new NoSuchElementException ("没有有效的微信支付平台证书" );
111
- }
112
- return certificate ;
113
- }
114
- }
115
-
116
71
private CertificatesManager () {
117
72
}
118
73
@@ -162,14 +117,27 @@ public synchronized void putMerchant(String merchantId, Credentials credentials,
162
117
}
163
118
164
119
/***
165
- * 代理配置
166
- *
167
- * @param proxy 代理host
168
- **/
120
+ * 代理配置
121
+ *
122
+ * @param proxy 代理host
123
+ **/
169
124
public synchronized void setProxy (HttpHost proxy ) {
170
125
this .proxy = proxy ;
171
126
}
172
127
128
+ /**
129
+ * 设置代理工厂
130
+ *
131
+ * @param proxyFactory 代理工厂
132
+ */
133
+ public synchronized void setProxyFactory (HttpProxyFactory proxyFactory ) {
134
+ this .proxyFactory = proxyFactory ;
135
+ }
136
+
137
+ public synchronized HttpHost resolveProxy () {
138
+ return Objects .nonNull (proxyFactory ) ? proxyFactory .buildHttpProxy () : proxy ;
139
+ }
140
+
173
141
/**
174
142
* 停止自动更新平台证书,停止后无法再重新启动
175
143
*/
@@ -236,7 +204,6 @@ public Verifier getVerifier(String merchantId) throws NotFoundException {
236
204
return new DefaultVerifier (merchantId );
237
205
}
238
206
239
-
240
207
private void beginScheduleUpdate () {
241
208
executor = new SafeSingleScheduleExecutor ();
242
209
Runnable runnable = () -> {
@@ -265,6 +232,7 @@ private void beginScheduleUpdate() {
265
232
*/
266
233
private synchronized void downloadAndUpdateCert (String merchantId , Verifier verifier , Credentials credentials ,
267
234
byte [] apiV3Key ) throws HttpCodeException , IOException , GeneralSecurityException {
235
+ proxy = resolveProxy ();
268
236
try (CloseableHttpClient httpClient = WechatPayHttpClientBuilder .create ()
269
237
.withCredentials (credentials )
270
238
.withValidator (verifier == null ? (response ) -> true
@@ -324,4 +292,53 @@ private void updateCertificates() {
324
292
}
325
293
}
326
294
}
295
+
296
+ /**
297
+ * 内部验签器
298
+ */
299
+ private class DefaultVerifier implements Verifier {
300
+
301
+ private String merchantId ;
302
+
303
+ private DefaultVerifier (String merchantId ) {
304
+ this .merchantId = merchantId ;
305
+ }
306
+
307
+ @ Override
308
+ public boolean verify (String serialNumber , byte [] message , String signature ) {
309
+ if (serialNumber .isEmpty () || message .length == 0 || signature .isEmpty ()) {
310
+ throw new IllegalArgumentException ("serialNumber或message或signature为空" );
311
+ }
312
+ BigInteger serialNumber16Radix = new BigInteger (serialNumber , 16 );
313
+ ConcurrentHashMap <BigInteger , X509Certificate > merchantCertificates = certificates .get (merchantId );
314
+ X509Certificate certificate = merchantCertificates .get (serialNumber16Radix );
315
+ if (certificate == null ) {
316
+ log .error ("商户证书为空,serialNumber:{}" , serialNumber );
317
+ return false ;
318
+ }
319
+ try {
320
+ Signature sign = Signature .getInstance ("SHA256withRSA" );
321
+ sign .initVerify (certificate );
322
+ sign .update (message );
323
+ return sign .verify (Base64 .getDecoder ().decode (signature ));
324
+ } catch (NoSuchAlgorithmException e ) {
325
+ throw new RuntimeException ("当前Java环境不支持SHA256withRSA" , e );
326
+ } catch (SignatureException e ) {
327
+ throw new RuntimeException ("签名验证过程发生了错误" , e );
328
+ } catch (InvalidKeyException e ) {
329
+ throw new RuntimeException ("无效的证书" , e );
330
+ }
331
+ }
332
+
333
+ @ Override
334
+ public X509Certificate getValidCertificate () {
335
+ X509Certificate certificate ;
336
+ try {
337
+ certificate = CertificatesManager .this .getLatestCertificate (merchantId );
338
+ } catch (NotFoundException e ) {
339
+ throw new NoSuchElementException ("没有有效的微信支付平台证书" );
340
+ }
341
+ return certificate ;
342
+ }
343
+ }
327
344
}
0 commit comments