diff --git a/README.md b/README.md
index f9c5b84..389688c 100644
--- a/README.md
+++ b/README.md
@@ -55,23 +55,23 @@ Starter,支持微信优惠券,代金券、商家券、智慧商圈、商家
## 文档地址
-- [payment-spring-boot GitHub文档](https://dromara.github.io/payment-spring-boot)
+- ~~[payment-spring-boot GitHub文档](https://dromara.github.io/payment-spring-boot) (暂时不可用)~~
## API清单
-目前已经实现绝大部分微信支付直连商户和服务商的接口,具体的API明细可查看[API清单](https://dromara.github.io/payment-spring-boot/#/wechat_v3_api)
+目前已经实现绝大部分微信支付直连商户和服务商的接口,具体的API明细可查看[API清单(暂时不可用)](https://dromara.github.io/payment-spring-boot/#/wechat_v3_api)
> 随着版本迭代功能会增加,也可通过API注册表类`WechatPayV3Type`进行API接口检索。
## CHANGELOG
-更新日志[CHANGELOG](https://dromara.github.io/payment-spring-boot/#/changelog)
+~~更新日志[CHANGELOG](https://dromara.github.io/payment-spring-boot/#/changelog) (暂时不可用)~~
## 使用入门
### 集成配置
-关于集成配置请详细阅读[payment-spring-boot GitHub文档](https://dromara.github.io/payment-spring-boot)
-中[快速接入](https://dromara.github.io/payment-spring-boot/#/quick_start)章节
+~~关于集成配置请详细阅读[payment-spring-boot GitHub文档](https://dromara.github.io/payment-spring-boot)
+中[快速接入](https://dromara.github.io/payment-spring-boot/#/quick_start)章节 (暂时不可用)~~
### 调用示例
diff --git a/docs/changelog.md b/docs/changelog.md
index 5d27d83..0f1ec2c 100644
--- a/docs/changelog.md
+++ b/docs/changelog.md
@@ -1,3 +1,13 @@
+## 1.0.21.RELEASE
+### 微信支付
+
+- enhance: 增加了通过微信公钥对微信支付相关接口的响应内容或微信回调通知的参数进行验签的支持。
+ - 微信配置项增加了:``` wechat-pay-public-key-id: 微信支付公钥的ID、 wechat-pay-public-key-path:微信支付公钥的路径、wechat-pay-public-key-absolute-path: 微信支付公钥的绝对路径、 switch-verify-sign-method: 是否启用从平台证书切换到微信支公钥```
+ - `wechat-pay-public-key-id ` 与`wechat-pay-public-key-path或wechat-pay-public-key-absolute-path`同时正确配置,才会启用微信支付公钥验签,否则默认使用平台证书进行验签。
+ - 如果需要[从平台证书切换成微信支付公钥](https://pay.weixin.qq.com/doc/v3/merchant/4012154180#5.-%E6%B2%A1%E6%9C%89%E4%BD%BF%E7%94%A8%E5%BE%AE%E4%BF%A1%E6%94%AF%E4%BB%98SDK%E7%9A%84%E5%95%86%E6%88%B7%E5%A6%82%E4%BD%95%E5%B0%86%E5%B9%B3%E5%8F%B0%E8%AF%81%E4%B9%A6%E5%88%87%E6%8D%A2%E6%88%90%E5%BE%AE%E4%BF%A1%E6%94%AF%E4%BB%98%E5%85%AC%E9%92%A5),请启用`switch-verify-sign-method`参数
+- enhance: 增加了微信支付V3版本的付款码支付``codePay``与撤销API``reverse``(仅支持普通商户模式,服务商模式暂不支持)
+- factor: 升级了spring-boot-parent版本从 2.7.7 到2.7.18
+- factor: 升级了Alipay SDK版本从4.31.7.ALL到4.40.251.ALL
## 1.0.18.RELEASE
### 微信支付
diff --git a/docs/quick_start.md b/docs/quick_start.md
index 768dff4..926bd09 100644
--- a/docs/quick_start.md
+++ b/docs/quick_start.md
@@ -4,7 +4,7 @@
cn.felord
payment-spring-boot-starter
- 1.0.20.RELEASE
+ 1.0.21.RELEASE
```
> 基于 **Spring Boot 2.x**
@@ -86,6 +86,13 @@ wechat:
mch-id: 1603337223
domain: https://felord.cn/miniapp
cert-path: miniapp/apiclient_cert.p12
+ #微信公钥ID
+ wechat-pay-public-key-id: PUB_KEY_ID_0116278111111115222222501
+ #微信公钥
+ wechat-pay-public-key-path: pub_key.pem
+ wechat-pay-public-key-absolute-path: D:\\felord\\wechat\\cert\\pub_key.pem
+ #是否启用从平台证书切换成微信支付公钥 不填默认为false
+ switch-verify-sign-method: true
```
> ❗注意:在一套系统中需要开发者保证`tentanID`唯一。
diff --git a/payment-spring-boot-autoconfigure/pom.xml b/payment-spring-boot-autoconfigure/pom.xml
index 86214da..3009ace 100644
--- a/payment-spring-boot-autoconfigure/pom.xml
+++ b/payment-spring-boot-autoconfigure/pom.xml
@@ -22,11 +22,11 @@
cn.felord
payment-spring-boot
- 1.0.20.RELEASE
+ 1.0.21.RELEASE
payment-spring-boot-autoconfigure
- 1.0.20.RELEASE
+ 1.0.21.RELEASE
jar
4.0.0
diff --git a/payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/InMemoryWechatTenantService.java b/payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/InMemoryWechatTenantService.java
index f0de581..8ff21f1 100644
--- a/payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/InMemoryWechatTenantService.java
+++ b/payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/InMemoryWechatTenantService.java
@@ -17,15 +17,23 @@
package cn.felord.payment.wechat;
-import cn.felord.payment.wechat.v3.KeyPairFactory;
-import cn.felord.payment.wechat.v3.WechatMetaBean;
+import cn.felord.payment.PayException;
+import cn.felord.payment.wechat.v3.*;
import lombok.AllArgsConstructor;
+import org.bouncycastle.util.io.pem.PemObject;
+import org.bouncycastle.util.io.pem.PemReader;
import org.springframework.core.io.FileSystemResource;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ResourceUtils;
+import org.springframework.util.StringUtils;
+import java.io.FileReader;
+import java.io.InputStreamReader;
+import java.security.KeyFactory;
+import java.security.interfaces.RSAPublicKey;
+import java.security.spec.X509EncodedKeySpec;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
@@ -62,6 +70,7 @@ public class InMemoryWechatTenantService implements WechatTenantService {
WechatMetaBean wechatMetaBean = keyPairFactory.initWechatMetaBean(resource, mchId);
wechatMetaBean.setV3(v3);
wechatMetaBean.setTenantId(tenantId);
+ SignatureProvider.addWeChatPublicKey(initWeChatPublicKeyInfo(wechatMetaBean));
return wechatMetaBean;
})
.collect(Collectors.toSet());
@@ -69,4 +78,29 @@ public class InMemoryWechatTenantService implements WechatTenantService {
}
return cache;
}
+
+ private WeChatPublicKeyInfo initWeChatPublicKeyInfo(WechatMetaBean meta) {
+ boolean enablePublicKey=StringUtils.hasLength(meta.getV3().getWechatPayPublicKeyId()) &&
+ (StringUtils.hasLength(meta.getV3().getWechatPayPublicKeyPath())||StringUtils.hasLength(meta.getV3().getWechatPayPublicKeyAbsolutePath()));
+ if (!enablePublicKey) {
+ return null;
+ }
+ try {
+ String certPath=meta.getV3().getWechatPayPublicKeyPath();
+ String certAbsolutePath = meta.getV3().getWechatPayPublicKeyAbsolutePath();
+ Resource resource =
+ StringUtils.hasLength(certAbsolutePath) ? new FileSystemResource(certAbsolutePath) :
+ resourceLoader.getResource(!StringUtils.hasLength(certPath) ? "classpath:wechat/pub_key.pem" :
+ certPath.startsWith(ResourceUtils.CLASSPATH_URL_PREFIX) ? certPath : ResourceUtils.CLASSPATH_URL_PREFIX + certPath);
+ PemReader pemReader = new PemReader(new InputStreamReader(resource.getInputStream()));
+ PemObject pemObject = pemReader.readPemObject();
+ X509EncodedKeySpec keySpec = new X509EncodedKeySpec(pemObject.getContent());
+ KeyFactory keyFactory = KeyFactory.getInstance("RSA");
+ RSAPublicKey publicKey = (RSAPublicKey) keyFactory.generatePublic(keySpec);
+ // 生成公钥
+ return new WeChatPublicKeyInfo(publicKey, meta.getV3().getWechatPayPublicKeyId(), meta.getTenantId());
+ }catch (Exception e){
+ throw new PayException("An error occurred while generating the public key,Please check the format and content of the configured public key");
+ }
+ }
}
diff --git a/payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/WechatPayProperties.java b/payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/WechatPayProperties.java
index 05de2d9..18b353f 100644
--- a/payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/WechatPayProperties.java
+++ b/payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/WechatPayProperties.java
@@ -76,5 +76,28 @@ public class WechatPayProperties {
* your pay server domain
*/
private String domain;
+
+ /**
+ * wechat pay public key id
+ */
+ private String wechatPayPublicKeyId;
+
+ /**
+ * see
+ *
+ * wechat pay public key
+ */
+ private String wechatPayPublicKeyPath;
+
+ private String wechatPayPublicKeyAbsolutePath;
+
+ /**
+ *
+ * see
+ * Indicate whether to switch from the platform certificate to the WeChat Pay public key
+ *
+ */
+ private Boolean switchVerifySignMethod = false;
+
}
}
diff --git a/payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/enumeration/WechatPayV3Type.java b/payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/enumeration/WechatPayV3Type.java
index c62871d..2195a86 100644
--- a/payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/enumeration/WechatPayV3Type.java
+++ b/payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/enumeration/WechatPayV3Type.java
@@ -66,6 +66,13 @@ public enum WechatPayV3Type {
MERCHANT_MEDIA_VIDEO(HttpMethod.POST, "%s/v3/merchant/media/video_upload"),
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ /**
+ * 付款码支付
+ *
+ * @since 1.0.0.RELEASE
+ */
+ CODE(HttpMethod.POST, "%s/v3/pay/transactions/codepay"),
+
/**
* 微信公众号支付或者小程序支付.
*
@@ -99,6 +106,13 @@ public enum WechatPayV3Type {
* @since 1.0.0.RELEASE
*/
CLOSE(HttpMethod.POST, "%s/v3/pay/transactions/out-trade-no/{out_trade_no}/close"),
+ /**
+ * 关闭订单.
+ *
+ * @since 1.0.0.RELEASE
+ */
+ REVERSE(HttpMethod.POST, "%s/v3/pay/transactions/out-trade-no/{out_trade_no}/reverse"),
+
/**
* 微信支付订单号查询API.
*
@@ -633,6 +647,7 @@ public enum WechatPayV3Type {
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
/**
* 服务商APP下单API.
*
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 b949cd6..3b8a2c5 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
@@ -27,13 +27,15 @@ import com.fasterxml.jackson.databind.node.ObjectNode;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
+import org.bouncycastle.util.io.pem.PemObject;
+import org.bouncycastle.util.io.pem.PemReader;
+import org.springframework.core.io.FileSystemResource;
+import org.springframework.core.io.Resource;
+import org.springframework.core.io.ResourceLoader;
import org.springframework.http.*;
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.util.*;
import org.springframework.web.client.RestOperations;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.util.UriComponents;
@@ -44,12 +46,16 @@ import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.GCMParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.io.ByteArrayInputStream;
+import java.io.FileInputStream;
+import java.io.FileReader;
import java.nio.charset.StandardCharsets;
import java.security.*;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
+import java.security.interfaces.RSAPublicKey;
+import java.security.spec.X509EncodedKeySpec;
import java.time.Instant;
import java.util.*;
import java.util.stream.Collectors;
@@ -85,6 +91,11 @@ public class SignatureProvider {
* 微信平台证书容器 key = 序列号 value = 证书对象
*/
private static final Set CERTIFICATE_SET = Collections.synchronizedSet(new HashSet<>());
+
+ private static final Set PUBLIC_KEY_SET = Collections.synchronizedSet(new HashSet<>());
+
+ private static final String PUBLIC_KYE_ID_PREFIX = "PUB_KEY_ID";
+
/**
* 加密算法提供方 - BouncyCastle
*/
@@ -117,6 +128,10 @@ public class SignatureProvider {
wechatMetaContainer.getTenantIds().forEach(this::refreshCertificate);
}
+ public static void addWeChatPublicKey(WeChatPublicKeyInfo weChatPublicKeyInfo) {
+ PUBLIC_KEY_SET.add(weChatPublicKeyInfo);
+ }
+
/**
* 我方请求前用 SHA256withRSA 加签,使用API证书.
@@ -171,7 +186,19 @@ public class SignatureProvider {
* @return the boolean
*/
public boolean responseSignVerify(ResponseSignVerifyParams params) {
+ log.debug("wechatpaySerial: {}", params.getWechatpaySerial());
+ boolean verifyResult= params.getWechatpaySerial().startsWith(PUBLIC_KYE_ID_PREFIX)?
+ responseSignVerifyWithWeChatPublicKeyInfo(params):
+ responseSignVerifyWithX509WechatCertificate(params);
+ log.debug("responseSignVerify: {}", verifyResult);
+ return verifyResult;
+ }
+ /***
+ *通过平台证书进行验签
+ */
+ private boolean responseSignVerifyWithX509WechatCertificate(ResponseSignVerifyParams params){
+ log.debug("responseSignVerifyWithX509WechatCertificate: {}", params);
String wechatpaySerial = params.getWechatpaySerial();
X509WechatCertificateInfo certificate = CERTIFICATE_SET.stream()
.filter(cert -> Objects.equals(wechatpaySerial, cert.getWechatPaySerial()))
@@ -195,6 +222,30 @@ public class SignatureProvider {
}
}
+ /***
+ *通过微信支付公钥进行验签
+ */
+ private boolean responseSignVerifyWithWeChatPublicKeyInfo(ResponseSignVerifyParams params){
+ log.debug("responseSignVerifyWithWeChatPublicKeyInfo: {}", params);
+ String wechatpaySerial = params.getWechatpaySerial();
+ if (wechatpaySerial.startsWith(PUBLIC_KYE_ID_PREFIX)){
+ WeChatPublicKeyInfo info = PUBLIC_KEY_SET.stream()
+ .filter(key -> Objects.equals(wechatpaySerial, key.getPublicKeyId()))
+ .findAny()
+ .orElseThrow(() -> new PayException("cannot obtain the public key"));
+
+ try {
+ final String signatureStr = createSign(params.getWechatpayTimestamp(), params.getWechatpayNonce(), params.getBody());
+ Signature signer = Signature.getInstance("SHA256withRSA", BC_PROVIDER);
+ signer.initVerify(info.getPublicKey());
+ 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());
+ }
+ }
+ return false;
+ }
/**
* 当我方服务器不存在平台证书或者证书同当前响应报文中的证书序列号不一致时应当刷新 调用/v3/certificates
@@ -395,4 +446,16 @@ public class SignatureProvider {
.collect(Collectors.joining("\n", "", "\n"));
}
+ public boolean isSwitchVerifySignMethod(String tenantId) {
+
+ String publicKeyId=wechatMetaContainer.getWechatMeta(tenantId).getV3().getWechatPayPublicKeyId();
+
+ Boolean switchVerifySignMethod = wechatMetaContainer.getWechatMeta(tenantId).getV3().getSwitchVerifySignMethod();
+
+ return switchVerifySignMethod && StringUtils.hasLength(publicKeyId);
+ }
+
+ public String getWechatPublicKeyId(String tenantId) {
+ return wechatMetaContainer.getWechatMeta(tenantId).getV3().getWechatPayPublicKeyId();
+ }
}
diff --git a/payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/v3/WeChatPublicKeyInfo.java b/payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/v3/WeChatPublicKeyInfo.java
new file mode 100644
index 0000000..73b347e
--- /dev/null
+++ b/payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/v3/WeChatPublicKeyInfo.java
@@ -0,0 +1,24 @@
+package cn.felord.payment.wechat.v3;
+
+import lombok.Data;
+
+import java.security.interfaces.RSAPublicKey;
+
+@Data
+public class WeChatPublicKeyInfo {
+
+ private RSAPublicKey publicKey;
+
+ private String publicKeyId;
+
+ private String tenantId;
+
+ public WeChatPublicKeyInfo(RSAPublicKey publicKey, String publicKeyId, String tenantId) {
+ this.publicKeyId = publicKeyId;
+ this.tenantId = tenantId;
+ this.publicKey = publicKey;
+ }
+
+ public WeChatPublicKeyInfo() {
+ }
+}
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..2c4cbdc 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
@@ -57,11 +57,34 @@ public class WechatDirectPayApi extends AbstractApi {
}
/**
- * APP下单API
+ * 付款码支付API
*
* @param payParams the pay params
* @return the wechat response entity
*/
+ public WechatResponseEntity codePay(PayParams payParams) {
+ WechatResponseEntity wechatResponseEntity = new WechatResponseEntity<>();
+ this.client().withType(WechatPayV3Type.CODE, payParams)
+ .function(this::payFunction)
+ .consumer(responseEntity -> {
+ ObjectNode body = responseEntity.getBody();
+ if (Objects.isNull(body)) {
+ throw new PayException("response body cannot be resolved");
+ }
+ wechatResponseEntity.setHttpStatus(responseEntity.getStatusCodeValue());
+ wechatResponseEntity.setBody(body);
+ })
+ .request();
+ return wechatResponseEntity;
+ }
+
+
+ /**
+ * APP下单API
+ *
+ * @param payParams the pay params
+ * @return the wechat response entity
+ */
public WechatResponseEntity appPay(PayParams payParams) {
WechatResponseEntity wechatResponseEntity = new WechatResponseEntity<>();
this.client().withType(WechatPayV3Type.APP, payParams)
@@ -185,8 +208,10 @@ public class WechatDirectPayApi extends AbstractApi {
WechatPayProperties.V3 v3 = this.wechatMetaBean().getV3();
payParams.setAppid(v3.getAppId());
payParams.setMchid(v3.getMchId());
- String notifyUrl = v3.getDomain().concat(payParams.getNotifyUrl());
- payParams.setNotifyUrl(notifyUrl);
+ if (!type.equals(WechatPayV3Type.CODE)){
+ String notifyUrl = v3.getDomain().concat(payParams.getNotifyUrl());
+ payParams.setNotifyUrl(notifyUrl);
+ }
URI uri = UriComponentsBuilder.fromHttpUrl(type.uri(WeChatServer.CHINA))
.build()
.toUri();
@@ -252,6 +277,21 @@ public class WechatDirectPayApi extends AbstractApi {
return wechatResponseEntity;
}
+ /**
+ * 撤销API
+ *
+ * @param outTradeNo the out trade no
+ * @return the wechat response entity
+ */
+ public WechatResponseEntity reverse(String outTradeNo) {
+ WechatResponseEntity wechatResponseEntity = new WechatResponseEntity<>();
+ this.client().withType(WechatPayV3Type.REVERSE, outTradeNo)
+ .function(this::reverseOutTradeNoFunction)
+ .consumer(wechatResponseEntity::convert)
+ .request();
+ return wechatResponseEntity;
+ }
+
private RequestEntity> closeByOutTradeNoFunction(WechatPayV3Type type, String outTradeNo) {
WechatPayProperties.V3 v3 = this.wechatMetaBean().getV3();
@@ -265,6 +305,20 @@ public class WechatDirectPayApi extends AbstractApi {
return Post(uri, queryParams);
}
+ private RequestEntity> reverseOutTradeNoFunction(WechatPayV3Type type, String outTradeNo) {
+ WechatPayProperties.V3 v3 = this.wechatMetaBean().getV3();
+
+ Map queryParams = new HashMap<>(1);
+ queryParams.put("mchid", v3.getMchId());
+ queryParams.put("appid", v3.getAppId());
+
+ URI uri = UriComponentsBuilder.fromHttpUrl(type.uri(WeChatServer.CHINA))
+ .build()
+ .expand(outTradeNo)
+ .toUri();
+ return Post(uri, queryParams);
+ }
+
/**
* 申请退款API
*
diff --git a/payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/v3/WechatMetaBean.java b/payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/v3/WechatMetaBean.java
index 6e1cd8e..4ed15e5 100644
--- a/payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/v3/WechatMetaBean.java
+++ b/payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/v3/WechatMetaBean.java
@@ -46,5 +46,7 @@ public class WechatMetaBean {
* The V3.
*/
private WechatPayProperties.V3 v3;
+
+ private WeChatPublicKeyInfo publicKeyInfo;
}
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..61212d6 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
@@ -232,6 +232,11 @@ public class WechatPayClient {
// 避免出现因为中文导致的 HttpRetryException
httpHeaders.setContentType(MediaType.parseMediaType("application/json;charset=UTF-8"));
}
+
+ if (signatureProvider.isSwitchVerifySignMethod(tenantId)){
+ httpHeaders.add("Wechatpay-Serial", signatureProvider.getWechatPublicKeyId(tenantId));
+ }
+
httpHeaders.add("Authorization", authorization);
httpHeaders.add("User-Agent", "X-Pay-Service");
httpHeaders.remove("Meta-Info");
diff --git a/payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/v3/model/Payer.java b/payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/v3/model/Payer.java
index 1b29fc4..b928056 100644
--- a/payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/v3/model/Payer.java
+++ b/payment-spring-boot-autoconfigure/src/main/java/cn/felord/payment/wechat/v3/model/Payer.java
@@ -38,4 +38,6 @@ public class Payer {
* 用户子标识
*/
private String subOpenid;
+
+ private String authCode;
}
diff --git a/payment-spring-boot-starter/pom.xml b/payment-spring-boot-starter/pom.xml
index 52620ab..92afff8 100644
--- a/payment-spring-boot-starter/pom.xml
+++ b/payment-spring-boot-starter/pom.xml
@@ -26,7 +26,7 @@
payment-spring-boot-starter
- 1.0.20.RELEASE
+ 1.0.21.RELEASE
jar
4.0.0
diff --git a/pom.xml b/pom.xml
index 4c8b172..0f89ec2 100644
--- a/pom.xml
+++ b/pom.xml
@@ -21,7 +21,7 @@
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
cn.felord
payment-spring-boot
- 1.0.20.RELEASE
+ 1.0.21.RELEASE
pom
4.0.0
@@ -88,8 +88,8 @@
UTF-8
UTF-8
1.8
- 2.7.7
- 4.31.7.ALL
+ 2.7.18
+ 4.40.251.ALL
1.78