Эх сурвалжийг харах

mall + pay:
1. 增加微信 bar 和 native 的集成测试,方便调试配置

YunaiV 1 жил өмнө
parent
commit
7caf8e900f
13 өөрчлөгдсөн 265 нэмэгдсэн , 51 устгасан
  1. 9 1
      yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/dto/refund/PayRefundUnifiedReqDTO.java
  2. 2 1
      yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/alipay/AbstractAlipayPayClient.java
  3. 51 0
      yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/weixin/AbstractWxPayClient.java
  4. 0 7
      yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/weixin/WxAppPayClient.java
  5. 0 7
      yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/weixin/WxBarPayClient.java
  6. 0 7
      yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/weixin/WxH5PayClient.java
  7. 2 9
      yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/weixin/WxNativePayClient.java
  8. 0 8
      yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/weixin/WxPubPayClient.java
  9. 111 0
      yudao-framework/yudao-spring-boot-starter-biz-pay/src/test/java/cn/iocoder/yudao/framework/pay/core/client/impl/weixin/WxBarPayClientIntegrationTest.java
  10. 85 0
      yudao-framework/yudao-spring-boot-starter-biz-pay/src/test/java/cn/iocoder/yudao/framework/pay/core/client/impl/weixin/WxNativePayClientIntegrationTest.java
  11. 3 2
      yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/refund/PayRefundServiceImpl.java
  12. 2 2
      yudao-module-pay/yudao-module-pay-biz/src/test/java/cn/iocoder/yudao/module/pay/service/order/PayOrderServiceTest.java
  13. 0 7
      yudao-module-pay/yudao-module-pay-biz/src/test/java/cn/iocoder/yudao/module/pay/service/refund/PayRefundServiceTest.java

+ 9 - 1
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/dto/refund/PayRefundUnifiedReqDTO.java

@@ -45,12 +45,20 @@ public class PayRefundUnifiedReqDTO {
     @NotEmpty(message = "退款原因不能为空")
     private String reason;
 
+    /**
+     * 支付金额,单位:分
+     *
+     * 目前微信支付在退款的时候,必须传递该字段
+     */
+    @NotNull(message = "支付金额不能为空")
+    @DecimalMin(value = "0", inclusive = false, message = "支付金额必须大于零")
+    private Integer payPrice;
     /**
      * 退款金额,单位:分
      */
     @NotNull(message = "退款金额不能为空")
     @DecimalMin(value = "0", inclusive = false, message = "支付金额必须大于零")
-    private Integer price;
+    private Integer refundPrice;
 
     /**
      * 退款结果的 notify 回调地址

+ 2 - 1
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/alipay/AbstractAlipayPayClient.java

@@ -67,7 +67,7 @@ public abstract class AbstractAlipayPayClient extends AbstractPayClient<AlipayPa
         AlipayTradeRefundModel model = new AlipayTradeRefundModel();
         model.setOutTradeNo(reqDTO.getOutTradeNo());
         model.setOutRequestNo(reqDTO.getOutRefundNo());
-        model.setRefundAmount(formatAmount(reqDTO.getPrice()));
+        model.setRefundAmount(formatAmount(reqDTO.getRefundPrice()));
         model.setRefundReason(reqDTO.getReason());
         // 1.2 构建 AlipayTradePayRequest 请求
         AlipayTradeRefundRequest request = new AlipayTradeRefundRequest();
@@ -75,6 +75,7 @@ public abstract class AbstractAlipayPayClient extends AbstractPayClient<AlipayPa
         try {
             // 2.1 执行请求
             AlipayTradeRefundResponse response =  client.execute(request);
+            // 2.2 创建返回结果
             PayRefundRespDTO refund = new PayRefundRespDTO()
                     .setOutRefundNo(reqDTO.getOutRefundNo())
                     .setRawData(response);

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

@@ -9,10 +9,15 @@ import cn.iocoder.yudao.framework.common.util.io.FileUtils;
 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.order.PayOrderUnifiedRespDTO;
+import cn.iocoder.yudao.framework.pay.core.client.dto.refund.PayRefundRespDTO;
+import cn.iocoder.yudao.framework.pay.core.client.dto.refund.PayRefundUnifiedReqDTO;
 import cn.iocoder.yudao.framework.pay.core.client.impl.AbstractPayClient;
 import cn.iocoder.yudao.framework.pay.core.enums.PayFrameworkErrorCodeConstants;
+import cn.iocoder.yudao.framework.pay.core.enums.refund.PayRefundStatusRespEnum;
 import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyResult;
 import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyV3Result;
+import com.github.binarywang.wxpay.bean.request.WxPayRefundRequest;
+import com.github.binarywang.wxpay.bean.result.WxPayRefundResult;
 import com.github.binarywang.wxpay.config.WxPayConfig;
 import com.github.binarywang.wxpay.exception.WxPayException;
 import com.github.binarywang.wxpay.service.WxPayService;
@@ -80,6 +85,7 @@ public abstract class AbstractWxPayClient extends AbstractPayClient<WxPayClientC
                     throw new IllegalArgumentException(String.format("未知的 API 版本(%s)", config.getApiVersion()));
             }
         } catch (WxPayException e) {
+            // todo 芋艿:异常的处理;
             throw buildUnifiedOrderException(reqDTO, e);
         }
     }
@@ -102,6 +108,51 @@ public abstract class AbstractWxPayClient extends AbstractPayClient<WxPayClientC
     protected abstract PayOrderUnifiedRespDTO doUnifiedOrderV3(PayOrderUnifiedReqDTO reqDTO)
             throws WxPayException;
 
+    @Override
+    protected PayRefundRespDTO doUnifiedRefund(PayRefundUnifiedReqDTO reqDTO) throws Throwable {
+        try {
+            switch (config.getApiVersion()) {
+                case WxPayClientConfig.API_VERSION_V2:
+                    return doUnifiedRefundV2(reqDTO);
+                case WxPayClientConfig.API_VERSION_V3:
+                    return doUnifiedRefundV3(reqDTO);
+                default:
+                    throw new IllegalArgumentException(String.format("未知的 API 版本(%s)", config.getApiVersion()));
+            }
+        } catch (WxPayException e) {
+            // todo 芋艿:异常的处理;
+            throw buildUnifiedOrderException(null, e);
+        }
+    }
+
+    private PayRefundRespDTO doUnifiedRefundV2(PayRefundUnifiedReqDTO reqDTO) throws Throwable {
+        // 1. 构建 WxPayRefundRequest 请求
+        WxPayRefundRequest request = new WxPayRefundRequest()
+                .setOutTradeNo(reqDTO.getOutTradeNo())
+                .setOutRefundNo(reqDTO.getOutRefundNo())
+                .setRefundFee(reqDTO.getRefundPrice())
+                .setRefundDesc(reqDTO.getReason())
+                .setTotalFee(reqDTO.getPayPrice())
+                .setNotifyUrl(reqDTO.getNotifyUrl());
+        // 2.1 执行请求
+        WxPayRefundResult response = client.refundV2(request); // TODO 芋艿:可以分成 V2 和 V3 的退款接口
+        // 2.2 创建返回结果
+        PayRefundRespDTO refund = new PayRefundRespDTO()
+                .setOutRefundNo(reqDTO.getOutRefundNo())
+                .setRawData(response);
+        if (Objects.equals("SUCCESS", response.getResultCode())) {
+            refund.setStatus(PayRefundStatusRespEnum.WAITING.getStatus());
+            refund.setChannelRefundNo(response.getRefundId());
+        } else {
+            refund.setStatus(PayRefundStatusRespEnum.FAILURE.getStatus());
+            // TODO 芋艿;异常的处理;
+        }
+        return refund;
+    }
+
+    private PayRefundRespDTO doUnifiedRefundV3(PayRefundUnifiedReqDTO reqDTO) throws Throwable {
+        return null;
+    }
 
     @Override
     public Object parseNotify(Map<String, String> params, String body) {

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

@@ -2,8 +2,6 @@ package cn.iocoder.yudao.framework.pay.core.client.impl.weixin;
 
 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.PayRefundRespDTO;
-import cn.iocoder.yudao.framework.pay.core.client.dto.refund.PayRefundUnifiedReqDTO;
 import cn.iocoder.yudao.framework.pay.core.enums.channel.PayChannelEnum;
 import com.github.binarywang.wxpay.constant.WxPayConstants;
 import com.github.binarywang.wxpay.exception.WxPayException;
@@ -20,11 +18,6 @@ public class WxAppPayClient extends AbstractWxPayClient {
         super.doInit(WxPayConstants.TradeType.APP);
     }
 
-    @Override
-    protected PayRefundRespDTO doUnifiedRefund(PayRefundUnifiedReqDTO reqDTO) throws Throwable {
-        return null;
-    }
-
     @Override
     protected PayOrderUnifiedRespDTO doUnifiedOrderV2(PayOrderUnifiedReqDTO reqDTO) throws WxPayException {
         return null;

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

@@ -8,8 +8,6 @@ import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
 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.order.PayOrderUnifiedRespDTO;
-import cn.iocoder.yudao.framework.pay.core.client.dto.refund.PayRefundRespDTO;
-import cn.iocoder.yudao.framework.pay.core.client.dto.refund.PayRefundUnifiedReqDTO;
 import cn.iocoder.yudao.framework.pay.core.enums.channel.PayChannelEnum;
 import cn.iocoder.yudao.framework.pay.core.enums.order.PayOrderDisplayModeEnum;
 import cn.iocoder.yudao.framework.pay.core.enums.order.PayOrderStatusRespEnum;
@@ -104,11 +102,6 @@ public class WxBarPayClient extends AbstractWxPayClient {
         return doUnifiedOrderV2(reqDTO);
     }
 
-    @Override
-    protected PayRefundRespDTO doUnifiedRefund(PayRefundUnifiedReqDTO reqDTO) {
-        return null;
-    }
-
     // ========== 各种工具方法 ==========
 
     static String getAuthCode(PayOrderUnifiedReqDTO reqDTO) {

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

@@ -2,8 +2,6 @@ package cn.iocoder.yudao.framework.pay.core.client.impl.weixin;
 
 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.PayRefundRespDTO;
-import cn.iocoder.yudao.framework.pay.core.client.dto.refund.PayRefundUnifiedReqDTO;
 import cn.iocoder.yudao.framework.pay.core.enums.channel.PayChannelEnum;
 import com.github.binarywang.wxpay.constant.WxPayConstants;
 import com.github.binarywang.wxpay.exception.WxPayException;
@@ -20,11 +18,6 @@ public class WxH5PayClient extends AbstractWxPayClient {
         super.doInit(WxPayConstants.TradeType.MWEB);
     }
 
-    @Override
-    protected PayRefundRespDTO doUnifiedRefund(PayRefundUnifiedReqDTO reqDTO) throws Throwable {
-        return null;
-    }
-
     @Override
     protected PayOrderUnifiedRespDTO doUnifiedOrderV2(PayOrderUnifiedReqDTO reqDTO) throws WxPayException {
         return null;

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

@@ -2,8 +2,6 @@ package cn.iocoder.yudao.framework.pay.core.client.impl.weixin;
 
 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.PayRefundRespDTO;
-import cn.iocoder.yudao.framework.pay.core.client.dto.refund.PayRefundUnifiedReqDTO;
 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.WxPayNativeOrderResult;
@@ -65,16 +63,11 @@ public class WxNativePayClient extends AbstractWxPayClient {
         request.setSceneInfo(new WxPayUnifiedOrderV3Request.SceneInfo().setPayerClientIp(reqDTO.getUserIp()));
         request.setNotifyUrl(reqDTO.getNotifyUrl());
         // 执行请求
-        WxPayNativeOrderResult response = client.createOrderV3(TradeTypeEnum.NATIVE, request);
+        String response = client.createOrderV3(TradeTypeEnum.NATIVE, request);
 
         // 转换结果
         return new PayOrderUnifiedRespDTO(PayOrderDisplayModeEnum.QR_CODE.getMode(),
-                response.getCodeUrl());
-    }
-
-    @Override
-    protected PayRefundRespDTO doUnifiedRefund(PayRefundUnifiedReqDTO reqDTO) throws Throwable {
-        return null;
+                response);
     }
 
 }

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

@@ -5,8 +5,6 @@ import cn.hutool.core.util.StrUtil;
 import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
 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.PayRefundRespDTO;
-import cn.iocoder.yudao.framework.pay.core.client.dto.refund.PayRefundUnifiedReqDTO;
 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;
@@ -83,12 +81,6 @@ public class WxPubPayClient extends AbstractWxPayClient {
                 JsonUtils.toJsonString(response));
     }
 
-    @Override
-    protected PayRefundRespDTO doUnifiedRefund(PayRefundUnifiedReqDTO reqDTO) {
-        // TODO 需要实现
-        throw new UnsupportedOperationException();
-    }
-
     // ========== 各种工具方法 ==========
 
     static String getOpenid(PayOrderUnifiedReqDTO reqDTO) {

+ 111 - 0
yudao-framework/yudao-spring-boot-starter-biz-pay/src/test/java/cn/iocoder/yudao/framework/pay/core/client/impl/weixin/WxBarPayClientIntegrationTest.java

@@ -0,0 +1,111 @@
+package cn.iocoder.yudao.framework.pay.core.client.impl.weixin;
+
+import cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils;
+import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
+import com.github.binarywang.wxpay.bean.request.WxPayMicropayRequest;
+import com.github.binarywang.wxpay.bean.request.WxPayRefundRequest;
+import com.github.binarywang.wxpay.bean.request.WxPayRefundV3Request;
+import com.github.binarywang.wxpay.bean.result.WxPayMicropayResult;
+import com.github.binarywang.wxpay.bean.result.WxPayRefundResult;
+import com.github.binarywang.wxpay.bean.result.WxPayRefundV3Result;
+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 org.junit.jupiter.api.Disabled;
+import org.junit.jupiter.api.Test;
+
+import java.time.Duration;
+
+import static cn.iocoder.yudao.framework.pay.core.client.impl.weixin.AbstractWxPayClient.formatDateV2;
+
+/**
+ * {@link WxBarPayClient} 的集成测试,用于快速调试微信条码支付
+ *
+ * @author 芋道源码
+ */
+@Disabled
+public class WxBarPayClientIntegrationTest {
+
+    @Test
+    public void testPayV2() throws WxPayException {
+        // 创建 config 配置
+        WxPayConfig config = buildWxPayConfigV2();
+        // 创建 WxPayService 客户端
+        WxPayService client = new WxPayServiceImpl();
+        client.setConfig(config);
+
+        // 执行发起支付
+        WxPayMicropayRequest request = WxPayMicropayRequest.newBuilder()
+                .outTradeNo(String.valueOf(System.currentTimeMillis()))
+                .body("测试支付-body")
+                .detail("测试支付-detail")
+                .totalFee(1) // 单位分
+                .timeExpire(formatDateV2(LocalDateTimeUtils.addTime(Duration.ofMinutes(2))))
+                .spbillCreateIp("127.0.0.1")
+                .authCode("131276541518138032")
+                .build();
+        System.out.println("========= request ==========");
+        System.out.println(JsonUtils.toJsonPrettyString(request));
+        WxPayMicropayResult response = client.micropay(request);
+        System.out.println("========= response ==========");
+        System.out.println(JsonUtils.toJsonPrettyString(response));
+    }
+
+    @Test
+    public void testRefundV2() throws WxPayException {
+        // 创建 config 配置
+        WxPayConfig config = buildWxPayConfigV2();
+        // 创建 WxPayService 客户端
+        WxPayService client = new WxPayServiceImpl();
+        client.setConfig(config);
+
+        // 执行发起退款
+        WxPayRefundRequest request = new WxPayRefundRequest()
+                .setOutTradeNo("1689504162805")
+                .setOutRefundNo(String.valueOf(System.currentTimeMillis()))
+                .setRefundFee(1)
+                .setRefundDesc("就是想退了")
+                .setTotalFee(1);
+        System.out.println("========= request ==========");
+        System.out.println(JsonUtils.toJsonPrettyString(request));
+        WxPayRefundResult response = client.refund(request);
+        System.out.println("========= response ==========");
+        System.out.println(JsonUtils.toJsonPrettyString(response));
+    }
+
+    @Test
+    public void testRefundV3() throws WxPayException {
+        // 创建 config 配置
+        WxPayConfig config = buildWxPayConfigV2();
+        // 创建 WxPayService 客户端
+        WxPayService client = new WxPayServiceImpl();
+        client.setConfig(config);
+
+        // 执行发起退款
+        WxPayRefundV3Request request = new WxPayRefundV3Request()
+                .setOutTradeNo("1689506325635")
+                .setOutRefundNo(String.valueOf(System.currentTimeMillis()))
+                .setAmount(new WxPayRefundV3Request.Amount().setTotal(1).setRefund(1).setCurrency("CNY"))
+                .setReason("就是想退了");
+        System.out.println("========= request ==========");
+        System.out.println(JsonUtils.toJsonPrettyString(request));
+        WxPayRefundV3Result response = client.refundV3(request);
+        System.out.println("========= response ==========");
+        System.out.println(JsonUtils.toJsonPrettyString(response));
+    }
+
+    private WxPayConfig buildWxPayConfigV2() {
+        WxPayConfig config = new WxPayConfig();
+        config.setAppId("wx62056c0d5e8db250");
+        config.setMchId("1545083881");
+        config.setMchKey("dS1ngeN63JLr3NRbvPH9AJy3MyUxZdim");
+        config.setSignType(WxPayConstants.SignType.MD5);
+        config.setKeyPath("/Users/yunai/Downloads/wx_pay/apiclient_cert.p12");
+        config.setPrivateCertPath("/Users/yunai/Downloads/wx_pay/apiclient_cert.pem");
+        config.setPrivateKeyPath("/Users/yunai/Downloads/wx_pay/apiclient_key.pem");
+        return config;
+    }
+
+}

+ 85 - 0
yudao-framework/yudao-spring-boot-starter-biz-pay/src/test/java/cn/iocoder/yudao/framework/pay/core/client/impl/weixin/WxNativePayClientIntegrationTest.java

@@ -0,0 +1,85 @@
+package cn.iocoder.yudao.framework.pay.core.client.impl.weixin;
+
+import cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils;
+import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
+import com.github.binarywang.wxpay.bean.request.WxPayRefundV3Request;
+import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderV3Request;
+import com.github.binarywang.wxpay.bean.result.WxPayRefundV3Result;
+import com.github.binarywang.wxpay.bean.result.enums.TradeTypeEnum;
+import com.github.binarywang.wxpay.config.WxPayConfig;
+import com.github.binarywang.wxpay.exception.WxPayException;
+import com.github.binarywang.wxpay.service.WxPayService;
+import com.github.binarywang.wxpay.service.impl.WxPayServiceImpl;
+import org.junit.jupiter.api.Disabled;
+import org.junit.jupiter.api.Test;
+
+import java.time.Duration;
+
+import static cn.iocoder.yudao.framework.pay.core.client.impl.weixin.AbstractWxPayClient.formatDateV3;
+
+/**
+ * {@link WxNativePayClient} 的集成测试,用于快速调试微信扫码支付
+ *
+ * @author 芋道源码
+ */
+@Disabled
+public class WxNativePayClientIntegrationTest {
+
+    @Test
+    public void testPayV3() throws WxPayException {
+        // 创建 config 配置
+        WxPayConfig config = buildWxPayConfigV3();
+        // 创建 WxPayService 客户端
+        WxPayService client = new WxPayServiceImpl();
+        client.setConfig(config);
+
+        // 执行发起支付
+        WxPayUnifiedOrderV3Request request = new WxPayUnifiedOrderV3Request()
+                .setOutTradeNo(String.valueOf(System.currentTimeMillis()))
+                .setDescription("测试支付-body")
+                .setAmount(new WxPayUnifiedOrderV3Request.Amount().setTotal(1)) // 单位分
+                .setTimeExpire(formatDateV3(LocalDateTimeUtils.addTime(Duration.ofMinutes(2))))
+                .setSceneInfo(new WxPayUnifiedOrderV3Request.SceneInfo().setPayerClientIp("127.0.0.1"))
+                .setNotifyUrl("http://127.0.0.1:48080");
+        System.out.println("========= request ==========");
+        System.out.println(JsonUtils.toJsonPrettyString(request));
+        String response = client.createOrderV3(TradeTypeEnum.NATIVE, request);
+        System.out.println("========= response ==========");
+        System.out.println(JsonUtils.toJsonPrettyString(response));
+    }
+
+    @Test
+    public void testRefundV3() throws WxPayException {
+        // 创建 config 配置
+        WxPayConfig config = buildWxPayConfigV3();
+        // 创建 WxPayService 客户端
+        WxPayService client = new WxPayServiceImpl();
+        client.setConfig(config);
+
+        // 执行发起退款
+        WxPayRefundV3Request request = new WxPayRefundV3Request()
+                .setOutTradeNo("1689506153043")
+                .setOutRefundNo(String.valueOf(System.currentTimeMillis()))
+                .setAmount(new WxPayRefundV3Request.Amount().setTotal(1).setRefund(1).setCurrency("CNY"))
+                .setReason("就是想退了");
+        System.out.println("========= request ==========");
+        System.out.println(JsonUtils.toJsonPrettyString(request));
+        WxPayRefundV3Result response = client.refundV3(request);
+        System.out.println("========= response ==========");
+        System.out.println(JsonUtils.toJsonPrettyString(response));
+    }
+
+    private WxPayConfig buildWxPayConfigV3() {
+        WxPayConfig config = new WxPayConfig();
+        config.setAppId("wx62056c0d5e8db250");
+        config.setMchId("1545083881");
+        config.setMchKey("dS1ngeN63JLr3NRbvPH9AJy3MyUxZdim");
+        config.setApiV3Key("459arNsYHl1mgkiO6H9ZH5KkhFXSxaA4");
+//        config.setCertSerialNo(serialNo);
+        config.setKeyPath("/Users/yunai/Downloads/wx_pay/apiclient_cert.p12");
+        config.setPrivateCertPath("/Users/yunai/Downloads/wx_pay/apiclient_cert.pem");
+        config.setPrivateKeyPath("/Users/yunai/Downloads/wx_pay/apiclient_key.pem");
+        return config;
+    }
+
+}

+ 3 - 2
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/refund/PayRefundServiceImpl.java

@@ -129,8 +129,9 @@ public class PayRefundServiceImpl implements PayRefundService {
         refundMapper.insert(refund);
         // 2.2 向渠道发起退款申请
         PayOrderExtensionDO orderExtension = orderExtensionService.getOrderExtension(order.getSuccessExtensionId());
-        PayRefundUnifiedReqDTO unifiedReqDTO = new PayRefundUnifiedReqDTO();
-        unifiedReqDTO.setPrice(reqDTO.getPrice())
+        PayRefundUnifiedReqDTO unifiedReqDTO = new PayRefundUnifiedReqDTO()
+                .setPayPrice(order.getPrice())
+                .setRefundPrice(reqDTO.getPrice())
                 .setOutTradeNo(orderExtension.getNo())
                 .setOutRefundNo(refund.getNo())
                 .setNotifyUrl(genChannelPayNotifyUrl(channel)) // TODO 芋艿:优化下 notifyUrl

+ 2 - 2
yudao-module-pay/yudao-module-pay-biz/src/test/java/cn/iocoder/yudao/module/pay/service/order/PayOrderServiceTest.java

@@ -87,7 +87,7 @@ public class PayOrderServiceTest extends BaseDbUnitTest {
             o.setSuccessExtensionId(1L);
             o.setRefundStatus(PayOrderRefundStatusEnum.NO.getStatus());
             o.setRefundTimes(0);
-            o.setRefundPrice(0L);
+            o.setRefundPrice(0);
             o.setChannelUserId("1008611");
             o.setChannelOrderNo(channelOrderId);
             o.setUpdateTime(LocalDateTime.of(2018, 1, 1, 10, 10, 15));
@@ -155,7 +155,7 @@ public class PayOrderServiceTest extends BaseDbUnitTest {
             o.setSuccessExtensionId(1L);
             o.setRefundStatus(PayOrderRefundStatusEnum.NO.getStatus());
             o.setRefundTimes(0);
-            o.setRefundPrice(0L);
+            o.setRefundPrice(0);
             o.setChannelUserId("1008611");
             o.setChannelOrderNo(channelOrderId);
             o.setUpdateTime(LocalDateTime.of(2018, 1, 1, 10, 10, 15));

+ 0 - 7
yudao-module-pay/yudao-module-pay-biz/src/test/java/cn/iocoder/yudao/module/pay/service/refund/PayRefundServiceTest.java

@@ -68,7 +68,6 @@ public class PayRefundServiceTest extends BaseDbUnitTest {
             o.setNotifyUrl("https://www.cancanzi.com");
             o.setNotifyStatus(PayOrderNotifyStatusEnum.SUCCESS.getStatus());
             o.setStatus(PayRefundStatusEnum.SUCCESS.getStatus());
-            o.setType(PayOrderRefundStatusEnum.PART.getStatus());
             o.setPayPrice(100);
             o.setRefundPrice(500);
             o.setReason("就是想退款了,你有意见吗");
@@ -93,8 +92,6 @@ public class PayRefundServiceTest extends BaseDbUnitTest {
                 cloneIgnoreId(dbRefund, o -> o.setNotifyStatus(PayOrderNotifyStatusEnum.FAILURE.getStatus())));
         // 测试 status 不匹配
         refundMapper.insert(cloneIgnoreId(dbRefund, o -> o.setStatus(PayRefundStatusEnum.FAILURE.getStatus())));
-        // 测试 type 不匹配
-        refundMapper.insert(cloneIgnoreId(dbRefund, o -> o.setType(PayOrderRefundStatusEnum.ALL.getStatus())));
         // 测试 createTime 不匹配
         refundMapper.insert(cloneIgnoreId(dbRefund, o ->
                 o.setCreateTime(LocalDateTime.of(2022, 1, 1, 10, 10, 10))));
@@ -105,7 +102,6 @@ public class PayRefundServiceTest extends BaseDbUnitTest {
         reqVO.setMerchantRefundNo("MRF0000001");
         reqVO.setNotifyStatus(PayOrderNotifyStatusEnum.SUCCESS.getStatus());
         reqVO.setStatus(PayRefundStatusEnum.SUCCESS.getStatus());
-        reqVO.setType(PayOrderRefundStatusEnum.PART.getStatus());
         reqVO.setCreateTime((new LocalDateTime[]{LocalDateTime.of(2021, 1, 1, 10, 10, 10), LocalDateTime.of(2021, 1, 1, 10, 10, 12)}));
 
         // 调用
@@ -130,7 +126,6 @@ public class PayRefundServiceTest extends BaseDbUnitTest {
             o.setNotifyUrl("https://www.cancanzi.com");
             o.setNotifyStatus(PayOrderNotifyStatusEnum.SUCCESS.getStatus());
             o.setStatus(PayRefundStatusEnum.SUCCESS.getStatus());
-            o.setType(PayOrderRefundStatusEnum.PART.getStatus());
             o.setPayPrice(100);
             o.setRefundPrice(500);
             o.setReason("就是想退款了,你有意见吗");
@@ -155,8 +150,6 @@ public class PayRefundServiceTest extends BaseDbUnitTest {
                 cloneIgnoreId(dbRefund, o -> o.setNotifyStatus(PayOrderNotifyStatusEnum.FAILURE.getStatus())));
         // 测试 status 不匹配
         refundMapper.insert(cloneIgnoreId(dbRefund, o -> o.setStatus(PayRefundStatusEnum.FAILURE.getStatus())));
-        // 测试 type 不匹配
-        refundMapper.insert(cloneIgnoreId(dbRefund, o -> o.setType(PayOrderRefundStatusEnum.ALL.getStatus())));
         // 测试 createTime 不匹配
         refundMapper.insert(cloneIgnoreId(dbRefund, o ->
                 o.setCreateTime(LocalDateTime.of(2022, 1, 1, 10, 10, 10))));