@@ -232,6 +232,11 @@ public class WxPayConfig {
232
232
*/
233
233
private boolean strictlyNeedWechatPaySerial = false ;
234
234
235
+ /**
236
+ * 是否完全使用公钥模式(用以微信从平台证书到公钥的灰度切换),默认不使用
237
+ */
238
+ private boolean fullPublicKeyModel = false ;
239
+
235
240
/**
236
241
* 返回所设置的微信支付接口请求地址域名.
237
242
*
@@ -289,48 +294,76 @@ public CloseableHttpClient initApiV3HttpClient() throws WxPayException {
289
294
if (StringUtils .isBlank (this .getApiV3Key ())) {
290
295
throw new WxPayException ("请确保apiV3Key值已设置" );
291
296
}
292
-
293
- // 尝试从p12证书中加载私钥和证书
294
- PrivateKey merchantPrivateKey = null ;
295
- X509Certificate certificate = null ;
296
- Object [] objects = this .p12ToPem ();
297
- if (objects != null ) {
298
- merchantPrivateKey = (PrivateKey ) objects [0 ];
299
- certificate = (X509Certificate ) objects [1 ];
300
- this .certSerialNo = certificate .getSerialNumber ().toString (16 ).toUpperCase ();
301
- }
302
297
try {
303
- if (merchantPrivateKey == null && StringUtils .isNotBlank (this .getPrivateKeyPath ())) {
304
- try (InputStream keyInputStream = this .loadConfigInputStream (this .getPrivateKeyString (), this .getPrivateKeyPath (),
305
- this .privateKeyContent , "privateKeyPath" )) {
306
- merchantPrivateKey = PemUtils .loadPrivateKey (keyInputStream );
298
+ PrivateKey merchantPrivateKey = null ;
299
+ PublicKey publicKey = null ;
300
+
301
+ // 使用完全公钥模式时,只加载公钥相关配置,避免下载平台证书使灰度切换无法达到100%覆盖
302
+ if (this .fullPublicKeyModel ) {
303
+ if (StringUtils .isBlank (this .getCertSerialNo ())) {
304
+ throw new WxPayException ("使用公钥模式时,请确保certSerialNo(apiV3证书序列号)值已设置" );
307
305
}
308
- }
309
- if (certificate == null && StringUtils .isBlank (this .getCertSerialNo ()) && StringUtils .isNotBlank (this .getPrivateCertPath ())) {
310
- try (InputStream certInputStream = this .loadConfigInputStream (this .getPrivateCertString (), this .getPrivateCertPath (),
311
- this .privateCertContent , "privateCertPath" )) {
312
- certificate = PemUtils .loadCertificate (certInputStream );
306
+ if (StringUtils .isBlank (this .getPublicKeyId ())) {
307
+ throw new WxPayException ("使用公钥模式时,请确保publicKeyId值已设置" );
313
308
}
314
- this .certSerialNo = certificate . getSerialNumber (). toString ( 16 ). toUpperCase ();
315
- }
316
- PublicKey publicKey = null ;
317
- if ( this . getPublicKeyString () != null || this . getPublicKeyPath () != null || this . publicKeyContent != null ) {
309
+ if ( StringUtils . isBlank ( this .getPublicKeyString ()) && StringUtils . isBlank ( this . getPublicKeyPath ()) && this . getPublicKeyContent () == null ) {
310
+ throw new WxPayException ( "使用公钥模式时,请确保publicKeyString/publicKeyPath/publicKeyContent其中一项值已设置" );
311
+ }
312
+
318
313
try (InputStream pubInputStream =
319
314
this .loadConfigInputStream (this .getPublicKeyString (), this .getPublicKeyPath (),
320
- this .publicKeyContent , "publicKeyPath" )) {
315
+ this .getPublicKeyContent () , "publicKeyPath" )) {
321
316
publicKey = PemUtils .loadPublicKey (pubInputStream );
322
317
}
318
+ } else {
319
+ // 不使用完全公钥模式时,同时兼容平台证书和公钥
320
+ X509Certificate certificate = null ;
321
+ // 尝试从p12证书中加载私钥和证书
322
+ Object [] objects = this .p12ToPem ();
323
+ if (objects != null ) {
324
+ merchantPrivateKey = (PrivateKey ) objects [0 ];
325
+ certificate = (X509Certificate ) objects [1 ];
326
+ this .certSerialNo = certificate .getSerialNumber ().toString (16 ).toUpperCase ();
327
+ }
328
+ if (certificate == null && StringUtils .isBlank (this .getCertSerialNo ()) && StringUtils .isNotBlank (this .getPrivateCertPath ())) {
329
+ try (InputStream certInputStream = this .loadConfigInputStream (this .getPrivateCertString (), this .getPrivateCertPath (),
330
+ this .privateCertContent , "privateCertPath" )) {
331
+ certificate = PemUtils .loadCertificate (certInputStream );
332
+ }
333
+ this .certSerialNo = certificate .getSerialNumber ().toString (16 ).toUpperCase ();
334
+ }
335
+ if (this .getPublicKeyString () != null || this .getPublicKeyPath () != null || this .publicKeyContent != null ) {
336
+ if (StringUtils .isBlank (this .getPublicKeyId ())) {
337
+ throw new WxPayException ("请确保和publicKeyId配套使用" );
338
+ }
339
+ try (InputStream pubInputStream =
340
+ this .loadConfigInputStream (this .getPublicKeyString (), this .getPublicKeyPath (),
341
+ this .publicKeyContent , "publicKeyPath" )) {
342
+ publicKey = PemUtils .loadPublicKey (pubInputStream );
343
+ }
344
+ }
345
+ }
346
+
347
+ // 加载api私钥
348
+ if (merchantPrivateKey == null && StringUtils .isNotBlank (this .getPrivateKeyPath ())) {
349
+ try (InputStream keyInputStream = this .loadConfigInputStream (this .getPrivateKeyString (), this .getPrivateKeyPath (),
350
+ this .privateKeyContent , "privateKeyPath" )) {
351
+ merchantPrivateKey = PemUtils .loadPrivateKey (keyInputStream );
352
+ }
323
353
}
324
354
325
355
//构造Http Proxy正向代理
326
356
WxPayHttpProxy wxPayHttpProxy = getWxPayHttpProxy ();
327
357
328
358
// 构造证书验签器
329
- Verifier certificatesVerifier = VerifierBuilder .build (
330
- this .getCertSerialNo (), this .getMchId (), this .getApiV3Key (), merchantPrivateKey , wxPayHttpProxy ,
331
- this .getCertAutoUpdateTime (), this .getPayBaseUrl (),
332
- this .getPublicKeyId (), publicKey
333
- );
359
+ Verifier certificatesVerifier ;
360
+ if (this .fullPublicKeyModel ) {
361
+ certificatesVerifier = VerifierBuilder .buildPublicCertVerifier (this .publicKeyId , publicKey );
362
+ } else {
363
+ certificatesVerifier = VerifierBuilder .build (
364
+ this .getCertSerialNo (), this .getMchId (), this .getApiV3Key (), merchantPrivateKey , wxPayHttpProxy ,
365
+ this .getCertAutoUpdateTime (), this .getPayBaseUrl (), this .getPublicKeyId (), publicKey );
366
+ }
334
367
335
368
WxPayV3HttpClientBuilder wxPayV3HttpClientBuilder = WxPayV3HttpClientBuilder .create ()
336
369
.withMerchant (mchId , certSerialNo , merchantPrivateKey )
0 commit comments