From 10b09ac4bbc4ca32d5e8315a51e7330cc9c7002b Mon Sep 17 00:00:00 2001 From: fourier Date: Tue, 4 Jul 2023 10:26:54 +0800 Subject: [PATCH 1/4] =?UTF-8?q?feat:=20=E7=94=B5=E5=95=86=E6=94=B6?= =?UTF-8?q?=E4=BB=98=E9=80=9A=E4=BA=8C=E7=BA=A7=E5=95=86=E6=88=B7=E8=BF=9B?= =?UTF-8?q?=E4=BB=B6=E6=8E=A5=E5=8F=A3=E8=81=94=E7=B3=BB=E4=BA=BA=E4=BF=A1?= =?UTF-8?q?=E6=81=AF=E5=A2=9E=E5=8A=A0=E5=AD=97=E6=AE=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../wechat/v3/model/ecommerce/EcommerceContactInfo.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/v3/model/ecommerce/EcommerceContactInfo.java b/payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/v3/model/ecommerce/EcommerceContactInfo.java index 8457f99..895f40a 100644 --- a/payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/v3/model/ecommerce/EcommerceContactInfo.java +++ b/payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/v3/model/ecommerce/EcommerceContactInfo.java @@ -17,13 +17,20 @@ package cn.felord.payment.wechat.v3.model.ecommerce; +import cn.felord.payment.wechat.enumeration.IdDocType; import lombok.Data; @Data public class EcommerceContactInfo { private String contactType; private String contactName; + private IdDocType contactIdDocType; private String contactIdCardNumber; + private String contactIdDocCopy; + private String contactIdDocCopyBack; + private String contactIdDocPeriodBegin; + private String contactIdDocPeriodEnd; + private String businessAuthorizationLetter; private String mobilePhone; private String contactEmail; } \ No newline at end of file -- Gitee From aaad20b78afe2d734cdbe5c13b2339f3c0bdd08a Mon Sep 17 00:00:00 2001 From: fourier Date: Tue, 4 Jul 2023 10:33:41 +0800 Subject: [PATCH 2/4] =?UTF-8?q?feat:=20=E7=94=B5=E5=95=86=E6=94=B6?= =?UTF-8?q?=E4=BB=98=E9=80=9A=E4=BA=8C=E7=BA=A7=E5=95=86=E6=88=B7=E8=BF=9B?= =?UTF-8?q?=E4=BB=B6=E6=8E=A5=E5=8F=A3=E8=81=94=E7=B3=BB=E4=BA=BA=E6=89=8B?= =?UTF-8?q?=E6=9C=BA=E5=8F=B7=E7=A0=81=E5=8A=A0=E5=AF=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/cn/felord/payment/wechat/v3/ecommerce/ApplymentApi.java | 1 + 1 file changed, 1 insertion(+) diff --git a/payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/v3/ecommerce/ApplymentApi.java b/payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/v3/ecommerce/ApplymentApi.java index 2b46e31..5c03e0f 100644 --- a/payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/v3/ecommerce/ApplymentApi.java +++ b/payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/v3/ecommerce/ApplymentApi.java @@ -178,6 +178,7 @@ public class ApplymentApi extends AbstractApi { EcommerceContactInfo contactInfo = applymentParams.getContactInfo(); contactInfo.setContactName(signatureProvider.encryptRequestMessage(contactInfo.getContactName(), x509Certificate)); contactInfo.setContactIdCardNumber(signatureProvider.encryptRequestMessage(contactInfo.getContactIdCardNumber(), x509Certificate)); + contactInfo.setMobilePhone(signatureProvider.encryptRequestMessage(contactInfo.getMobilePhone(), x509Certificate)); String contactEmail = contactInfo.getContactEmail(); if (contactEmail != null) { contactInfo.setContactEmail(signatureProvider.encryptRequestMessage(contactEmail, x509Certificate)); -- Gitee From 41968541af828aa7dc16b5067446656b034ef9f9 Mon Sep 17 00:00:00 2001 From: dys <3276637414@qq.com> Date: Tue, 26 Dec 2023 14:21:07 +0800 Subject: [PATCH 3/4] =?UTF-8?q?=E5=8D=87=E7=BA=A7springboot3.2.1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- payment-spring-boot-autoconfigure/pom.xml | 4 +- .../payment/wechat/v2/model/BaseModel.java | 53 +++++++++++++------ .../payment/wechat/v3/SignatureProvider.java | 51 +++++++++++------- .../payment/wechat/v3/WechatDirectPayApi.java | 4 +- .../wechat/v3/WechatPartnerPayApi.java | 4 +- .../wechat/v3/WechatResponseEntity.java | 2 +- payment-spring-boot-starter/pom.xml | 4 +- pom.xml | 12 ++--- 8 files changed, 85 insertions(+), 49 deletions(-) diff --git a/payment-spring-boot-autoconfigure/pom.xml b/payment-spring-boot-autoconfigure/pom.xml index 89ed791..501757e 100644 --- a/payment-spring-boot-autoconfigure/pom.xml +++ b/payment-spring-boot-autoconfigure/pom.xml @@ -74,8 +74,8 @@ alipay-sdk-java - org.apache.httpcomponents - httpclient + org.apache.httpcomponents.client5 + httpclient5 provided diff --git a/payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/v2/model/BaseModel.java b/payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/v2/model/BaseModel.java index f5ceb41..260f78a 100644 --- a/payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/v2/model/BaseModel.java +++ b/payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/v2/model/BaseModel.java @@ -28,11 +28,18 @@ import com.fasterxml.jackson.databind.PropertyNamingStrategy; import com.fasterxml.jackson.dataformat.xml.XmlMapper; import lombok.Getter; import lombok.SneakyThrows; -import org.apache.http.conn.ssl.NoopHostnameVerifier; -import org.apache.http.conn.ssl.SSLConnectionSocketFactory; -import org.apache.http.impl.client.CloseableHttpClient; -import org.apache.http.impl.client.HttpClients; -import org.apache.http.ssl.SSLContextBuilder; +import org.apache.hc.client5.http.config.ConnectionConfig; +import org.apache.hc.client5.http.impl.classic.CloseableHttpClient; +import org.apache.hc.client5.http.impl.classic.HttpClients; +import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManager; +import org.apache.hc.client5.http.socket.ConnectionSocketFactory; +import org.apache.hc.client5.http.socket.PlainConnectionSocketFactory; +import org.apache.hc.client5.http.ssl.NoopHostnameVerifier; +import org.apache.hc.client5.http.ssl.SSLConnectionSocketFactory; +import org.apache.hc.core5.http.config.Registry; +import org.apache.hc.core5.http.config.RegistryBuilder; +import org.apache.hc.core5.ssl.SSLContextBuilder; +import org.apache.hc.core5.util.TimeValue; import org.bouncycastle.crypto.Digest; import org.bouncycastle.crypto.digests.MD5Digest; import org.bouncycastle.util.encoders.Hex; @@ -56,11 +63,7 @@ import javax.net.ssl.HostnameVerifier; import javax.net.ssl.SSLContext; import java.io.IOException; import java.nio.charset.StandardCharsets; -import java.security.KeyManagementException; -import java.security.KeyStore; -import java.security.KeyStoreException; -import java.security.NoSuchAlgorithmException; -import java.security.UnrecoverableKeyException; +import java.security.*; import java.security.cert.CertificateException; import java.util.TreeMap; import java.util.stream.Collectors; @@ -73,7 +76,7 @@ import java.util.stream.Collectors; */ @Getter public abstract class BaseModel { - public static final String HMAC_SHA256="HMAC-SHA256"; + public static final String HMAC_SHA256 = "HMAC-SHA256"; private static final XmlMapper XML_MAPPER = new XmlMapper(); private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper(); @@ -165,7 +168,7 @@ public abstract class BaseModel { @SneakyThrows private String hmacSha256(String src) { String algorithm = "HmacSHA256"; - Mac sha256HMAC = Mac.getInstance(algorithm,"BC"); + Mac sha256HMAC = Mac.getInstance(algorithm, "BC"); SecretKeySpec secretKeySpec = new SecretKeySpec(appSecret.getBytes(), algorithm); sha256HMAC.init(secretKeySpec); byte[] bytes = sha256HMAC.doFinal(src.getBytes(StandardCharsets.UTF_8)); @@ -182,7 +185,7 @@ public abstract class BaseModel { @SneakyThrows private String link(T t) { Assert.hasText(appSecret, "wechat pay appSecret is required"); - String json = OBJECT_MAPPER + String json = OBJECT_MAPPER .writeValueAsString(t); TreeMap map = OBJECT_MAPPER.readValue(json, new TypeReference>() { @@ -200,8 +203,8 @@ public abstract class BaseModel { public JsonNode request(String mchId, HttpMethod method, String url) { String xml = this.xml(); RequestEntity body = RequestEntity.method(method, UriComponentsBuilder.fromHttpUrl(url) - .build() - .toUri()) + .build() + .toUri()) .contentType(MediaType.valueOf("application/x-www-form-urlencoded;charset=UTF-8")) .body(xml); ResponseEntity responseEntity = this.getRestTemplateClientAuthentication(mchId) @@ -236,8 +239,26 @@ public abstract class BaseModel { SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslcontext, new String[]{"TLSv1"}, null, hostnameVerifier); + // 自定义 SSL 策略 + Registry registry = RegistryBuilder.create() + .register("http", PlainConnectionSocketFactory.getSocketFactory()) + .register("https", sslsf) + .build(); + // 设置连接池 + PoolingHttpClientConnectionManager connMgr = new PoolingHttpClientConnectionManager(registry); + // 设置连接池大小 + connMgr.setMaxTotal(100); + // 设置每条路由的最大并发连接数 + connMgr.setDefaultMaxPerRoute(connMgr.getMaxTotal()); + // 设置长连接 + connMgr.setDefaultConnectionConfig( + ConnectionConfig.custom() + .setValidateAfterInactivity(TimeValue.ofSeconds(600)) + .build() + ); + CloseableHttpClient httpclient = HttpClients.custom() - .setSSLSocketFactory(sslsf) + .setConnectionManager(connMgr) .build(); HttpComponentsClientHttpRequestFactory clientHttpRequestFactory = new HttpComponentsClientHttpRequestFactory(httpclient); return new RestTemplate(clientHttpRequestFactory); diff --git a/payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/v3/SignatureProvider.java b/payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/v3/SignatureProvider.java index c683574..24407ec 100644 --- a/payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/v3/SignatureProvider.java +++ b/payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/v3/SignatureProvider.java @@ -32,7 +32,6 @@ import org.springframework.http.converter.HttpMessageConverter; import org.springframework.http.converter.xml.MappingJackson2XmlHttpMessageConverter; import org.springframework.util.AlternativeJdkIdGenerator; import org.springframework.util.Assert; -import org.springframework.util.Base64Utils; import org.springframework.util.IdGenerator; import org.springframework.web.client.RestOperations; import org.springframework.web.client.RestTemplate; @@ -161,7 +160,10 @@ public class SignatureProvider { signer.initSign(privateKey); final String signatureStr = createSign(orderedComponents); signer.update(signatureStr.getBytes(StandardCharsets.UTF_8)); - return Base64Utils.encodeToString(signer.sign()); + if (signer.sign().length == 0) { + return ""; + } + return Base64.getEncoder().encodeToString(signer.sign()); } /** @@ -184,15 +186,21 @@ public class SignatureProvider { .orElseThrow(() -> new PayException("cannot obtain the certificate")); }); - try { - final String signatureStr = createSign(params.getWechatpayTimestamp(), params.getWechatpayNonce(), params.getBody()); - Signature signer = Signature.getInstance("SHA256withRSA", BC_PROVIDER); - signer.initVerify(certificate.getX509Certificate()); - signer.update(signatureStr.getBytes(StandardCharsets.UTF_8)); - return signer.verify(Base64Utils.decodeFromString(params.getWechatpaySignature())); - }catch (Exception e){ - throw new PayException("An exception occurred during the response verification, the cause: "+e.getMessage()); - } + try { + final String signatureStr = createSign(params.getWechatpayTimestamp(), params.getWechatpayNonce(), params.getBody()); + Signature signer = Signature.getInstance("SHA256withRSA", BC_PROVIDER); + signer.initVerify(certificate.getX509Certificate()); + signer.update(signatureStr.getBytes(StandardCharsets.UTF_8)); + byte[] bytes; + if (params.getWechatpaySignature().isEmpty()) { + bytes = new byte[0]; + } else { + bytes = Base64.getDecoder().decode(params.getWechatpaySignature()); + } + return signer.verify(bytes); + } catch (Exception e) { + throw new PayException("An exception occurred during the response verification, the cause: " + e.getMessage()); + } } @@ -290,10 +298,10 @@ public class SignatureProvider { cipher.updateAAD(associatedData.getBytes(StandardCharsets.UTF_8)); byte[] bytes; - try { - bytes = cipher.doFinal(Base64Utils.decodeFromString(ciphertext)); - } catch (GeneralSecurityException e) { - throw new PayException(e); + if (ciphertext.isEmpty()) { + bytes = new byte[0]; + } else { + bytes = Base64.getDecoder().decode(ciphertext); } return new String(bytes, StandardCharsets.UTF_8); } catch (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException | @@ -317,8 +325,10 @@ public class SignatureProvider { byte[] data = message.getBytes(StandardCharsets.UTF_8); byte[] cipherData = cipher.doFinal(data); - return Base64Utils.encodeToString(cipherData); - + if (cipherData.length == 0) { + return ""; + } + return Base64.getEncoder().encodeToString(cipherData); } catch (Exception e) { throw new PayException(e); } @@ -338,7 +348,12 @@ public class SignatureProvider { PrivateKey privateKey = wechatMetaBean.getKeyPair().getPrivate(); Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPWithSHA-1AndMGF1Padding", BC_PROVIDER); cipher.init(Cipher.DECRYPT_MODE, privateKey); - byte[] data = Base64Utils.decodeFromString(message); + byte[] data; + if (message.isEmpty()) { + data = new byte[0]; + } else { + data = Base64.getDecoder().decode(message); + } byte[] cipherData = cipher.doFinal(data); return new String(cipherData, StandardCharsets.UTF_8); diff --git a/payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/v3/WechatDirectPayApi.java b/payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/v3/WechatDirectPayApi.java index 3814f6a..2bc996e 100644 --- a/payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/v3/WechatDirectPayApi.java +++ b/payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/v3/WechatDirectPayApi.java @@ -98,7 +98,7 @@ public class WechatDirectPayApi extends AbstractApi { body.put("signType", "RSA"); body.put("paySign", paySign); - wechatResponseEntity.setHttpStatus(responseEntity.getStatusCodeValue()); + wechatResponseEntity.setHttpStatus(responseEntity.getStatusCode().value()); wechatResponseEntity.setBody(body); }) .request(); @@ -144,7 +144,7 @@ public class WechatDirectPayApi extends AbstractApi { body.put("signType", "RSA"); body.put("paySign", paySign); - wechatResponseEntity.setHttpStatus(responseEntity.getStatusCodeValue()); + wechatResponseEntity.setHttpStatus(responseEntity.getStatusCode().value()); wechatResponseEntity.setBody(body); }) .request(); diff --git a/payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/v3/WechatPartnerPayApi.java b/payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/v3/WechatPartnerPayApi.java index c8c0d68..95baac7 100644 --- a/payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/v3/WechatPartnerPayApi.java +++ b/payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/v3/WechatPartnerPayApi.java @@ -99,7 +99,7 @@ public class WechatPartnerPayApi extends AbstractApi { body.put("signType", "RSA"); body.put("paySign", paySign); - wechatResponseEntity.setHttpStatus(responseEntity.getStatusCodeValue()); + wechatResponseEntity.setHttpStatus(responseEntity.getStatusCode().value()); wechatResponseEntity.setBody(body); }) .request(); @@ -145,7 +145,7 @@ public class WechatPartnerPayApi extends AbstractApi { body.put("signType", "RSA"); body.put("paySign", paySign); - wechatResponseEntity.setHttpStatus(responseEntity.getStatusCodeValue()); + wechatResponseEntity.setHttpStatus(responseEntity.getStatusCode().value()); wechatResponseEntity.setBody(body); }) .request(); diff --git a/payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/v3/WechatResponseEntity.java b/payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/v3/WechatResponseEntity.java index 7be553e..e145d6d 100644 --- a/payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/v3/WechatResponseEntity.java +++ b/payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/v3/WechatResponseEntity.java @@ -53,7 +53,7 @@ public class WechatResponseEntity { log.debug("wechat response {}", responseEntity); } if (Objects.nonNull(responseEntity)) { - this.httpStatus = responseEntity.getStatusCodeValue(); + this.httpStatus = responseEntity.getStatusCode().value(); this.body = responseEntity.getBody(); } else { this.httpStatus = HttpStatus.REQUEST_TIMEOUT.value(); diff --git a/payment-spring-boot-starter/pom.xml b/payment-spring-boot-starter/pom.xml index f593105..dd95438 100644 --- a/payment-spring-boot-starter/pom.xml +++ b/payment-spring-boot-starter/pom.xml @@ -53,8 +53,8 @@ bcprov-jdk15to18 - org.apache.httpcomponents - httpclient + org.apache.httpcomponents.client5 + httpclient5 com.fasterxml.jackson.dataformat diff --git a/pom.xml b/pom.xml index 448adcb..381ae11 100644 --- a/pom.xml +++ b/pom.xml @@ -83,14 +83,14 @@ - 1.8 - 1.8 + 17 + 17 UTF-8 UTF-8 - 1.8 - 2.7.7 - 4.31.7.ALL - 1.69 + 17 + 3.2.1 + 4.38.170.ALL + 1.74 -- Gitee From 6054df87c177059a92306ec9d4996684897e84c6 Mon Sep 17 00:00:00 2001 From: dys <3276637414@qq.com> Date: Tue, 26 Dec 2023 14:28:35 +0800 Subject: [PATCH 4/4] =?UTF-8?q?=E5=8D=87=E7=BA=A7springboot3.2.1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/cn/felord/payment/wechat/v3/WechatPayClient.java | 6 +++--- pom.xml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/v3/WechatPayClient.java b/payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/v3/WechatPayClient.java index 6c987ba..889a5da 100644 --- a/payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/v3/WechatPayClient.java +++ b/payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/v3/WechatPayClient.java @@ -252,7 +252,7 @@ public class WechatPayClient { ResponseEntity responseEntity = restOperations.exchange(requestEntity, ObjectNode.class); HttpHeaders headers = responseEntity.getHeaders(); ObjectNode body = responseEntity.getBody(); - HttpStatus statusCode = responseEntity.getStatusCode(); + HttpStatusCode statusCode = responseEntity.getStatusCode(); // 微信请求id String requestId = headers.getFirst("Request-ID"); if (!statusCode.is2xxSuccessful()) { @@ -298,7 +298,7 @@ public class WechatPayClient { ResponseEntity responseEntity = restOperations.exchange(requestEntity, String.class); - HttpStatus statusCode = responseEntity.getStatusCode(); + HttpStatusCode statusCode = responseEntity.getStatusCode(); // 微信请求id String requestId = requestEntity.getHeaders().getFirst("Request-ID"); if (!statusCode.is2xxSuccessful()) { @@ -322,7 +322,7 @@ public class WechatPayClient { ResponseEntity responseEntity = restOperations.exchange(requestEntity, Resource.class); - HttpStatus statusCode = responseEntity.getStatusCode(); + HttpStatusCode statusCode = responseEntity.getStatusCode(); // 微信请求id String requestId = requestEntity.getHeaders().getFirst("Request-ID"); if (!statusCode.is2xxSuccessful()) { diff --git a/pom.xml b/pom.xml index 381ae11..17caded 100644 --- a/pom.xml +++ b/pom.xml @@ -88,7 +88,7 @@ UTF-8 UTF-8 17 - 3.2.1 + 3.2.0 4.38.170.ALL 1.74 -- Gitee