瀏覽代碼

扫码支付统一退款单元测试, 修复退款失败,渠道错误未赋值bug

jason 1 年之前
父節點
當前提交
6fbf7b261b

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

@@ -148,7 +148,7 @@ public abstract class AbstractAlipayPayClient extends AbstractPayClient<AlipayPa
         // 2.1 执行请求
         AlipayTradeRefundResponse response = client.execute(request);
         if (!response.isSuccess()) {
-            return PayRefundRespDTO.failureOf(reqDTO.getOutRefundNo(), response);
+            return PayRefundRespDTO.failureOf(response.getSubCode(), response.getSubMsg(), reqDTO.getOutRefundNo(), response);
         }
         // 2.2 创建返回结果
         // 支付宝只要退款调用返回 success,就认为退款成功,不需要回调。具体可见 parseNotify 方法的说明。

+ 135 - 6
yudao-framework/yudao-spring-boot-starter-biz-pay/src/test/java/cn/iocoder/yudao/framework/pay/core/client/impl/alipay/AlipayQrPayClientTest.java

@@ -1,5 +1,6 @@
 package cn.iocoder.yudao.framework.pay.core.client.impl.alipay;
 
+import cn.hutool.core.date.LocalDateTimeUtil;
 import cn.hutool.core.util.RandomUtil;
 import cn.hutool.core.util.ReflectUtil;
 import cn.iocoder.yudao.framework.common.exception.ServiceException;
@@ -7,19 +8,27 @@ import cn.iocoder.yudao.framework.common.exception.enums.GlobalErrorCodeConstant
 import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil;
 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.client.dto.refund.PayRefundUnifiedReqDTO;
 import cn.iocoder.yudao.framework.pay.core.client.exception.PayException;
 import cn.iocoder.yudao.framework.pay.core.enums.order.PayOrderDisplayModeEnum;
+import cn.iocoder.yudao.framework.pay.core.enums.refund.PayRefundStatusRespEnum;
 import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest;
 import com.alipay.api.AlipayApiException;
 import com.alipay.api.DefaultAlipayClient;
+import com.alipay.api.domain.AlipayTradeRefundModel;
 import com.alipay.api.request.AlipayTradePrecreateRequest;
+import com.alipay.api.request.AlipayTradeRefundRequest;
 import com.alipay.api.response.AlipayTradePrecreateResponse;
+import com.alipay.api.response.AlipayTradeRefundResponse;
+import org.junit.jupiter.api.DisplayName;
 import org.junit.jupiter.api.Test;
 import org.mockito.ArgumentMatcher;
 import org.mockito.InjectMocks;
 import org.mockito.Mock;
 
 import javax.validation.ConstraintViolationException;
+import java.util.Date;
 
 import static cn.iocoder.yudao.framework.pay.core.client.impl.alipay.AlipayPayClientConfig.MODE_PUBLIC_KEY;
 import static cn.iocoder.yudao.framework.pay.core.enums.order.PayOrderStatusRespEnum.CLOSED;
@@ -51,13 +60,14 @@ public class AlipayQrPayClientTest extends BaseMockitoUnitTest {
     private DefaultAlipayClient defaultAlipayClient;
 
     @Test
-    public void testDoInit() {
+    public void test_do_init() {
         client.doInit();
         assertNotSame(defaultAlipayClient, ReflectUtil.getFieldValue(client, "defaultAlipayClient"));
     }
 
     @Test
-    public void testUnifiedOrderSuccess() throws AlipayApiException {
+    @DisplayName("支付包扫描支付下单成功")
+    public void test_unified_order_success() throws AlipayApiException {
         // 准备返回对象
         String notifyUrl = randomURL();
         String qrCode = randomString();
@@ -84,7 +94,8 @@ public class AlipayQrPayClientTest extends BaseMockitoUnitTest {
     }
 
     @Test
-    public void testUnifiedOrderChannelFailed() throws AlipayApiException {
+    @DisplayName("支付包扫描支付,渠道返回失败")
+    public void test_unified_order_channel_failed() throws AlipayApiException {
         String notifyUrl = randomURL();
         String subCode = randomString();
         String subMsg = randomString();
@@ -110,7 +121,8 @@ public class AlipayQrPayClientTest extends BaseMockitoUnitTest {
     }
 
     @Test
-    public void test_unifiedOrder_throw_pay_exception() throws AlipayApiException {
+    @DisplayName("支付包扫描支付,抛出系统异常")
+    public void test_unified_order_throw_pay_exception() throws AlipayApiException {
         // 准备请求参数
         String outTradeNo = randomString();
         String notifyUrl = randomURL();
@@ -126,7 +138,8 @@ public class AlipayQrPayClientTest extends BaseMockitoUnitTest {
     }
 
     @Test
-    public void test_unifiedOrder_throw_service_exception() throws AlipayApiException {
+    @DisplayName("支付包扫描支付,抛出业务异常")
+    public void test_unified_order_throw_service_exception() throws AlipayApiException {
         // 准备请求参数
         String outTradeNo = randomString();
         String notifyUrl = randomURL();
@@ -142,7 +155,8 @@ public class AlipayQrPayClientTest extends BaseMockitoUnitTest {
     }
 
     @Test
-    public void test_unifiedOrder_param_validate() {
+    @DisplayName("支付包扫描支付,参数校验不通过")
+    public void test_unified_order_param_validate() {
         // 准备请求参数
         String outTradeNo = randomString();
         String notifyUrl = randomURL();
@@ -162,4 +176,119 @@ public class AlipayQrPayClientTest extends BaseMockitoUnitTest {
             o.setBody(RandomUtil.randomString(32));
         });
     }
+
+    @Test
+    @DisplayName("支付包扫描退款成功")
+    public void test_unified_refund_success() throws AlipayApiException {
+        // 准备返回对象
+        String notifyUrl = randomURL();
+        Date refundTime = randomDate();
+        String outRefundNo = randomString();
+        String outTradeNo = randomString();
+        Integer refundAmount = randomInteger();
+        AlipayTradeRefundResponse response = randomPojo(AlipayTradeRefundResponse.class, o -> {
+            o.setSubCode("");
+            o.setGmtRefundPay(refundTime);
+        });
+        // mock
+        when(defaultAlipayClient.execute(argThat((ArgumentMatcher<AlipayTradeRefundRequest>) request -> {
+            assertInstanceOf(AlipayTradeRefundModel.class, request.getBizModel());
+            AlipayTradeRefundModel bizModel = (AlipayTradeRefundModel) request.getBizModel();
+            assertEquals(outRefundNo, bizModel.getOutRequestNo());
+            assertEquals(outTradeNo, bizModel.getOutTradeNo());
+            assertEquals(String.valueOf(refundAmount / 100.0), bizModel.getRefundAmount());
+            return true;
+        }))).thenReturn(response);
+        // 准备请求参数
+        PayRefundUnifiedReqDTO refundReqDTO = randomPojo(PayRefundUnifiedReqDTO.class, o -> {
+            o.setOutRefundNo(outRefundNo);
+            o.setOutTradeNo(outTradeNo);
+            o.setNotifyUrl(notifyUrl);
+            o.setRefundPrice(refundAmount);
+        });
+        PayRefundRespDTO resp = client.unifiedRefund(refundReqDTO);
+        // 断言
+        assertEquals(PayRefundStatusRespEnum.SUCCESS.getStatus(), resp.getStatus());
+        assertNull(resp.getChannelRefundNo());
+        assertEquals(LocalDateTimeUtil.of(refundTime), resp.getSuccessTime());
+        assertEquals(outRefundNo, resp.getOutRefundNo());
+        assertSame(response, resp.getRawData());
+    }
+
+    @Test
+    @DisplayName("支付包扫描退款,渠道返回失败")
+    public void test_unified_refund_channel_failed() throws AlipayApiException {
+        // 准备返回对象
+        String notifyUrl = randomURL();
+        String subCode = randomString();
+        String subMsg = randomString();
+        AlipayTradeRefundResponse response = randomPojo(AlipayTradeRefundResponse.class, o -> {
+            o.setSubCode(subCode);
+            o.setSubMsg(subMsg);
+        });
+        // mock
+        when(defaultAlipayClient.execute(argThat((ArgumentMatcher<AlipayTradeRefundRequest>) request -> {
+            assertInstanceOf(AlipayTradeRefundModel.class, request.getBizModel());
+            return true;
+        }))).thenReturn(response);
+        // 准备请求参数
+        String outRefundNo = randomString();
+        String outTradeNo = randomString();
+        PayRefundUnifiedReqDTO refundReqDTO = randomPojo(PayRefundUnifiedReqDTO.class, o -> {
+            o.setOutRefundNo(outRefundNo);
+            o.setOutTradeNo(outTradeNo);
+            o.setNotifyUrl(notifyUrl);
+        });
+        PayRefundRespDTO resp = client.unifiedRefund(refundReqDTO);
+        // 断言
+        assertEquals(PayRefundStatusRespEnum.FAILURE.getStatus(), resp.getStatus());
+        assertNull(resp.getChannelRefundNo());
+        assertEquals(subCode, resp.getChannelErrorCode());
+        assertEquals(subMsg, resp.getChannelErrorMsg());
+        assertNull(resp.getSuccessTime());
+        assertEquals(outRefundNo, resp.getOutRefundNo());
+        assertSame(response, resp.getRawData());
+    }
+
+    @Test
+    @DisplayName("支付包扫描退款,参数校验不通过")
+    public void test_unified_refund_param_validate() {
+        // 准备请求参数
+        String notifyUrl = randomURL();
+        PayRefundUnifiedReqDTO refundReqDTO = randomPojo(PayRefundUnifiedReqDTO.class, o -> {
+            o.setOutTradeNo("");
+            o.setNotifyUrl(notifyUrl);
+        });
+        // 断言
+        assertThrows(ConstraintViolationException.class, () -> client.unifiedRefund(refundReqDTO));
+    }
+
+    @Test
+    @DisplayName("支付包扫描退款,抛出业务异常")
+    public void test_unified_refund_throw_service_exception() throws AlipayApiException {
+        // mock
+        when(defaultAlipayClient.execute(argThat((ArgumentMatcher<AlipayTradeRefundRequest>) request -> true)))
+                .thenThrow(ServiceExceptionUtil.exception(GlobalErrorCodeConstants.INTERNAL_SERVER_ERROR));
+        // 准备请求参数
+        String notifyUrl = randomURL();
+        PayRefundUnifiedReqDTO refundReqDTO = randomPojo(PayRefundUnifiedReqDTO.class, o -> {
+            o.setNotifyUrl(notifyUrl);
+        });
+        // 断言
+        assertThrows(ServiceException.class, () -> client.unifiedRefund(refundReqDTO));
+    }
+    @Test
+    @DisplayName("支付包扫描退款,抛出系统异常")
+    public void test_unified_refund_throw_pay_exception() throws AlipayApiException {
+        // mock
+        when(defaultAlipayClient.execute(argThat((ArgumentMatcher<AlipayTradeRefundRequest>) request -> true)))
+                .thenThrow(new RuntimeException("系统异常"));
+        // 准备请求参数
+        String notifyUrl = randomURL();
+        PayRefundUnifiedReqDTO refundReqDTO = randomPojo(PayRefundUnifiedReqDTO.class, o -> {
+            o.setNotifyUrl(notifyUrl);
+        });
+        // 断言
+        assertThrows(PayException.class, () -> client.unifiedRefund(refundReqDTO));
+    }
 }

+ 2 - 4
yudao-module-mall/yudao-module-promotion-biz/src/test/java/cn/iocoder/yudao/module/promotion/service/decorate/DecorateComponentServiceImplTest.java

@@ -7,16 +7,14 @@ import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
 import org.mockito.InjectMocks;
 import org.mockito.Mock;
-import org.mockito.Mockito;
 
 import java.util.ArrayList;
 import java.util.List;
 
 import static cn.iocoder.yudao.module.promotion.enums.decorate.DecorateComponentEnum.ROLLING_NEWS;
 import static cn.iocoder.yudao.module.promotion.enums.decorate.DecoratePageEnum.INDEX;
-import static org.mockito.ArgumentMatchers.eq;
 
-// TODO @芋艿:后续 review 下
+// TODO 待完成  @芋艿:后续 review 下
 /**
  * @author jason
  */
@@ -41,6 +39,6 @@ public class DecorateComponentServiceImplTest extends BaseMockitoUnitTest {
                 .setCode(ROLLING_NEWS.getCode()).setId(1L);
         list.add(decorateDO);
         //mock 方法
-        Mockito.when(decorateComponentMapper.selectListByPageAndStatus(eq(1))).thenReturn(list);
+        //Mockito.when(decorateComponentMapper.selectListByPageAndStatus(eq(1))).thenReturn(list);
     }
 }