mirror of
				https://github.com/YunaiV/ruoyi-vue-pro.git
				synced 2025-10-31 10:37:41 +08:00 
			
		
		
		
	mall + pay:
1、调整微信 Lite 小程序支付的实现
This commit is contained in:
		| @ -61,7 +61,7 @@ public class PayClientFactoryImpl implements PayClientFactory { | |||||||
|         // TODO @芋艿 WX_LITE WX_APP 如果不添加在 项目启动的时候去初始化会报错无法启动。所以我手动加了两个,具体需要你来配 |         // TODO @芋艿 WX_LITE WX_APP 如果不添加在 项目启动的时候去初始化会报错无法启动。所以我手动加了两个,具体需要你来配 | ||||||
|         switch (channelEnum) { |         switch (channelEnum) { | ||||||
|             case WX_PUB: return (AbstractPayClient<Config>) new WxPubPayClient(channelId, (WxPayClientConfig) config); |             case WX_PUB: return (AbstractPayClient<Config>) new WxPubPayClient(channelId, (WxPayClientConfig) config); | ||||||
|             case WX_LITE: return (AbstractPayClient<Config>) new WXLitePayClient(channelId, (WxPayClientConfig) config); //微信小程序请求支付 |             case WX_LITE: return (AbstractPayClient<Config>) new WXLitePayClient(channelId, (WxPayClientConfig) config); | ||||||
|             case WX_APP: return (AbstractPayClient<Config>) new WxPubPayClient(channelId, (WxPayClientConfig) config); |             case WX_APP: return (AbstractPayClient<Config>) new WxPubPayClient(channelId, (WxPayClientConfig) config); | ||||||
|             case WX_NATIVE: return (AbstractPayClient<Config>) new WXNativePayClient(channelId, (WxPayClientConfig) config); |             case WX_NATIVE: return (AbstractPayClient<Config>) new WXNativePayClient(channelId, (WxPayClientConfig) config); | ||||||
|             case ALIPAY_WAP: return (AbstractPayClient<Config>) new AlipayWapPayClient(channelId, (AlipayPayClientConfig) config); |             case ALIPAY_WAP: return (AbstractPayClient<Config>) new AlipayWapPayClient(channelId, (AlipayPayClientConfig) config); | ||||||
|  | |||||||
| @ -1,195 +1,20 @@ | |||||||
| package cn.iocoder.yudao.framework.pay.core.client.impl.weixin; | package cn.iocoder.yudao.framework.pay.core.client.impl.weixin; | ||||||
|  |  | ||||||
| import cn.hutool.core.bean.BeanUtil; |  | ||||||
| import cn.hutool.core.date.DateUtil; |  | ||||||
| import cn.hutool.core.date.LocalDateTimeUtil; |  | ||||||
| import cn.hutool.core.lang.Assert; |  | ||||||
| import cn.hutool.core.map.MapUtil; |  | ||||||
| import cn.hutool.core.util.StrUtil; |  | ||||||
| import cn.iocoder.yudao.framework.common.util.io.FileUtils; |  | ||||||
| import cn.iocoder.yudao.framework.pay.core.client.dto.notify.PayNotifyReqDTO; |  | ||||||
| import cn.iocoder.yudao.framework.pay.core.client.dto.notify.PayOrderNotifyRespDTO; |  | ||||||
| import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderUnifiedReqDTO; |  | ||||||
| import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderUnifiedRespDTO; |  | ||||||
| import cn.iocoder.yudao.framework.pay.core.client.dto.refund.PayRefundUnifiedReqDTO; |  | ||||||
| import cn.iocoder.yudao.framework.pay.core.client.dto.refund.PayRefundUnifiedRespDTO; |  | ||||||
| import cn.iocoder.yudao.framework.pay.core.client.impl.AbstractPayClient; |  | ||||||
| import cn.iocoder.yudao.framework.pay.core.enums.PayChannelEnum; | import cn.iocoder.yudao.framework.pay.core.enums.PayChannelEnum; | ||||||
| import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyResult; |  | ||||||
| import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyV3Result; |  | ||||||
| import com.github.binarywang.wxpay.bean.order.WxPayMpOrderResult; |  | ||||||
| import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderRequest; |  | ||||||
| import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderV3Request; |  | ||||||
| import com.github.binarywang.wxpay.bean.result.WxPayUnifiedOrderV3Result; |  | ||||||
| import com.github.binarywang.wxpay.bean.result.enums.TradeTypeEnum; |  | ||||||
| import com.github.binarywang.wxpay.config.WxPayConfig; |  | ||||||
| import com.github.binarywang.wxpay.constant.WxPayConstants; |  | ||||||
| import com.github.binarywang.wxpay.exception.WxPayException; |  | ||||||
| import com.github.binarywang.wxpay.service.WxPayService; |  | ||||||
| import com.github.binarywang.wxpay.service.impl.WxPayServiceImpl; |  | ||||||
| import lombok.extern.slf4j.Slf4j; | import lombok.extern.slf4j.Slf4j; | ||||||
|  |  | ||||||
| import java.time.ZoneId; |  | ||||||
| import java.util.Date; |  | ||||||
| import java.util.Objects; |  | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * 微信小程序下支付 |  * 微信支付(小程序)的 PayClient 实现类 | ||||||
|  |  * | ||||||
|  |  * 由于公众号和小程序的微信支付逻辑一致,所以直接进行继承 | ||||||
|  * |  * | ||||||
|  * @author zwy |  * @author zwy | ||||||
|  */ |  */ | ||||||
| @Slf4j | @Slf4j | ||||||
| public class WXLitePayClient extends AbstractPayClient<WxPayClientConfig> { | public class WXLitePayClient extends WxPubPayClient { | ||||||
|  |  | ||||||
|     private WxPayService client; |  | ||||||
|  |  | ||||||
|     public WXLitePayClient(Long channelId, WxPayClientConfig config) { |     public WXLitePayClient(Long channelId, WxPayClientConfig config) { | ||||||
|         super(channelId, PayChannelEnum.WX_LITE.getCode(), config); |         super(channelId, PayChannelEnum.WX_LITE.getCode(), config); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     @Override |  | ||||||
|     protected void doInit() { |  | ||||||
|         WxPayConfig payConfig = new WxPayConfig(); |  | ||||||
|         BeanUtil.copyProperties(config, payConfig, "privateKeyContent","privateCertContent"); |  | ||||||
|         payConfig.setTradeType(WxPayConstants.TradeType.JSAPI); // 设置使用 JS API 支付方式 |  | ||||||
| //        if (StrUtil.isNotEmpty(config.getKeyContent())) { |  | ||||||
| //            payConfig.setKeyContent(config.getKeyContent().getBytes(StandardCharsets.UTF_8)); |  | ||||||
| //        } |  | ||||||
|         if (StrUtil.isNotEmpty(config.getPrivateKeyContent())) { |  | ||||||
|             // weixin-pay-java 存在 BUG,无法直接设置内容,所以创建临时文件来解决 |  | ||||||
|             payConfig.setPrivateKeyPath(FileUtils.createTempFile(config.getPrivateKeyContent()).getPath()); |  | ||||||
|         } |  | ||||||
|         if (StrUtil.isNotEmpty(config.getPrivateCertContent())) { |  | ||||||
|             // weixin-pay-java 存在 BUG,无法直接设置内容,所以创建临时文件来解决 |  | ||||||
|             payConfig.setPrivateCertPath(FileUtils.createTempFile(config.getPrivateCertContent()).getPath()); |  | ||||||
|         } |  | ||||||
|         // 真实客户端 |  | ||||||
|         this.client = new WxPayServiceImpl(); |  | ||||||
|         client.setConfig(payConfig); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     @Override |  | ||||||
|     public PayOrderUnifiedRespDTO doUnifiedOrder(PayOrderUnifiedReqDTO reqDTO) { |  | ||||||
|         throw new UnsupportedOperationException(); |  | ||||||
| //        WxPayMpOrderResult response; |  | ||||||
| //        try { |  | ||||||
| //            switch (config.getApiVersion()) { |  | ||||||
| //                case WXPayClientConfig.API_VERSION_V2: |  | ||||||
| //                    response = this.unifiedOrderV2(reqDTO); |  | ||||||
| //                    break; |  | ||||||
| //                case WXPayClientConfig.API_VERSION_V3: |  | ||||||
| //                    WxPayUnifiedOrderV3Result.JsapiResult responseV3 = this.unifiedOrderV3(reqDTO); |  | ||||||
| //                    // 将 V3 的结果,统一转换成 V2。返回的字段是一致的 |  | ||||||
| //                    response = new WxPayMpOrderResult(); |  | ||||||
| //                    BeanUtil.copyProperties(responseV3, response, true); |  | ||||||
| //                    break; |  | ||||||
| //                default: |  | ||||||
| //                    throw new IllegalArgumentException(String.format("未知的 API 版本(%s)", config.getApiVersion())); |  | ||||||
| //            } |  | ||||||
| //        } catch (WxPayException e) { |  | ||||||
| //            log.error("[unifiedOrder][request({}) 发起支付失败,原因({})]", toJsonString(reqDTO), e); |  | ||||||
| //            return PayCommonResult.build(ObjectUtils.defaultIfNull(e.getErrCode(), e.getReturnCode(), "CustomErrorCode"), |  | ||||||
| //                    ObjectUtils.defaultIfNull(e.getErrCodeDes(), e.getCustomErrorMsg()), null, codeMapping); |  | ||||||
| //        } |  | ||||||
| //        return PayCommonResult.build(CODE_SUCCESS, MESSAGE_SUCCESS, response, codeMapping); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     private WxPayMpOrderResult unifiedOrderV2(PayOrderUnifiedReqDTO reqDTO) throws WxPayException { |  | ||||||
|         // 构建 WxPayUnifiedOrderRequest 对象 |  | ||||||
|         WxPayUnifiedOrderRequest request = WxPayUnifiedOrderRequest.newBuilder() |  | ||||||
|                 .outTradeNo(reqDTO.getMerchantOrderId()) |  | ||||||
|                 .body(reqDTO.getBody()) |  | ||||||
|                 .totalFee(reqDTO.getAmount()) // 单位分 |  | ||||||
|                 .timeExpire(DateUtil.format(reqDTO.getExpireTime(), "yyyyMMddHHmmss")) // v2的时间格式 |  | ||||||
|                 .spbillCreateIp(reqDTO.getUserIp()) |  | ||||||
|                 .openid(getOpenid(reqDTO)) |  | ||||||
|                 .notifyUrl(reqDTO.getNotifyUrl()) |  | ||||||
|                 .build(); |  | ||||||
|         // 执行请求 |  | ||||||
|         return client.createOrder(request); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     private WxPayUnifiedOrderV3Result.JsapiResult unifiedOrderV3(PayOrderUnifiedReqDTO reqDTO) throws WxPayException { |  | ||||||
|         // 构建 WxPayUnifiedOrderRequest 对象 |  | ||||||
|         WxPayUnifiedOrderV3Request request = new WxPayUnifiedOrderV3Request(); |  | ||||||
|         request.setOutTradeNo(reqDTO.getMerchantOrderId()); |  | ||||||
|  |  | ||||||
|         request.setDescription(reqDTO.getBody()); |  | ||||||
|         request.setAmount(new WxPayUnifiedOrderV3Request |  | ||||||
|                 .Amount() |  | ||||||
|                 .setTotal(reqDTO.getAmount())); // 单位分 |  | ||||||
|         request.setTimeExpire(DateUtil.format(Date.from(reqDTO.getExpireTime().atZone(ZoneId.systemDefault()).toInstant()), "yyyy-MM-dd'T'HH:mm:ssXXX")); // v3的时间格式 |  | ||||||
|         request.setPayer(new WxPayUnifiedOrderV3Request.Payer().setOpenid(getOpenid(reqDTO))); |  | ||||||
|         request.setSceneInfo(new WxPayUnifiedOrderV3Request.SceneInfo().setPayerClientIp(reqDTO.getUserIp())); |  | ||||||
|         request.setNotifyUrl(reqDTO.getNotifyUrl()); |  | ||||||
|         // 执行请求 |  | ||||||
|         return client.createOrderV3(TradeTypeEnum.JSAPI, request); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     private static String getOpenid(PayOrderUnifiedReqDTO reqDTO) { |  | ||||||
|         String openid = MapUtil.getStr(reqDTO.getChannelExtras(), "openid"); |  | ||||||
|         if (StrUtil.isEmpty(openid)) { |  | ||||||
|             throw new IllegalArgumentException("支付请求的 openid 不能为空!"); |  | ||||||
|         } |  | ||||||
|         return openid; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     /** |  | ||||||
|      * |  | ||||||
|      * 微信支付回调 分 v2 和v3 的处理方式 |  | ||||||
|      * |  | ||||||
|      * @param data 通知结果 |  | ||||||
|      * @return 支付回调对象 |  | ||||||
|      * @throws WxPayException 微信异常类 |  | ||||||
|      */ |  | ||||||
| //    @Override |  | ||||||
|     public PayOrderNotifyRespDTO parseOrderNotify(PayNotifyReqDTO data) throws WxPayException { |  | ||||||
|         log.info("[parseOrderNotify][微信支付回调data数据:{}]", data.getBody()); |  | ||||||
|         // 微信支付 v2 回调结果处理 |  | ||||||
|         switch (config.getApiVersion()) { |  | ||||||
|             case WxPayClientConfig.API_VERSION_V2: |  | ||||||
|                 return parseOrderNotifyV2(data); |  | ||||||
|             case WxPayClientConfig.API_VERSION_V3: |  | ||||||
|                 return parseOrderNotifyV3(data); |  | ||||||
|             default: |  | ||||||
|                 throw new IllegalArgumentException(String.format("未知的 API 版本(%s)", config.getApiVersion())); |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     private PayOrderNotifyRespDTO parseOrderNotifyV3(PayNotifyReqDTO data) throws WxPayException { |  | ||||||
|         WxPayOrderNotifyV3Result wxPayOrderNotifyV3Result = client.parseOrderNotifyV3Result(data.getBody(), null); |  | ||||||
|         WxPayOrderNotifyV3Result.DecryptNotifyResult result = wxPayOrderNotifyV3Result.getResult(); |  | ||||||
|         // 转换结果 |  | ||||||
|         Assert.isTrue(Objects.equals(wxPayOrderNotifyV3Result.getResult().getTradeState(), "SUCCESS"), |  | ||||||
|                 "支付结果非 SUCCESS"); |  | ||||||
|  |  | ||||||
|         return PayOrderNotifyRespDTO |  | ||||||
|                 .builder() |  | ||||||
|                 .orderExtensionNo(result.getOutTradeNo()) |  | ||||||
|                 .channelOrderNo(result.getTransactionId()) |  | ||||||
|                 .channelUserId(result.getPayer().getOpenid()) |  | ||||||
|                 .successTime(LocalDateTimeUtil.parse(result.getSuccessTime(), "yyyy-MM-dd'T'HH:mm:ssXXX")) |  | ||||||
|                 .build(); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     private PayOrderNotifyRespDTO parseOrderNotifyV2(PayNotifyReqDTO data) throws WxPayException { |  | ||||||
|         WxPayOrderNotifyResult notifyResult = client.parseOrderNotifyResult(data.getBody()); |  | ||||||
|         Assert.isTrue(Objects.equals(notifyResult.getResultCode(), "SUCCESS"), "支付结果非 SUCCESS"); |  | ||||||
|         // 转换结果 |  | ||||||
|         return PayOrderNotifyRespDTO |  | ||||||
|                 .builder() |  | ||||||
|                 .orderExtensionNo(notifyResult.getOutTradeNo()) |  | ||||||
|                 .channelOrderNo(notifyResult.getTransactionId()) |  | ||||||
|                 .channelUserId(notifyResult.getOpenid()) |  | ||||||
|                 .successTime(LocalDateTimeUtil.parse(notifyResult.getTimeEnd(), "yyyyMMddHHmmss")) |  | ||||||
|                 .build(); |  | ||||||
|  |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     @Override |  | ||||||
|     protected PayRefundUnifiedRespDTO doUnifiedRefund(PayRefundUnifiedReqDTO reqDTO)  { |  | ||||||
|         //TODO 需要实现 |  | ||||||
|         throw new UnsupportedOperationException(); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
| } | } | ||||||
|  | |||||||
| @ -28,6 +28,10 @@ public class WxPubPayClient extends AbstractWxPayClient { | |||||||
|         super(channelId, PayChannelEnum.WX_PUB.getCode(), config); |         super(channelId, PayChannelEnum.WX_PUB.getCode(), config); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     protected WxPubPayClient(Long channelId, String channelCode, WxPayClientConfig config) { | ||||||
|  |         super(channelId, channelCode, config); | ||||||
|  |     } | ||||||
|  |  | ||||||
|     @Override |     @Override | ||||||
|     protected void doInit() { |     protected void doInit() { | ||||||
|         super.doInit(WxPayConstants.TradeType.JSAPI); |         super.doInit(WxPayConstants.TradeType.JSAPI); | ||||||
|  | |||||||
		Reference in New Issue
	
	Block a user
	 YunaiV
					YunaiV