mirror of
				https://github.com/YunaiV/ruoyi-vue-pro.git
				synced 2025-10-31 02:28:03 +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 如果不添加在 项目启动的时候去初始化会报错无法启动。所以我手动加了两个,具体需要你来配 | ||||
|         switch (channelEnum) { | ||||
|             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_NATIVE: return (AbstractPayClient<Config>) new WXNativePayClient(channelId, (WxPayClientConfig) 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; | ||||
|  | ||||
| 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 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 java.time.ZoneId; | ||||
| import java.util.Date; | ||||
| import java.util.Objects; | ||||
|  | ||||
| /** | ||||
|  * 微信小程序下支付 | ||||
|  * 微信支付(小程序)的 PayClient 实现类 | ||||
|  * | ||||
|  * 由于公众号和小程序的微信支付逻辑一致,所以直接进行继承 | ||||
|  * | ||||
|  * @author zwy | ||||
|  */ | ||||
| @Slf4j | ||||
| public class WXLitePayClient extends AbstractPayClient<WxPayClientConfig> { | ||||
|  | ||||
|     private WxPayService client; | ||||
| public class WXLitePayClient extends WxPubPayClient { | ||||
|  | ||||
|     public WXLitePayClient(Long channelId, WxPayClientConfig 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); | ||||
|     } | ||||
|  | ||||
|     protected WxPubPayClient(Long channelId, String channelCode, WxPayClientConfig config) { | ||||
|         super(channelId, channelCode, config); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     protected void doInit() { | ||||
|         super.doInit(WxPayConstants.TradeType.JSAPI); | ||||
|  | ||||
		Reference in New Issue
	
	Block a user
	 YunaiV
					YunaiV