Commit d224b6b9be9ae55755861fba9d306d5557e44e40

Authored by YunaiV
1 parent cbc61184

mall + pay:

1、调整微信 Lite 小程序支付的实现
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/PayClientFactoryImpl.java
@@ -61,7 +61,7 @@ public class PayClientFactoryImpl implements PayClientFactory { @@ -61,7 +61,7 @@ public class PayClientFactoryImpl implements PayClientFactory {
61 // TODO @芋艿 WX_LITE WX_APP 如果不添加在 项目启动的时候去初始化会报错无法启动。所以我手动加了两个,具体需要你来配 61 // TODO @芋艿 WX_LITE WX_APP 如果不添加在 项目启动的时候去初始化会报错无法启动。所以我手动加了两个,具体需要你来配
62 switch (channelEnum) { 62 switch (channelEnum) {
63 case WX_PUB: return (AbstractPayClient<Config>) new WxPubPayClient(channelId, (WxPayClientConfig) config); 63 case WX_PUB: return (AbstractPayClient<Config>) new WxPubPayClient(channelId, (WxPayClientConfig) config);
64 - case WX_LITE: return (AbstractPayClient<Config>) new WXLitePayClient(channelId, (WxPayClientConfig) config); //微信小程序请求支付 64 + case WX_LITE: return (AbstractPayClient<Config>) new WXLitePayClient(channelId, (WxPayClientConfig) config);
65 case WX_APP: return (AbstractPayClient<Config>) new WxPubPayClient(channelId, (WxPayClientConfig) config); 65 case WX_APP: return (AbstractPayClient<Config>) new WxPubPayClient(channelId, (WxPayClientConfig) config);
66 case WX_NATIVE: return (AbstractPayClient<Config>) new WXNativePayClient(channelId, (WxPayClientConfig) config); 66 case WX_NATIVE: return (AbstractPayClient<Config>) new WXNativePayClient(channelId, (WxPayClientConfig) config);
67 case ALIPAY_WAP: return (AbstractPayClient<Config>) new AlipayWapPayClient(channelId, (AlipayPayClientConfig) config); 67 case ALIPAY_WAP: return (AbstractPayClient<Config>) new AlipayWapPayClient(channelId, (AlipayPayClientConfig) config);
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/weixin/WXLitePayClient.java
1 package cn.iocoder.yudao.framework.pay.core.client.impl.weixin; 1 package cn.iocoder.yudao.framework.pay.core.client.impl.weixin;
2 2
3 -import cn.hutool.core.bean.BeanUtil;  
4 -import cn.hutool.core.date.DateUtil;  
5 -import cn.hutool.core.date.LocalDateTimeUtil;  
6 -import cn.hutool.core.lang.Assert;  
7 -import cn.hutool.core.map.MapUtil;  
8 -import cn.hutool.core.util.StrUtil;  
9 -import cn.iocoder.yudao.framework.common.util.io.FileUtils;  
10 -import cn.iocoder.yudao.framework.pay.core.client.dto.notify.PayNotifyReqDTO;  
11 -import cn.iocoder.yudao.framework.pay.core.client.dto.notify.PayOrderNotifyRespDTO;  
12 -import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderUnifiedReqDTO;  
13 -import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderUnifiedRespDTO;  
14 -import cn.iocoder.yudao.framework.pay.core.client.dto.refund.PayRefundUnifiedReqDTO;  
15 -import cn.iocoder.yudao.framework.pay.core.client.dto.refund.PayRefundUnifiedRespDTO;  
16 -import cn.iocoder.yudao.framework.pay.core.client.impl.AbstractPayClient;  
17 import cn.iocoder.yudao.framework.pay.core.enums.PayChannelEnum; 3 import cn.iocoder.yudao.framework.pay.core.enums.PayChannelEnum;
18 -import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyResult;  
19 -import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyV3Result;  
20 -import com.github.binarywang.wxpay.bean.order.WxPayMpOrderResult;  
21 -import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderRequest;  
22 -import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderV3Request;  
23 -import com.github.binarywang.wxpay.bean.result.WxPayUnifiedOrderV3Result;  
24 -import com.github.binarywang.wxpay.bean.result.enums.TradeTypeEnum;  
25 -import com.github.binarywang.wxpay.config.WxPayConfig;  
26 -import com.github.binarywang.wxpay.constant.WxPayConstants;  
27 -import com.github.binarywang.wxpay.exception.WxPayException;  
28 -import com.github.binarywang.wxpay.service.WxPayService;  
29 -import com.github.binarywang.wxpay.service.impl.WxPayServiceImpl;  
30 import lombok.extern.slf4j.Slf4j; 4 import lombok.extern.slf4j.Slf4j;
31 5
32 -import java.time.ZoneId;  
33 -import java.util.Date;  
34 -import java.util.Objects;  
35 -  
36 /** 6 /**
37 - * 微信小程序下支付 7 + * 微信支付(小程序)的 PayClient 实现类
  8 + *
  9 + * 由于公众号和小程序的微信支付逻辑一致,所以直接进行继承
38 * 10 *
39 * @author zwy 11 * @author zwy
40 */ 12 */
41 @Slf4j 13 @Slf4j
42 -public class WXLitePayClient extends AbstractPayClient<WxPayClientConfig> {  
43 -  
44 - private WxPayService client; 14 +public class WXLitePayClient extends WxPubPayClient {
45 15
46 public WXLitePayClient(Long channelId, WxPayClientConfig config) { 16 public WXLitePayClient(Long channelId, WxPayClientConfig config) {
47 super(channelId, PayChannelEnum.WX_LITE.getCode(), config); 17 super(channelId, PayChannelEnum.WX_LITE.getCode(), config);
48 } 18 }
49 19
50 - @Override  
51 - protected void doInit() {  
52 - WxPayConfig payConfig = new WxPayConfig();  
53 - BeanUtil.copyProperties(config, payConfig, "privateKeyContent","privateCertContent");  
54 - payConfig.setTradeType(WxPayConstants.TradeType.JSAPI); // 设置使用 JS API 支付方式  
55 -// if (StrUtil.isNotEmpty(config.getKeyContent())) {  
56 -// payConfig.setKeyContent(config.getKeyContent().getBytes(StandardCharsets.UTF_8));  
57 -// }  
58 - if (StrUtil.isNotEmpty(config.getPrivateKeyContent())) {  
59 - // weixin-pay-java 存在 BUG,无法直接设置内容,所以创建临时文件来解决  
60 - payConfig.setPrivateKeyPath(FileUtils.createTempFile(config.getPrivateKeyContent()).getPath());  
61 - }  
62 - if (StrUtil.isNotEmpty(config.getPrivateCertContent())) {  
63 - // weixin-pay-java 存在 BUG,无法直接设置内容,所以创建临时文件来解决  
64 - payConfig.setPrivateCertPath(FileUtils.createTempFile(config.getPrivateCertContent()).getPath());  
65 - }  
66 - // 真实客户端  
67 - this.client = new WxPayServiceImpl();  
68 - client.setConfig(payConfig);  
69 - }  
70 -  
71 - @Override  
72 - public PayOrderUnifiedRespDTO doUnifiedOrder(PayOrderUnifiedReqDTO reqDTO) {  
73 - throw new UnsupportedOperationException();  
74 -// WxPayMpOrderResult response;  
75 -// try {  
76 -// switch (config.getApiVersion()) {  
77 -// case WXPayClientConfig.API_VERSION_V2:  
78 -// response = this.unifiedOrderV2(reqDTO);  
79 -// break;  
80 -// case WXPayClientConfig.API_VERSION_V3:  
81 -// WxPayUnifiedOrderV3Result.JsapiResult responseV3 = this.unifiedOrderV3(reqDTO);  
82 -// // 将 V3 的结果,统一转换成 V2。返回的字段是一致的  
83 -// response = new WxPayMpOrderResult();  
84 -// BeanUtil.copyProperties(responseV3, response, true);  
85 -// break;  
86 -// default:  
87 -// throw new IllegalArgumentException(String.format("未知的 API 版本(%s)", config.getApiVersion()));  
88 -// }  
89 -// } catch (WxPayException e) {  
90 -// log.error("[unifiedOrder][request({}) 发起支付失败,原因({})]", toJsonString(reqDTO), e);  
91 -// return PayCommonResult.build(ObjectUtils.defaultIfNull(e.getErrCode(), e.getReturnCode(), "CustomErrorCode"),  
92 -// ObjectUtils.defaultIfNull(e.getErrCodeDes(), e.getCustomErrorMsg()), null, codeMapping);  
93 -// }  
94 -// return PayCommonResult.build(CODE_SUCCESS, MESSAGE_SUCCESS, response, codeMapping);  
95 - }  
96 -  
97 - private WxPayMpOrderResult unifiedOrderV2(PayOrderUnifiedReqDTO reqDTO) throws WxPayException {  
98 - // 构建 WxPayUnifiedOrderRequest 对象  
99 - WxPayUnifiedOrderRequest request = WxPayUnifiedOrderRequest.newBuilder()  
100 - .outTradeNo(reqDTO.getMerchantOrderId())  
101 - .body(reqDTO.getBody())  
102 - .totalFee(reqDTO.getAmount()) // 单位分  
103 - .timeExpire(DateUtil.format(reqDTO.getExpireTime(), "yyyyMMddHHmmss")) // v2的时间格式  
104 - .spbillCreateIp(reqDTO.getUserIp())  
105 - .openid(getOpenid(reqDTO))  
106 - .notifyUrl(reqDTO.getNotifyUrl())  
107 - .build();  
108 - // 执行请求  
109 - return client.createOrder(request);  
110 - }  
111 -  
112 - private WxPayUnifiedOrderV3Result.JsapiResult unifiedOrderV3(PayOrderUnifiedReqDTO reqDTO) throws WxPayException {  
113 - // 构建 WxPayUnifiedOrderRequest 对象  
114 - WxPayUnifiedOrderV3Request request = new WxPayUnifiedOrderV3Request();  
115 - request.setOutTradeNo(reqDTO.getMerchantOrderId());  
116 -  
117 - request.setDescription(reqDTO.getBody());  
118 - request.setAmount(new WxPayUnifiedOrderV3Request  
119 - .Amount()  
120 - .setTotal(reqDTO.getAmount())); // 单位分  
121 - request.setTimeExpire(DateUtil.format(Date.from(reqDTO.getExpireTime().atZone(ZoneId.systemDefault()).toInstant()), "yyyy-MM-dd'T'HH:mm:ssXXX")); // v3的时间格式  
122 - request.setPayer(new WxPayUnifiedOrderV3Request.Payer().setOpenid(getOpenid(reqDTO)));  
123 - request.setSceneInfo(new WxPayUnifiedOrderV3Request.SceneInfo().setPayerClientIp(reqDTO.getUserIp()));  
124 - request.setNotifyUrl(reqDTO.getNotifyUrl());  
125 - // 执行请求  
126 - return client.createOrderV3(TradeTypeEnum.JSAPI, request);  
127 - }  
128 -  
129 - private static String getOpenid(PayOrderUnifiedReqDTO reqDTO) {  
130 - String openid = MapUtil.getStr(reqDTO.getChannelExtras(), "openid");  
131 - if (StrUtil.isEmpty(openid)) {  
132 - throw new IllegalArgumentException("支付请求的 openid 不能为空!");  
133 - }  
134 - return openid;  
135 - }  
136 -  
137 - /**  
138 - *  
139 - * 微信支付回调 分 v2 和v3 的处理方式  
140 - *  
141 - * @param data 通知结果  
142 - * @return 支付回调对象  
143 - * @throws WxPayException 微信异常类  
144 - */  
145 -// @Override  
146 - public PayOrderNotifyRespDTO parseOrderNotify(PayNotifyReqDTO data) throws WxPayException {  
147 - log.info("[parseOrderNotify][微信支付回调data数据:{}]", data.getBody());  
148 - // 微信支付 v2 回调结果处理  
149 - switch (config.getApiVersion()) {  
150 - case WxPayClientConfig.API_VERSION_V2:  
151 - return parseOrderNotifyV2(data);  
152 - case WxPayClientConfig.API_VERSION_V3:  
153 - return parseOrderNotifyV3(data);  
154 - default:  
155 - throw new IllegalArgumentException(String.format("未知的 API 版本(%s)", config.getApiVersion()));  
156 - }  
157 - }  
158 -  
159 - private PayOrderNotifyRespDTO parseOrderNotifyV3(PayNotifyReqDTO data) throws WxPayException {  
160 - WxPayOrderNotifyV3Result wxPayOrderNotifyV3Result = client.parseOrderNotifyV3Result(data.getBody(), null);  
161 - WxPayOrderNotifyV3Result.DecryptNotifyResult result = wxPayOrderNotifyV3Result.getResult();  
162 - // 转换结果  
163 - Assert.isTrue(Objects.equals(wxPayOrderNotifyV3Result.getResult().getTradeState(), "SUCCESS"),  
164 - "支付结果非 SUCCESS");  
165 -  
166 - return PayOrderNotifyRespDTO  
167 - .builder()  
168 - .orderExtensionNo(result.getOutTradeNo())  
169 - .channelOrderNo(result.getTransactionId())  
170 - .channelUserId(result.getPayer().getOpenid())  
171 - .successTime(LocalDateTimeUtil.parse(result.getSuccessTime(), "yyyy-MM-dd'T'HH:mm:ssXXX"))  
172 - .build();  
173 - }  
174 -  
175 - private PayOrderNotifyRespDTO parseOrderNotifyV2(PayNotifyReqDTO data) throws WxPayException {  
176 - WxPayOrderNotifyResult notifyResult = client.parseOrderNotifyResult(data.getBody());  
177 - Assert.isTrue(Objects.equals(notifyResult.getResultCode(), "SUCCESS"), "支付结果非 SUCCESS");  
178 - // 转换结果  
179 - return PayOrderNotifyRespDTO  
180 - .builder()  
181 - .orderExtensionNo(notifyResult.getOutTradeNo())  
182 - .channelOrderNo(notifyResult.getTransactionId())  
183 - .channelUserId(notifyResult.getOpenid())  
184 - .successTime(LocalDateTimeUtil.parse(notifyResult.getTimeEnd(), "yyyyMMddHHmmss"))  
185 - .build();  
186 -  
187 - }  
188 -  
189 - @Override  
190 - protected PayRefundUnifiedRespDTO doUnifiedRefund(PayRefundUnifiedReqDTO reqDTO) {  
191 - //TODO 需要实现  
192 - throw new UnsupportedOperationException();  
193 - }  
194 -  
195 } 20 }
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/weixin/WxPubPayClient.java
@@ -28,6 +28,10 @@ public class WxPubPayClient extends AbstractWxPayClient { @@ -28,6 +28,10 @@ public class WxPubPayClient extends AbstractWxPayClient {
28 super(channelId, PayChannelEnum.WX_PUB.getCode(), config); 28 super(channelId, PayChannelEnum.WX_PUB.getCode(), config);
29 } 29 }
30 30
  31 + protected WxPubPayClient(Long channelId, String channelCode, WxPayClientConfig config) {
  32 + super(channelId, channelCode, config);
  33 + }
  34 +
31 @Override 35 @Override
32 protected void doInit() { 36 protected void doInit() {
33 super.doInit(WxPayConstants.TradeType.JSAPI); 37 super.doInit(WxPayConstants.TradeType.JSAPI);