1010import com .wechat .pay .contrib .apache .httpclient .auth .WechatPay2Validator ;
1111import com .wechat .pay .contrib .apache .httpclient .exception .HttpCodeException ;
1212import com .wechat .pay .contrib .apache .httpclient .exception .NotFoundException ;
13+ import com .wechat .pay .contrib .apache .httpclient .proxy .HttpProxyFactory ;
1314import com .wechat .pay .contrib .apache .httpclient .util .CertSerializeUtil ;
1415import java .io .IOException ;
1516import java .math .BigInteger ;
2526import java .util .Base64 ;
2627import java .util .Map ;
2728import java .util .NoSuchElementException ;
29+ import java .util .Objects ;
2830import java .util .concurrent .ConcurrentHashMap ;
2931import java .util .concurrent .ScheduledExecutorService ;
3032import java .util .concurrent .TimeUnit ;
33+ import org .apache .http .HttpHost ;
3134import org .apache .http .client .methods .CloseableHttpResponse ;
3235import org .apache .http .client .methods .HttpGet ;
3336import org .apache .http .impl .client .CloseableHttpClient ;
3437import org .apache .http .util .EntityUtils ;
35- import org .apache .http .HttpHost ;
3638import org .slf4j .Logger ;
3739import org .slf4j .LoggerFactory ;
3840
4446 */
4547public class CertificatesManager {
4648
47- private static final Logger log = LoggerFactory .getLogger (CertificatesManager .class );
4849 protected static final int UPDATE_INTERVAL_MINUTE = 1440 ;
50+ private static final Logger log = LoggerFactory .getLogger (CertificatesManager .class );
4951 /**
5052 * 证书下载地址
5153 */
@@ -54,65 +56,18 @@ public class CertificatesManager {
5456 private volatile static CertificatesManager instance = null ;
5557 private ConcurrentHashMap <String , byte []> apiV3Keys = new ConcurrentHashMap <>();
5658
59+ private HttpProxyFactory proxyFactory ;
5760 private HttpHost proxy ;
5861
59- private ConcurrentHashMap <String , ConcurrentHashMap <BigInteger , X509Certificate >> certificates = new ConcurrentHashMap <>();
62+ private ConcurrentHashMap <String , ConcurrentHashMap <BigInteger , X509Certificate >> certificates =
63+ new ConcurrentHashMap <>();
6064
6165 private ConcurrentHashMap <String , Credentials > credentialsMap = new ConcurrentHashMap <>();
6266 /**
6367 * 执行定时更新平台证书的线程池
6468 */
6569 private ScheduledExecutorService executor ;
6670
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-
11671 private CertificatesManager () {
11772 }
11873
@@ -162,14 +117,27 @@ public synchronized void putMerchant(String merchantId, Credentials credentials,
162117 }
163118
164119 /***
165- * 代理配置
166- *
167- * @param proxy 代理host
168- **/
120+ * 代理配置
121+ *
122+ * @param proxy 代理host
123+ **/
169124 public synchronized void setProxy (HttpHost proxy ) {
170125 this .proxy = proxy ;
171126 }
172127
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+
173141 /**
174142 * 停止自动更新平台证书,停止后无法再重新启动
175143 */
@@ -236,7 +204,6 @@ public Verifier getVerifier(String merchantId) throws NotFoundException {
236204 return new DefaultVerifier (merchantId );
237205 }
238206
239-
240207 private void beginScheduleUpdate () {
241208 executor = new SafeSingleScheduleExecutor ();
242209 Runnable runnable = () -> {
@@ -265,6 +232,7 @@ private void beginScheduleUpdate() {
265232 */
266233 private synchronized void downloadAndUpdateCert (String merchantId , Verifier verifier , Credentials credentials ,
267234 byte [] apiV3Key ) throws HttpCodeException , IOException , GeneralSecurityException {
235+ proxy = resolveProxy ();
268236 try (CloseableHttpClient httpClient = WechatPayHttpClientBuilder .create ()
269237 .withCredentials (credentials )
270238 .withValidator (verifier == null ? (response ) -> true
@@ -324,4 +292,53 @@ private void updateCertificates() {
324292 }
325293 }
326294 }
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+ }
327344}
0 commit comments