Commit a2bfa7a95aede05244f41cccf21ccef194fc1f77

Authored by YunaiV
1 parent 59234e1e

feat:weixin-java from 4.7.2.B => 4.7.4.B

feat:微信支付 v3 从平台证书切换成微信支付公钥
feat:微信支付 v3 增加 header 解析
yudao-dependencies/pom.xml
... ... @@ -75,7 +75,7 @@
75 75 <justauth.version>1.16.7</justauth.version>
76 76 <justauth-starter.version>1.4.0</justauth-starter.version>
77 77 <jimureport.version>1.9.4</jimureport.version>
78   - <weixin-java.version>4.7.2.B</weixin-java.version>
  78 + <weixin-java.version>4.7.4.B</weixin-java.version>
79 79 </properties>
80 80  
81 81 <dependencyManagement>
... ...
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/notify/PayNotifyController.java
... ... @@ -66,7 +66,8 @@ public class PayNotifyController {
66 66 @TenantIgnore
67 67 public String notifyOrder(@PathVariable("channelId") Long channelId,
68 68 @RequestParam(required = false) Map<String, String> params,
69   - @RequestBody(required = false) String body) {
  69 + @RequestBody(required = false) String body,
  70 + @RequestHeader Map<String, String> headers) {
70 71 log.info("[notifyOrder][channelId({}) 回调数据({}/{})]", channelId, params, body);
71 72 // 1. 校验支付渠道是否存在
72 73 PayClient payClient = channelService.getPayClient(channelId);
... ... @@ -76,7 +77,7 @@ public class PayNotifyController {
76 77 }
77 78  
78 79 // 2. 解析通知数据
79   - PayOrderRespDTO notify = payClient.parseOrderNotify(params, body);
  80 + PayOrderRespDTO notify = payClient.parseOrderNotify(params, body, headers);
80 81 orderService.notifyOrder(channelId, notify);
81 82 return "success";
82 83 }
... ... @@ -87,7 +88,8 @@ public class PayNotifyController {
87 88 @TenantIgnore
88 89 public String notifyRefund(@PathVariable("channelId") Long channelId,
89 90 @RequestParam(required = false) Map<String, String> params,
90   - @RequestBody(required = false) String body) {
  91 + @RequestBody(required = false) String body,
  92 + @RequestHeader Map<String, String> headers) {
91 93 log.info("[notifyRefund][channelId({}) 回调数据({}/{})]", channelId, params, body);
92 94 // 1. 校验支付渠道是否存在
93 95 PayClient payClient = channelService.getPayClient(channelId);
... ... @@ -97,7 +99,7 @@ public class PayNotifyController {
97 99 }
98 100  
99 101 // 2. 解析通知数据
100   - PayRefundRespDTO notify = payClient.parseRefundNotify(params, body);
  102 + PayRefundRespDTO notify = payClient.parseRefundNotify(params, body, headers);
101 103 refundService.notifyRefund(channelId, notify);
102 104 return "success";
103 105 }
... ... @@ -108,7 +110,8 @@ public class PayNotifyController {
108 110 @TenantIgnore
109 111 public String notifyTransfer(@PathVariable("channelId") Long channelId,
110 112 @RequestParam(required = false) Map<String, String> params,
111   - @RequestBody(required = false) String body) {
  113 + @RequestBody(required = false) String body,
  114 + @RequestHeader Map<String, String> headers) {
112 115 log.info("[notifyTransfer][channelId({}) 回调数据({}/{})]", channelId, params, body);
113 116 // 1. 校验支付渠道是否存在
114 117 PayClient payClient = channelService.getPayClient(channelId);
... ... @@ -118,7 +121,7 @@ public class PayNotifyController {
118 121 }
119 122  
120 123 // 2. 解析通知数据
121   - PayTransferRespDTO notify = payClient.parseTransferNotify(params, body);
  124 + PayTransferRespDTO notify = payClient.parseTransferNotify(params, body, headers);
122 125 payTransferService.notifyTransfer(channelId, notify);
123 126 return "success";
124 127 }
... ...
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/framework/pay/core/WalletPayClient.java
... ... @@ -89,7 +89,7 @@ public class WalletPayClient extends AbstractPayClient&lt;NonePayClientConfig&gt; {
89 89 }
90 90  
91 91 @Override
92   - protected PayOrderRespDTO doParseOrderNotify(Map<String, String> params, String body) {
  92 + protected PayOrderRespDTO doParseOrderNotify(Map<String, String> params, String body, Map<String, String> headers) {
93 93 throw new UnsupportedOperationException("钱包支付无支付回调");
94 94 }
95 95  
... ... @@ -144,7 +144,7 @@ public class WalletPayClient extends AbstractPayClient&lt;NonePayClientConfig&gt; {
144 144 }
145 145  
146 146 @Override
147   - protected PayRefundRespDTO doParseRefundNotify(Map<String, String> params, String body) {
  147 + protected PayRefundRespDTO doParseRefundNotify(Map<String, String> params, String body, Map<String, String> headers) {
148 148 throw new UnsupportedOperationException("钱包支付无退款回调");
149 149 }
150 150  
... ... @@ -178,7 +178,7 @@ public class WalletPayClient extends AbstractPayClient&lt;NonePayClientConfig&gt; {
178 178 }
179 179  
180 180 @Override
181   - protected PayTransferRespDTO doParseTransferNotify(Map<String, String> params, String body) throws Throwable {
  181 + protected PayTransferRespDTO doParseTransferNotify(Map<String, String> params, String body, Map<String, String> headers) {
182 182 throw new UnsupportedOperationException("未实现");
183 183 }
184 184  
... ...
yudao-module-pay/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/PayClient.java
... ... @@ -39,9 +39,10 @@ public interface PayClient {
39 39 *
40 40 * @param params HTTP 回调接口 content type 为 application/x-www-form-urlencoded 的所有参数
41 41 * @param body HTTP 回调接口的 request body
  42 + * @param headers HTTP 回调接口的 request headers
42 43 * @return 支付订单信息
43 44 */
44   - PayOrderRespDTO parseOrderNotify(Map<String, String> params, String body);
  45 + PayOrderRespDTO parseOrderNotify(Map<String, String> params, String body, Map<String, String> headers);
45 46  
46 47 /**
47 48 * 获得支付订单信息
... ... @@ -66,9 +67,10 @@ public interface PayClient {
66 67 *
67 68 * @param params HTTP 回调接口 content type 为 application/x-www-form-urlencoded 的所有参数
68 69 * @param body HTTP 回调接口的 request body
  70 + * @param headers HTTP 回调接口的 request headers
69 71 * @return 支付订单信息
70 72 */
71   - PayRefundRespDTO parseRefundNotify(Map<String, String> params, String body);
  73 + PayRefundRespDTO parseRefundNotify(Map<String, String> params, String body, Map<String, String> headers);
72 74  
73 75 /**
74 76 * 获得退款订单信息
... ... @@ -103,8 +105,9 @@ public interface PayClient {
103 105 *
104 106 * @param params HTTP 回调接口 content type 为 application/x-www-form-urlencoded 的所有参数
105 107 * @param body HTTP 回调接口的 request body
  108 + * @param headers HTTP 回调接口的 request headers
106 109 * @return 转账信息
107 110 */
108   - PayTransferRespDTO parseTransferNotify(Map<String, String> params, String body);
  111 + PayTransferRespDTO parseTransferNotify(Map<String, String> params, String body, Map<String, String> headers);
109 112  
110 113 }
... ...
yudao-module-pay/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/PayClientConfig.java
1 1 package cn.iocoder.yudao.framework.pay.core.client;
2 2  
  3 +import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
3 4 import com.fasterxml.jackson.annotation.JsonTypeInfo;
4   -
5 5 import jakarta.validation.Validator;
6 6  
7 7 /**
... ... @@ -14,6 +14,7 @@ import jakarta.validation.Validator;
14 14 // @JsonTypeInfo 注解的作用,Jackson 多态
15 15 // 1. 序列化到时数据库时,增加 @class 属性。
16 16 // 2. 反序列化到内存对象时,通过 @class 属性,可以创建出正确的类型
  17 +@JsonIgnoreProperties(ignoreUnknown = true) // 目的:忽略未知的属性,避免反序列化失败
17 18 public interface PayClientConfig {
18 19  
19 20 /**
... ...
yudao-module-pay/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/AbstractPayClient.java
... ... @@ -101,19 +101,19 @@ public abstract class AbstractPayClient&lt;Config extends PayClientConfig&gt; implemen
101 101 throws Throwable;
102 102  
103 103 @Override
104   - public final PayOrderRespDTO parseOrderNotify(Map<String, String> params, String body) {
  104 + public final PayOrderRespDTO parseOrderNotify(Map<String, String> params, String body, Map<String, String> headers) {
105 105 try {
106   - return doParseOrderNotify(params, body);
  106 + return doParseOrderNotify(params, body, headers);
107 107 } catch (ServiceException ex) { // 业务异常,都是实现类已经翻译,所以直接抛出即可
108 108 throw ex;
109 109 } catch (Throwable ex) {
110   - log.error("[parseOrderNotify][客户端({}) params({}) body({}) 解析失败]",
111   - getId(), params, body, ex);
  110 + log.error("[parseOrderNotify][客户端({}) params({}) body({}) headers({}) 解析失败]",
  111 + getId(), params, body, headers, ex);
112 112 throw buildPayException(ex);
113 113 }
114 114 }
115 115  
116   - protected abstract PayOrderRespDTO doParseOrderNotify(Map<String, String> params, String body)
  116 + protected abstract PayOrderRespDTO doParseOrderNotify(Map<String, String> params, String body, Map<String, String> headers)
117 117 throws Throwable;
118 118  
119 119 @Override
... ... @@ -155,19 +155,19 @@ public abstract class AbstractPayClient&lt;Config extends PayClientConfig&gt; implemen
155 155 protected abstract PayRefundRespDTO doUnifiedRefund(PayRefundUnifiedReqDTO reqDTO) throws Throwable;
156 156  
157 157 @Override
158   - public final PayRefundRespDTO parseRefundNotify(Map<String, String> params, String body) {
  158 + public final PayRefundRespDTO parseRefundNotify(Map<String, String> params, String body, Map<String, String> headers) {
159 159 try {
160   - return doParseRefundNotify(params, body);
  160 + return doParseRefundNotify(params, body, headers);
161 161 } catch (ServiceException ex) { // 业务异常,都是实现类已经翻译,所以直接抛出即可
162 162 throw ex;
163 163 } catch (Throwable ex) {
164   - log.error("[parseRefundNotify][客户端({}) params({}) body({}) 解析失败]",
165   - getId(), params, body, ex);
  164 + log.error("[parseRefundNotify][客户端({}) params({}) body({}) headers({}) 解析失败]",
  165 + getId(), params, body, headers, ex);
166 166 throw buildPayException(ex);
167 167 }
168 168 }
169 169  
170   - protected abstract PayRefundRespDTO doParseRefundNotify(Map<String, String> params, String body)
  170 + protected abstract PayRefundRespDTO doParseRefundNotify(Map<String, String> params, String body, Map<String, String> headers)
171 171 throws Throwable;
172 172  
173 173 @Override
... ... @@ -220,19 +220,19 @@ public abstract class AbstractPayClient&lt;Config extends PayClientConfig&gt; implemen
220 220 }
221 221  
222 222 @Override
223   - public final PayTransferRespDTO parseTransferNotify(Map<String, String> params, String body) {
  223 + public final PayTransferRespDTO parseTransferNotify(Map<String, String> params, String body, Map<String, String> headers) {
224 224 try {
225   - return doParseTransferNotify(params, body);
  225 + return doParseTransferNotify(params, body, headers);
226 226 } catch (ServiceException ex) { // 业务异常,都是实现类已经翻译,所以直接抛出即可
227 227 throw ex;
228 228 } catch (Throwable ex) {
229   - log.error("[doParseTransferNotify][客户端({}) params({}) body({}) 解析失败]",
230   - getId(), params, body, ex);
  229 + log.error("[doParseTransferNotify][客户端({}) params({}) body({}) headers({}) 解析失败]",
  230 + getId(), params, body, headers, ex);
231 231 throw buildPayException(ex);
232 232 }
233 233 }
234 234  
235   - protected abstract PayTransferRespDTO doParseTransferNotify(Map<String, String> params, String body)
  235 + protected abstract PayTransferRespDTO doParseTransferNotify(Map<String, String> params, String body, Map<String, String> headers)
236 236 throws Throwable;
237 237  
238 238 @Override
... ...
yudao-module-pay/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/alipay/AbstractAlipayPayClient.java
... ... @@ -79,7 +79,7 @@ public abstract class AbstractAlipayPayClient extends AbstractPayClient&lt;AlipayPa
79 79 }
80 80  
81 81 @Override
82   - public PayOrderRespDTO doParseOrderNotify(Map<String, String> params, String body) throws Throwable {
  82 + public PayOrderRespDTO doParseOrderNotify(Map<String, String> params, String body, Map<String, String> headers) throws Throwable {
83 83 // 1. 校验回调数据
84 84 Map<String, String> bodyObj = HttpUtil.decodeParamMap(body, StandardCharsets.UTF_8);
85 85 AlipaySignature.rsaCheckV1(bodyObj, config.getAlipayPublicKey(),
... ... @@ -175,7 +175,7 @@ public abstract class AbstractAlipayPayClient extends AbstractPayClient&lt;AlipayPa
175 175 }
176 176  
177 177 @Override
178   - public PayRefundRespDTO doParseRefundNotify(Map<String, String> params, String body) {
  178 + public PayRefundRespDTO doParseRefundNotify(Map<String, String> params, String body, Map<String, String> headers) {
179 179 // 补充说明:支付宝退款时,没有回调,这点和微信支付是不同的。并且,退款分成部分退款、和全部退款。
180 180 // ① 部分退款:是会有回调,但是它回调的是订单状态的同步回调,不是退款订单的回调
181 181 // ② 全部退款:Wap 支付有订单状态的同步回调,但是 PC/扫码又没有
... ... @@ -327,7 +327,7 @@ public abstract class AbstractAlipayPayClient extends AbstractPayClient&lt;AlipayPa
327 327  
328 328 // TODO @chihuo:这里是不是也要实现,支付宝的。
329 329 @Override
330   - protected PayTransferRespDTO doParseTransferNotify(Map<String, String> params, String body) throws Throwable {
  330 + protected PayTransferRespDTO doParseTransferNotify(Map<String, String> params, String body, Map<String, String> headers) {
331 331 throw new UnsupportedOperationException("未实现");
332 332 }
333 333  
... ...
yudao-module-pay/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/mock/MockPayClient.java
... ... @@ -58,17 +58,17 @@ public class MockPayClient extends AbstractPayClient&lt;NonePayClientConfig&gt; {
58 58 }
59 59  
60 60 @Override
61   - protected PayTransferRespDTO doParseTransferNotify(Map<String, String> params, String body) throws Throwable {
  61 + protected PayTransferRespDTO doParseTransferNotify(Map<String, String> params, String body, Map<String, String> headers) {
62 62 throw new UnsupportedOperationException("未实现");
63 63 }
64 64  
65 65 @Override
66   - protected PayRefundRespDTO doParseRefundNotify(Map<String, String> params, String body) {
  66 + protected PayRefundRespDTO doParseRefundNotify(Map<String, String> params, String body, Map<String, String> headers) {
67 67 throw new UnsupportedOperationException("模拟支付无退款回调");
68 68 }
69 69  
70 70 @Override
71   - protected PayOrderRespDTO doParseOrderNotify(Map<String, String> params, String body) {
  71 + protected PayOrderRespDTO doParseOrderNotify(Map<String, String> params, String body, Map<String, String> headers) {
72 72 throw new UnsupportedOperationException("模拟支付无支付回调");
73 73 }
74 74  
... ...
yudao-module-pay/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/weixin/AbstractWxPayClient.java
... ... @@ -18,10 +18,7 @@ import cn.iocoder.yudao.framework.pay.core.client.dto.transfer.WxPayTransferPart
18 18 import cn.iocoder.yudao.framework.pay.core.client.impl.AbstractPayClient;
19 19 import cn.iocoder.yudao.framework.pay.core.enums.order.PayOrderStatusRespEnum;
20 20 import cn.iocoder.yudao.framework.pay.core.enums.transfer.PayTransferTypeEnum;
21   -import com.github.binarywang.wxpay.bean.notify.WxPayNotifyV3Result;
22   -import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyResult;
23   -import com.github.binarywang.wxpay.bean.notify.WxPayRefundNotifyResult;
24   -import com.github.binarywang.wxpay.bean.notify.WxPayRefundNotifyV3Result;
  21 +import com.github.binarywang.wxpay.bean.notify.*;
25 22 import com.github.binarywang.wxpay.bean.request.*;
26 23 import com.github.binarywang.wxpay.bean.result.*;
27 24 import com.github.binarywang.wxpay.bean.transfer.QueryTransferBatchesRequest;
... ... @@ -67,13 +64,14 @@ public abstract class AbstractWxPayClient extends AbstractPayClient&lt;WxPayClientC
67 64 protected void doInit(String tradeType) {
68 65 // 创建 config 配置
69 66 WxPayConfig payConfig = new WxPayConfig();
70   - BeanUtil.copyProperties(config, payConfig, "keyContent", "privateKeyContent");
  67 + BeanUtil.copyProperties(config, payConfig, "keyContent", "privateKeyContent", "publicKeyContent");
71 68 payConfig.setTradeType(tradeType);
72 69 // weixin-pay-java 无法设置内容,只允许读取文件,所以这里要创建临时文件来解决
73 70 if (Objects.equals(config.getApiVersion(), API_VERSION_V2)) {
74 71 payConfig.setKeyPath(FileUtils.createTempFile(Base64.decode(config.getKeyContent())).getPath());
75 72 } else if (Objects.equals(config.getApiVersion(), API_VERSION_V3)) {
76 73 payConfig.setPrivateKeyPath(FileUtils.createTempFile(config.getPrivateKeyContent()).getPath());
  74 + payConfig.setPublicKeyPath(FileUtils.createTempFile(config.getPublicKeyContent()).getPath());
77 75 }
78 76  
79 77 // 创建 client 客户端
... ... @@ -157,12 +155,12 @@ public abstract class AbstractWxPayClient extends AbstractPayClient&lt;WxPayClientC
157 155 }
158 156  
159 157 @Override
160   - public PayOrderRespDTO doParseOrderNotify(Map<String, String> params, String body) throws WxPayException {
  158 + public PayOrderRespDTO doParseOrderNotify(Map<String, String> params, String body, Map<String, String> headers) throws WxPayException {
161 159 switch (config.getApiVersion()) {
162 160 case API_VERSION_V2:
163 161 return doParseOrderNotifyV2(body);
164 162 case API_VERSION_V3:
165   - return doParseOrderNotifyV3(body);
  163 + return doParseOrderNotifyV3(body, headers);
166 164 default:
167 165 throw new IllegalArgumentException(String.format("未知的 API 版本(%s)", config.getApiVersion()));
168 166 }
... ... @@ -179,9 +177,10 @@ public abstract class AbstractWxPayClient extends AbstractPayClient&lt;WxPayClientC
179 177 response.getOutTradeNo(), body);
180 178 }
181 179  
182   - private PayOrderRespDTO doParseOrderNotifyV3(String body) throws WxPayException {
  180 + private PayOrderRespDTO doParseOrderNotifyV3(String body, Map<String, String> headers) throws WxPayException {
183 181 // 1. 解析回调
184   - WxPayNotifyV3Result response = client.parseOrderNotifyV3Result(body, null);
  182 + SignatureHeader signatureHeader = getRequestHeader(headers);
  183 + WxPayNotifyV3Result response = client.parseOrderNotifyV3Result(body, signatureHeader);
185 184 WxPayNotifyV3Result.DecryptNotifyResult result = response.getResult();
186 185 // 2. 构建结果
187 186 Integer status = parseStatus(result.getTradeState());
... ... @@ -321,12 +320,12 @@ public abstract class AbstractWxPayClient extends AbstractPayClient&lt;WxPayClientC
321 320 }
322 321  
323 322 @Override
324   - public PayRefundRespDTO doParseRefundNotify(Map<String, String> params, String body) throws WxPayException {
  323 + public PayRefundRespDTO doParseRefundNotify(Map<String, String> params, String body, Map<String, String> headers) throws WxPayException {
325 324 switch (config.getApiVersion()) {
326 325 case API_VERSION_V2:
327 326 return doParseRefundNotifyV2(body);
328 327 case API_VERSION_V3:
329   - return parseRefundNotifyV3(body);
  328 + return parseRefundNotifyV3(body, headers);
330 329 default:
331 330 throw new IllegalArgumentException(String.format("未知的 API 版本(%s)", config.getApiVersion()));
332 331 }
... ... @@ -344,9 +343,10 @@ public abstract class AbstractWxPayClient extends AbstractPayClient&lt;WxPayClientC
344 343 return PayRefundRespDTO.failureOf(result.getOutRefundNo(), response);
345 344 }
346 345  
347   - private PayRefundRespDTO parseRefundNotifyV3(String body) throws WxPayException {
  346 + private PayRefundRespDTO parseRefundNotifyV3(String body, Map<String, String> headers) throws WxPayException {
348 347 // 1. 解析回调
349   - WxPayRefundNotifyV3Result response = client.parseRefundNotifyV3Result(body, null);
  348 + SignatureHeader signatureHeader = getRequestHeader(headers);
  349 + WxPayRefundNotifyV3Result response = client.parseRefundNotifyV3Result(body, signatureHeader);
350 350 WxPayRefundNotifyV3Result.DecryptNotifyResult result = response.getResult();
351 351 // 2. 构建结果
352 352 if (Objects.equals("SUCCESS", result.getRefundStatus())) {
... ... @@ -357,10 +357,10 @@ public abstract class AbstractWxPayClient extends AbstractPayClient&lt;WxPayClientC
357 357 }
358 358  
359 359 @Override
360   - public PayTransferRespDTO doParseTransferNotify(Map<String, String> params, String body) throws WxPayException {
  360 + public PayTransferRespDTO doParseTransferNotify(Map<String, String> params, String body, Map<String, String> headers) throws WxPayException {
361 361 switch (config.getApiVersion()) {
362 362 case API_VERSION_V3:
363   - return parseTransferNotifyV3(body);
  363 + return parseTransferNotifyV3(body, headers);
364 364 case API_VERSION_V2:
365 365 throw new UnsupportedOperationException("V2 版本暂不支持,建议使用 V3 版本");
366 366 default:
... ... @@ -368,10 +368,11 @@ public abstract class AbstractWxPayClient extends AbstractPayClient&lt;WxPayClientC
368 368 }
369 369 }
370 370  
371   - private PayTransferRespDTO parseTransferNotifyV3(String body) throws WxPayException {
  371 + private PayTransferRespDTO parseTransferNotifyV3(String body, Map<String, String> headers) throws WxPayException {
372 372 // 1. 解析回调
  373 + SignatureHeader signatureHeader = getRequestHeader(headers);
373 374 // TODO @luchi:这个可以复用 wxjava 里的类么?
374   - WxPayTransferPartnerNotifyV3Result response = client.baseParseOrderNotifyV3Result(body, null, WxPayTransferPartnerNotifyV3Result.class, WxPayTransferPartnerNotifyV3Result.TransferNotifyResult.class);
  375 + WxPayTransferPartnerNotifyV3Result response = client.baseParseOrderNotifyV3Result(body, signatureHeader, WxPayTransferPartnerNotifyV3Result.class, WxPayTransferPartnerNotifyV3Result.TransferNotifyResult.class);
375 376 WxPayTransferPartnerNotifyV3Result.TransferNotifyResult result = response.getResult();
376 377 // 2. 构建结果
377 378 if (Objects.equals("FINISHED", result.getBatchStatus())) {
... ... @@ -513,6 +514,20 @@ public abstract class AbstractWxPayClient extends AbstractPayClient&lt;WxPayClientC
513 514  
514 515 // ========== 各种工具方法 ==========
515 516  
  517 + /**
  518 + * 组装请求头重的签名信息
  519 + *
  520 + * @see <a href="https://github.com/binarywang/weixin-java-pay-demo/blob/master/src/main/java/com/github/binarywang/demo/wx/pay/controller/WxPayV3Controller.java#L202-L221">官方示例</a>
  521 + */
  522 + private SignatureHeader getRequestHeader(Map<String, String> headers) {
  523 + return SignatureHeader.builder()
  524 + .signature(headers.get("wechatpay-signature"))
  525 + .nonce(headers.get("wechatpay-nonce"))
  526 + .serial(headers.get("wechatpay-serial"))
  527 + .timeStamp(headers.get("wechatpay-timestamp"))
  528 + .build();
  529 + }
  530 +
516 531 static String formatDateV2(LocalDateTime time) {
517 532 return TemporalAccessorUtil.format(time.atZone(ZoneId.systemDefault()), PURE_DATETIME_PATTERN);
518 533 }
... ...
yudao-module-pay/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/weixin/WxPayClientConfig.java
... ... @@ -73,13 +73,18 @@ public class WxPayClientConfig implements PayClientConfig {
73 73 @NotBlank(message = "apiV3 密钥值不能为空", groups = V3.class)
74 74 private String apiV3Key;
75 75 /**
76   - * 证书序列号
  76 + * 证书序列号(merchantSerialNumber)
77 77 */
78 78 @NotBlank(message = "证书序列号不能为空", groups = V3.class)
79 79 private String certSerialNo;
80 80  
81   - @Deprecated // TODO 芋艿:V2.3.0 进行移除
82   - private String privateCertContent;
  81 + /**
  82 + * pub_key.pem 证书文件的对应字符串
  83 + */
  84 + @NotBlank(message = "pub_key.pem 不能为空", groups = V3.class)
  85 + private String publicKeyContent;
  86 + @NotBlank(message = "publicKeyId 不能为空", groups = V3.class)
  87 + private String publicKeyId;
83 88  
84 89 /**
85 90 * 分组校验 v2版本
... ...