Browse Source

1. 微信 App 支付 WxAppPayClient 实现
2. 优化微信支付的下单逻辑,增加 build request 公用方法

YunaiV 1 year ago
parent
commit
3a1694dea3

+ 35 - 0
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/weixin/AbstractWxPayClient.java

@@ -113,6 +113,41 @@ public abstract class AbstractWxPayClient extends AbstractPayClient<WxPayClientC
     protected abstract PayOrderRespDTO doUnifiedOrderV3(PayOrderUnifiedReqDTO reqDTO)
             throws WxPayException;
 
+    /**
+     * 【V2】创建微信下单请求
+     *
+     * @param reqDTO 下信息
+     * @return 下单请求
+     */
+    protected WxPayUnifiedOrderRequest buildPayUnifiedOrderRequestV2(PayOrderUnifiedReqDTO reqDTO) {
+        return WxPayUnifiedOrderRequest.newBuilder()
+                .outTradeNo(reqDTO.getOutTradeNo())
+                .body(reqDTO.getSubject())
+                .detail(reqDTO.getBody())
+                .totalFee(reqDTO.getPrice()) // 单位分
+                .timeExpire(formatDateV2(reqDTO.getExpireTime()))
+                .spbillCreateIp(reqDTO.getUserIp())
+                .notifyUrl(reqDTO.getNotifyUrl())
+                .build();
+    }
+
+    /**
+     * 【V3】创建微信下单请求
+     *
+     * @param reqDTO 下信息
+     * @return 下单请求
+     */
+    protected WxPayUnifiedOrderV3Request buildPayUnifiedOrderRequestV3(PayOrderUnifiedReqDTO reqDTO) {
+        WxPayUnifiedOrderV3Request request = new WxPayUnifiedOrderV3Request();
+        request.setOutTradeNo(reqDTO.getOutTradeNo());
+        request.setDescription(reqDTO.getSubject());
+        request.setAmount(new WxPayUnifiedOrderV3Request.Amount().setTotal(reqDTO.getPrice())); // 单位分
+        request.setTimeExpire(formatDateV3(reqDTO.getExpireTime()));
+        request.setSceneInfo(new WxPayUnifiedOrderV3Request.SceneInfo().setPayerClientIp(reqDTO.getUserIp()));
+        request.setNotifyUrl(reqDTO.getNotifyUrl());
+        return request;
+    }
+
     @Override
     public PayOrderRespDTO doParseOrderNotify(Map<String, String> params, String body) throws WxPayException {
         switch (config.getApiVersion()) {

+ 35 - 3
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/weixin/WxAppPayClient.java

@@ -3,10 +3,28 @@ package cn.iocoder.yudao.framework.pay.core.client.impl.weixin;
 import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderRespDTO;
 import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderUnifiedReqDTO;
 import cn.iocoder.yudao.framework.pay.core.enums.channel.PayChannelEnum;
+import cn.iocoder.yudao.framework.pay.core.enums.order.PayOrderDisplayModeEnum;
+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.constant.WxPayConstants;
 import com.github.binarywang.wxpay.exception.WxPayException;
+import lombok.extern.slf4j.Slf4j;
 
-// TODO 芋艿:未实现
+import static cn.iocoder.yudao.framework.common.util.json.JsonUtils.toJsonString;
+
+/**
+ * 微信支付【App 支付】的 PayClient 实现类
+ *
+ * 文档:<a href="https://pay.weixin.qq.com/wiki/doc/apiv3/open/pay/chapter2_5_3.shtml">App 支付</a>
+ *
+ * // TODO 芋艿:未详细测试,因为手头没 App
+ *
+ * @author 芋道源码
+ */
+@Slf4j
 public class WxAppPayClient extends AbstractWxPayClient {
 
     public WxAppPayClient(Long channelId, WxPayClientConfig config) {
@@ -20,12 +38,26 @@ public class WxAppPayClient extends AbstractWxPayClient {
 
     @Override
     protected PayOrderRespDTO doUnifiedOrderV2(PayOrderUnifiedReqDTO reqDTO) throws WxPayException {
-        return null;
+        // 构建 WxPayUnifiedOrderRequest 对象
+        WxPayUnifiedOrderRequest request = buildPayUnifiedOrderRequestV2(reqDTO);
+        // 执行请求
+        WxPayMpOrderResult response = client.createOrder(request);
+
+        // 转换结果
+        return PayOrderRespDTO.waitingOf(PayOrderDisplayModeEnum.APP.getMode(), toJsonString(response),
+                reqDTO.getOutTradeNo(), response);
     }
 
     @Override
     protected PayOrderRespDTO doUnifiedOrderV3(PayOrderUnifiedReqDTO reqDTO) throws WxPayException {
-        return null;
+        // 构建 WxPayUnifiedOrderV3Request 对象
+        WxPayUnifiedOrderV3Request request = buildPayUnifiedOrderRequestV3(reqDTO);
+        // 执行请求
+        WxPayUnifiedOrderV3Result.JsapiResult response = client.createOrderV3(TradeTypeEnum.APP, request);
+
+        // 转换结果
+        return PayOrderRespDTO.waitingOf(PayOrderDisplayModeEnum.APP.getMode(), toJsonString(response),
+                reqDTO.getOutTradeNo(), response);
     }
 
 }

+ 3 - 18
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/weixin/WxNativePayClient.java

@@ -34,16 +34,7 @@ public class WxNativePayClient extends AbstractWxPayClient {
     @Override
     protected PayOrderRespDTO doUnifiedOrderV2(PayOrderUnifiedReqDTO reqDTO) throws WxPayException {
         // 构建 WxPayUnifiedOrderRequest 对象
-        WxPayUnifiedOrderRequest request = WxPayUnifiedOrderRequest.newBuilder()
-                .outTradeNo(reqDTO.getOutTradeNo())
-                .body(reqDTO.getSubject())
-                .detail(reqDTO.getBody())
-                .totalFee(reqDTO.getPrice()) // 单位分
-                .productId(reqDTO.getOutTradeNo())
-                .timeExpire(formatDateV2(reqDTO.getExpireTime()))
-                .spbillCreateIp(reqDTO.getUserIp())
-                .notifyUrl(reqDTO.getNotifyUrl())
-                .build();
+        WxPayUnifiedOrderRequest request = buildPayUnifiedOrderRequestV2(reqDTO);
         // 执行请求
         WxPayNativeOrderResult response = client.createOrder(request);
 
@@ -54,14 +45,8 @@ public class WxNativePayClient extends AbstractWxPayClient {
 
     @Override
     protected PayOrderRespDTO doUnifiedOrderV3(PayOrderUnifiedReqDTO reqDTO) throws WxPayException {
-        // 构建 WxPayUnifiedOrderRequest 对象
-        WxPayUnifiedOrderV3Request request = new WxPayUnifiedOrderV3Request()
-                .setOutTradeNo(reqDTO.getOutTradeNo())
-                .setDescription(reqDTO.getSubject())
-                .setAmount(new WxPayUnifiedOrderV3Request.Amount().setTotal(reqDTO.getPrice())) // 单位分
-                .setTimeExpire(formatDateV3(reqDTO.getExpireTime()))
-                .setSceneInfo(new WxPayUnifiedOrderV3Request.SceneInfo().setPayerClientIp(reqDTO.getUserIp()))
-                .setNotifyUrl(reqDTO.getNotifyUrl());
+        // 构建 WxPayUnifiedOrderV3Request 对象
+        WxPayUnifiedOrderV3Request request = buildPayUnifiedOrderRequestV3(reqDTO);
         // 执行请求
         String response = client.createOrderV3(TradeTypeEnum.NATIVE, request);
 

+ 4 - 19
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/weixin/WxPubPayClient.java

@@ -4,7 +4,6 @@ import cn.hutool.core.map.MapUtil;
 import cn.hutool.core.util.StrUtil;
 import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderRespDTO;
 import cn.iocoder.yudao.framework.pay.core.client.dto.order.PayOrderUnifiedReqDTO;
-import cn.iocoder.yudao.framework.pay.core.client.dto.refund.PayRefundRespDTO;
 import cn.iocoder.yudao.framework.pay.core.enums.channel.PayChannelEnum;
 import cn.iocoder.yudao.framework.pay.core.enums.order.PayOrderDisplayModeEnum;
 import com.github.binarywang.wxpay.bean.order.WxPayMpOrderResult;
@@ -45,16 +44,8 @@ public class WxPubPayClient extends AbstractWxPayClient {
     @Override
     protected PayOrderRespDTO doUnifiedOrderV2(PayOrderUnifiedReqDTO reqDTO) throws WxPayException {
         // 构建 WxPayUnifiedOrderRequest 对象
-        WxPayUnifiedOrderRequest request = WxPayUnifiedOrderRequest.newBuilder()
-                .outTradeNo(reqDTO.getOutTradeNo())
-                .body(reqDTO.getSubject())
-                .detail(reqDTO.getBody())
-                .totalFee(reqDTO.getPrice()) // 单位分
-                .timeExpire(formatDateV2(reqDTO.getExpireTime()))
-                .spbillCreateIp(reqDTO.getUserIp())
-                .openid(getOpenid(reqDTO))
-                .notifyUrl(reqDTO.getNotifyUrl())
-                .build();
+        WxPayUnifiedOrderRequest request = buildPayUnifiedOrderRequestV2(reqDTO)
+                .setOpenid(getOpenid(reqDTO));
         // 执行请求
         WxPayMpOrderResult response = client.createOrder(request);
 
@@ -66,14 +57,8 @@ public class WxPubPayClient extends AbstractWxPayClient {
     @Override
     protected PayOrderRespDTO doUnifiedOrderV3(PayOrderUnifiedReqDTO reqDTO) throws WxPayException {
         // 构建 WxPayUnifiedOrderRequest 对象
-        WxPayUnifiedOrderV3Request request = new WxPayUnifiedOrderV3Request();
-        request.setOutTradeNo(reqDTO.getOutTradeNo());
-        request.setDescription(reqDTO.getSubject());
-        request.setAmount(new WxPayUnifiedOrderV3Request.Amount().setTotal(reqDTO.getPrice())); // 单位分
-        request.setTimeExpire(formatDateV3(reqDTO.getExpireTime()));
-        request.setPayer(new WxPayUnifiedOrderV3Request.Payer().setOpenid(getOpenid(reqDTO)));
-        request.setSceneInfo(new WxPayUnifiedOrderV3Request.SceneInfo().setPayerClientIp(reqDTO.getUserIp()));
-        request.setNotifyUrl(reqDTO.getNotifyUrl());
+        WxPayUnifiedOrderV3Request request = buildPayUnifiedOrderRequestV3(reqDTO)
+                .setPayer(new WxPayUnifiedOrderV3Request.Payer().setOpenid(getOpenid(reqDTO)));
         // 执行请求
         WxPayUnifiedOrderV3Result.JsapiResult response = client.createOrderV3(TradeTypeEnum.JSAPI, request);
 

+ 14 - 1
yudao-ui-admin/src/views/pay/cashier/index.vue

@@ -212,6 +212,16 @@ export default {
         return;
       }
 
+      // 微信公众号、小程序支付,无法在 PC 网页中进行
+      if (channelCode === PayChannelEnum.WX_PUB.code) {
+        this.$message.error('微信公众号支付:不支持 PC 网站');
+        return;
+      }
+      if (channelCode === PayChannelEnum.WX_LITE.code) {
+        this.$message.error('微信小程序:不支持 PC 网站');
+        return;
+      }
+
       // 默认的提交处理
       this.submit0(channelCode)
     },
@@ -292,7 +302,10 @@ export default {
     /** 提交支付后(App) */
     displayApp(channelCode, data) {
       if (channelCode === PayChannelEnum.ALIPAY_APP.code) {
-        this.$message.error('支付宝 App 无法在网页支付!');
+        this.$message.error('支付宝 App 支付:无法在网页支付!');
+      }
+      if (channelCode === PayChannelEnum.WX_APP.code) {
+        this.$message.error('微信 App 支付:无法在网页支付!');
       }
       this.submitLoading = false
     },