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

by gateway: 支付应用的代码优化

zhijiantianya@gmail.com 1 жил өмнө
parent
commit
052e4689ee
22 өөрчлөгдсөн 142 нэмэгдсэн , 184 устгасан
  1. 4 0
      yudao-framework/yudao-spring-boot-starter-test/src/main/java/cn/iocoder/yudao/framework/test/core/util/RandomUtils.java
  2. 2 1
      yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/enums/ErrorCodeConstants.java
  3. 6 33
      yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/app/PayAppController.java
  4. 9 5
      yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/app/vo/PayAppBaseVO.java
  5. 2 2
      yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/app/vo/PayAppPageItemRespVO.java
  6. 2 11
      yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/app/vo/PayAppPageReqVO.java
  7. 1 1
      yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/app/vo/PayAppRespVO.java
  8. 1 1
      yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/app/vo/PayAppUpdateReqVO.java
  9. 3 3
      yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/app/vo/PayAppUpdateStatusReqVO.java
  10. 14 1
      yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/convert/app/PayAppConvert.java
  11. 6 8
      yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/mysql/app/PayAppMapper.java
  12. 2 11
      yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/mysql/order/PayOrderMapper.java
  13. 3 6
      yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/mysql/refund/PayRefundMapper.java
  14. 8 9
      yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/app/PayAppService.java
  15. 30 54
      yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/app/PayAppServiceImpl.java
  16. 8 0
      yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/order/PayOrderService.java
  17. 5 0
      yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/order/PayOrderServiceImpl.java
  18. 8 0
      yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/refund/PayRefundService.java
  19. 5 0
      yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/refund/PayRefundServiceImpl.java
  20. 22 17
      yudao-module-pay/yudao-module-pay-biz/src/test/java/cn/iocoder/yudao/module/pay/service/app/PayAppServiceTest.java
  21. 0 1
      yudao-module-pay/yudao-module-pay-biz/src/test/resources/sql/clean.sql
  22. 1 20
      yudao-module-pay/yudao-module-pay-biz/src/test/resources/sql/create_tables.sql

+ 4 - 0
yudao-framework/yudao-spring-boot-starter-test/src/main/java/cn/iocoder/yudao/framework/test/core/util/RandomUtils.java

@@ -102,6 +102,10 @@ public class RandomUtils {
         return randomString() + "@qq.com";
     }
 
+    public static String randomURL() {
+        return "https://www.iocoder.cn/" + randomString();
+    }
+
     @SafeVarargs
     public static <T> T randomPojo(Class<T> clazz, Consumer<T>... consumers) {
         T pojo = PODAM_FACTORY.manufacturePojo(clazz);

+ 2 - 1
yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/enums/ErrorCodeConstants.java

@@ -12,7 +12,8 @@ public interface ErrorCodeConstants {
     // ========== APP 模块 1007000000 ==========
     ErrorCode PAY_APP_NOT_FOUND = new ErrorCode(1007000000, "App 不存在");
     ErrorCode PAY_APP_IS_DISABLE = new ErrorCode(1007000002, "App 已经被禁用");
-    ErrorCode PAY_APP_EXIST_TRANSACTION_ORDER_CANT_DELETE =  new ErrorCode(1007000003, "支付应用存在交易中的订单,无法删除");
+    ErrorCode PAY_APP_EXIST_ORDER_CANT_DELETE =  new ErrorCode(1007000003, "支付应用存在支付订单,无法删除");
+    ErrorCode PAY_APP_EXIST_REFUND_CANT_DELETE =  new ErrorCode(1007000004, "支付应用存在退款订单,无法删除");
 
     // ========== CHANNEL 模块 1007001000 ==========
     ErrorCode PAY_CHANNEL_NOT_FOUND = new ErrorCode(1007001000, "支付渠道的配置不存在");

+ 6 - 33
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/app/PayAppController.java

@@ -24,6 +24,7 @@ import javax.validation.Valid;
 import java.util.*;
 
 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
+import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
 
 @Slf4j
 @Tag(name = "管理后台 - 支付应用信息")
@@ -78,15 +79,6 @@ public class PayAppController {
         return success(PayAppConvert.INSTANCE.convert(app));
     }
 
-    @GetMapping("/list")
-    @Operation(summary = "获得支付应用信息列表")
-    @Parameter(name = "ids", description = "编号列表", required = true, example = "1024,2048")
-    @PreAuthorize("@ss.hasPermission('pay:app:query')")
-    public CommonResult<List<PayAppRespVO>> getAppList(@RequestParam("ids") Collection<Long> ids) {
-        List<PayAppDO> list = appService.getAppList(ids);
-        return success(PayAppConvert.INSTANCE.convertList(list));
-    }
-
     @GetMapping("/page")
     @Operation(summary = "获得支付应用信息分页")
     @PreAuthorize("@ss.hasPermission('pay:app:query')")
@@ -94,34 +86,15 @@ public class PayAppController {
         // 得到应用分页列表
         PageResult<PayAppDO> pageResult = appService.getAppPage(pageVO);
         if (CollUtil.isEmpty(pageResult.getList())) {
-            return success(new PageResult<>(pageResult.getTotal()));
+            return success(PageResult.empty());
         }
 
         // 得到所有的应用编号,查出所有的渠道
-        Collection<Long> payAppIds = CollectionUtils.convertList(pageResult.getList(), PayAppDO::getId);
-        List<PayChannelDO> channels = channelService.getChannelListByAppIds(payAppIds);
-        // TODO @aquan:可以基于 appId 简历一个 multiMap。这样下面,直接 get 到之后,CollUtil buildSet 即可
-        Iterator<PayChannelDO> iterator = channels.iterator();
-
-        // 利用反射将渠道数据复制到返回的数据结构中去
-        List<PayAppPageItemRespVO> appList = new ArrayList<>(pageResult.getList().size());
-        pageResult.getList().forEach(app -> {
-            // 写入应用信息的数据
-            PayAppPageItemRespVO respVO = PayAppConvert.INSTANCE.pageConvert(app);
-            // 写入支付渠道信息的数据
-            Set<String> channelCodes = new HashSet<>(PayChannelEnum.values().length);
-            while (iterator.hasNext()) {
-                PayChannelDO channelDO = iterator.next();
-                if (channelDO.getAppId().equals(app.getId())) {
-                    channelCodes.add(channelDO.getCode());
-                    iterator.remove();
-                }
-            }
-            respVO.setChannelCodes(channelCodes);
-            appList.add(respVO);
-        });
+        Collection<Long> appIds = convertList(pageResult.getList(), PayAppDO::getId);
+        List<PayChannelDO> channels = channelService.getChannelListByAppIds(appIds);
 
-        return success(new PageResult<>(appList, pageResult.getTotal()));
+        // 拼接后返回
+        return success(PayAppConvert.INSTANCE.convertPage(pageResult, channels));
     }
 
 }

+ 9 - 5
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/app/vo/PayAppBaseVO.java

@@ -1,6 +1,8 @@
 package cn.iocoder.yudao.module.pay.controller.admin.app.vo;
 import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.*;
+import org.hibernate.validator.constraints.URL;
+
 import javax.validation.constraints.*;
 
 /**
@@ -10,23 +12,25 @@ import javax.validation.constraints.*;
 @Data
 public class PayAppBaseVO {
 
-    @Schema(description = "应用名", requiredMode = Schema.RequiredMode.REQUIRED)
+    @Schema(description = "应用名", requiredMode = Schema.RequiredMode.REQUIRED, example = "小豆")
     @NotNull(message = "应用名不能为空")
     private String name;
 
-    @Schema(description = "开启状态", requiredMode = Schema.RequiredMode.REQUIRED)
+    @Schema(description = "开启状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "0")
     @NotNull(message = "开启状态不能为空")
     private Integer status;
 
-    @Schema(description = "备注")
+    @Schema(description = "备注", example = "我是一个测试应用")
     private String remark;
 
-    @Schema(description = "支付结果的回调地址", requiredMode = Schema.RequiredMode.REQUIRED)
+    @Schema(description = "支付结果的回调地址", requiredMode = Schema.RequiredMode.REQUIRED, example = "http://127.0.0.1:48080/pay-callback")
     @NotNull(message = "支付结果的回调地址不能为空")
+    @URL(message = "支付结果的回调地址必须为 URL 格式")
     private String payNotifyUrl;
 
-    @Schema(description = "退款结果的回调地址", requiredMode = Schema.RequiredMode.REQUIRED)
+    @Schema(description = "退款结果的回调地址", requiredMode = Schema.RequiredMode.REQUIRED, example = "http://127.0.0.1:48080/refund-callback")
     @NotNull(message = "退款结果的回调地址不能为空")
+    @URL(message = "退款结果的回调地址必须为 URL 格式")
     private String refundNotifyUrl;
 
 }

+ 2 - 2
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/app/vo/PayAppPageItemRespVO.java

@@ -14,13 +14,13 @@ import java.util.Set;
 @ToString(callSuper = true)
 public class PayAppPageItemRespVO extends PayAppBaseVO {
 
-    @Schema(description = "应用编号", requiredMode = Schema.RequiredMode.REQUIRED)
+    @Schema(description = "应用编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
     private Long id;
 
     @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
     private LocalDateTime createTime;
 
-    @Schema(description = "渠道编码集合", requiredMode = Schema.RequiredMode.REQUIRED, example = "[alipay_pc, alipay_wap]")
+    @Schema(description = "已配置的支付渠道编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "[alipay_pc, alipay_wap]")
     private Set<String> channelCodes;
 
 }

+ 2 - 11
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/app/vo/PayAppPageReqVO.java

@@ -17,21 +17,12 @@ import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_
 @ToString(callSuper = true)
 public class PayAppPageReqVO extends PageParam {
 
-    @Schema(description = "应用名")
+    @Schema(description = "应用名", example = "小豆")
     private String name;
 
-    @Schema(description = "开启状态")
+    @Schema(description = "开启状态", example = "0")
     private Integer status;
 
-    @Schema(description = "备注")
-    private String remark;
-
-    @Schema(description = "支付结果的回调地址")
-    private String payNotifyUrl;
-
-    @Schema(description = "退款结果的回调地址")
-    private String refundNotifyUrl;
-
     @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
     @Schema(description = "创建时间")
     private LocalDateTime[] createTime;

+ 1 - 1
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/app/vo/PayAppRespVO.java

@@ -10,7 +10,7 @@ import java.time.LocalDateTime;
 @ToString(callSuper = true)
 public class PayAppRespVO extends PayAppBaseVO {
 
-    @Schema(description = "应用编号", requiredMode = Schema.RequiredMode.REQUIRED)
+    @Schema(description = "应用编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
     private Long id;
 
     @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)

+ 1 - 1
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/app/vo/PayAppUpdateReqVO.java

@@ -9,7 +9,7 @@ import javax.validation.constraints.*;
 @ToString(callSuper = true)
 public class PayAppUpdateReqVO extends PayAppBaseVO {
 
-    @Schema(description = "应用编号", requiredMode = Schema.RequiredMode.REQUIRED)
+    @Schema(description = "应用编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
     @NotNull(message = "应用编号不能为空")
     private Long id;
 

+ 3 - 3
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/app/vo/PayAppUpdateStatusReqVO.java

@@ -9,11 +9,11 @@ import javax.validation.constraints.NotNull;
 @Data
 public class PayAppUpdateStatusReqVO {
 
-    @Schema(description = "商户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
-    @NotNull(message = "商户编号不能为空")
+    @Schema(description = "应用编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
+    @NotNull(message = "应用编号不能为空")
     private Long id;
 
-    @Schema(description = "状态,见 SysCommonStatusEnum 枚举", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+    @Schema(description = "状态见 SysCommonStatusEnum 枚举", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
     @NotNull(message = "状态不能为空")
     private Integer status;
 

+ 14 - 1
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/convert/app/PayAppConvert.java

@@ -1,15 +1,20 @@
 package cn.iocoder.yudao.module.pay.convert.app;
 
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
 import cn.iocoder.yudao.module.pay.controller.admin.app.vo.PayAppCreateReqVO;
 import cn.iocoder.yudao.module.pay.controller.admin.app.vo.PayAppPageItemRespVO;
 import cn.iocoder.yudao.module.pay.controller.admin.app.vo.PayAppRespVO;
 import cn.iocoder.yudao.module.pay.controller.admin.app.vo.PayAppUpdateReqVO;
 import cn.iocoder.yudao.module.pay.dal.dataobject.app.PayAppDO;
+import cn.iocoder.yudao.module.pay.dal.dataobject.channel.PayChannelDO;
 import org.mapstruct.Mapper;
 import org.mapstruct.factory.Mappers;
 
 import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.function.Consumer;
 
 /**
  * 支付应用信息 Convert
@@ -31,6 +36,14 @@ public interface PayAppConvert {
 
     List<PayAppRespVO> convertList(List<PayAppDO> list);
 
-    PageResult<PayAppRespVO> convertPage(PageResult<PayAppDO> page);
+    PageResult<PayAppPageItemRespVO> convertPage(PageResult<PayAppDO> page);
+
+    default PageResult<PayAppPageItemRespVO> convertPage(PageResult<PayAppDO> pageResult, List<PayChannelDO> channels) {
+        PageResult<PayAppPageItemRespVO> voPageResult = convertPage(pageResult);
+        // 处理 channel 关系
+        Map<Long, Set<String>> appIdChannelMap = CollectionUtils.convertMultiMap2(channels, PayChannelDO::getAppId, PayChannelDO::getCode);
+        voPageResult.getList().forEach(app -> app.setChannelCodes(appIdChannelMap.get(app.getId())));
+        return voPageResult;
+    }
 
 }

+ 6 - 8
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/mysql/app/PayAppMapper.java

@@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.pay.dal.mysql.app;
 
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
 import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
+import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
 import cn.iocoder.yudao.framework.mybatis.core.query.QueryWrapperX;
 import cn.iocoder.yudao.module.pay.controller.admin.app.vo.PayAppPageReqVO;
 import cn.iocoder.yudao.module.pay.dal.dataobject.app.PayAppDO;
@@ -11,14 +12,11 @@ import org.apache.ibatis.annotations.Mapper;
 public interface PayAppMapper extends BaseMapperX<PayAppDO> {
 
     default PageResult<PayAppDO> selectPage(PayAppPageReqVO reqVO) {
-        return selectPage(reqVO, new QueryWrapperX<PayAppDO>()
-                .likeIfPresent("name", reqVO.getName())
-                .eqIfPresent("status", reqVO.getStatus())
-                .eqIfPresent("remark", reqVO.getRemark())
-                .eqIfPresent("pay_notify_url", reqVO.getPayNotifyUrl())
-                .eqIfPresent("refund_notify_url", reqVO.getRefundNotifyUrl())
-                .betweenIfPresent("create_time", reqVO.getCreateTime())
-                .orderByDesc("id"));
+        return selectPage(reqVO, new LambdaQueryWrapperX<PayAppDO>()
+                .likeIfPresent(PayAppDO::getName, reqVO.getName())
+                .eqIfPresent(PayAppDO::getStatus, reqVO.getStatus())
+                .betweenIfPresent(PayAppDO::getCreateTime, reqVO.getCreateTime())
+                .orderByDesc(PayAppDO::getId));
     }
 
 }

+ 2 - 11
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/mysql/order/PayOrderMapper.java

@@ -50,17 +50,8 @@ public interface PayOrderMapper extends BaseMapperX<PayOrderDO> {
                 .in(PayOrderDO::getId, idList));
     }
 
-    /**
-     * 查询符合的订单数量
-     *
-     * @param appId 应用编号
-     * @param status 订单状态
-     * @return 条数
-     */
-    default Long selectCount(Long appId, Integer status) {
-        return selectCount(new LambdaQueryWrapper<PayOrderDO>()
-                .eq(PayOrderDO::getAppId, appId)
-                .in(PayOrderDO::getStatus, status));
+    default Long selectCountByAppId(Long appId) {
+        return selectCount(PayOrderDO::getAppId, appId);
     }
 
     default PayOrderDO selectByAppIdAndMerchantOrderId(Long appId, String merchantOrderId) {

+ 3 - 6
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/mysql/refund/PayRefundMapper.java

@@ -6,7 +6,6 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult;
 import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
 import cn.iocoder.yudao.framework.mybatis.core.query.QueryWrapperX;
 import cn.iocoder.yudao.module.pay.dal.dataobject.refund.PayRefundDO;
-import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import org.apache.ibatis.annotations.Mapper;
 
 import java.util.List;
@@ -38,11 +37,8 @@ public interface PayRefundMapper extends BaseMapperX<PayRefundDO> {
                 .orderByDesc("id"));
     }
 
-    default Long selectCount(Long appId, Integer status) {
-
-        return selectCount(new LambdaQueryWrapper<PayRefundDO>()
-                .eq(PayRefundDO::getAppId, appId)
-                .eq(PayRefundDO::getStatus, status));
+    default Long selectCountByApp(Long appId) {
+         return selectCount(PayRefundDO::getAppId, appId);
     }
 
     default PayRefundDO selectByReqNo(String reqNo) {
@@ -52,4 +48,5 @@ public interface PayRefundMapper extends BaseMapperX<PayRefundDO> {
     default  PayRefundDO selectByTradeNoAndMerchantRefundNo(String tradeNo, String merchantRefundNo){
         return selectOne("trade_no", tradeNo, "merchant_refund_no", merchantRefundNo);
     }
+
 }

+ 8 - 9
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/app/PayAppService.java

@@ -35,6 +35,14 @@ public interface PayAppService {
      */
     void updateApp(@Valid PayAppUpdateReqVO updateReqVO);
 
+    /**
+     * 修改应用信息状态
+     *
+     * @param id     应用编号
+     * @param status 状态
+     */
+    void updateAppStatus(Long id, Integer status);
+
     /**
      * 删除支付应用信息
      *
@@ -66,14 +74,6 @@ public interface PayAppService {
      */
     PageResult<PayAppDO> getAppPage(PayAppPageReqVO pageReqVO);
 
-    /**
-     * 修改应用信息状态
-     *
-     * @param id     应用编号
-     * @param status 状态{@link cn.iocoder.yudao.framework.common.enums.CommonStatusEnum}
-     */
-    void updateAppStatus(Long id, Integer status);
-
     /**
      * 获得指定编号的商户 Map
      *
@@ -85,7 +85,6 @@ public interface PayAppService {
         return CollectionUtils.convertMap(list, PayAppDO::getId);
     }
 
-
     /**
      * 支付应用的合法性
      *

+ 30 - 54
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/app/PayAppServiceImpl.java

@@ -9,12 +9,13 @@ import cn.iocoder.yudao.module.pay.controller.admin.app.vo.PayAppUpdateReqVO;
 import cn.iocoder.yudao.module.pay.convert.app.PayAppConvert;
 import cn.iocoder.yudao.module.pay.dal.dataobject.app.PayAppDO;
 import cn.iocoder.yudao.module.pay.dal.mysql.app.PayAppMapper;
-import cn.iocoder.yudao.module.pay.dal.mysql.order.PayOrderMapper;
 import cn.iocoder.yudao.module.pay.dal.mysql.refund.PayRefundMapper;
 import cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants;
 import cn.iocoder.yudao.module.pay.enums.order.PayOrderStatusEnum;
 import cn.iocoder.yudao.module.pay.enums.refund.PayRefundStatusEnum;
-import com.google.common.annotations.VisibleForTesting;
+import cn.iocoder.yudao.module.pay.service.order.PayOrderService;
+import cn.iocoder.yudao.module.pay.service.refund.PayRefundService;
+import org.springframework.context.annotation.Lazy;
 import org.springframework.stereotype.Service;
 import org.springframework.validation.annotation.Validated;
 
@@ -23,11 +24,10 @@ import java.util.Collection;
 import java.util.List;
 
 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
-import static cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants.PAY_APP_EXIST_TRANSACTION_ORDER_CANT_DELETE;
-import static cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants.PAY_APP_NOT_FOUND;
+import static cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants.*;
 
 /**
- * 支付应用信息 Service 实现类
+ * 支付应用 Service 实现类
  *
  * @author aquan
  */
@@ -37,11 +37,13 @@ public class PayAppServiceImpl implements PayAppService {
 
     @Resource
     private PayAppMapper appMapper;
-    // TODO 芋艿:不能调用对方的 mapper
+
     @Resource
-    private PayOrderMapper orderMapper;
+    @Lazy // 延迟加载,避免循环依赖报错
+    private PayOrderService orderService;
     @Resource
-    private PayRefundMapper refundMapper;
+    @Lazy // 延迟加载,避免循环依赖报错
+    private PayRefundService refundService;
 
     @Override
     public Long createApp(PayAppCreateReqVO createReqVO) {
@@ -55,17 +57,34 @@ public class PayAppServiceImpl implements PayAppService {
     @Override
     public void updateApp(PayAppUpdateReqVO updateReqVO) {
         // 校验存在
-        this.validateAppExists(updateReqVO.getId());
+        validateAppExists(updateReqVO.getId());
         // 更新
         PayAppDO updateObj = PayAppConvert.INSTANCE.convert(updateReqVO);
         appMapper.updateById(updateObj);
     }
 
+    @Override
+    public void updateAppStatus(Long id, Integer status) {
+        // 校验商户存在
+        validateAppExists(id);
+        // 更新状态
+        PayAppDO app = new PayAppDO();
+        app.setId(id);
+        app.setStatus(status);
+        appMapper.updateById(app);
+    }
+
     @Override
     public void deleteApp(Long id) {
         // 校验存在
-        this.validateAppExists(id);
-        this.validateOrderTransactionExist(id);
+        validateAppExists(id);
+        // 校验关联数据是否存在
+        if (orderService.getOrderCountByAppId(id) > 0) {
+            throw exception(PAY_APP_EXIST_ORDER_CANT_DELETE);
+        }
+        if (refundService.getRefundCountByAppId(id) > 0) {
+            throw exception(PAY_APP_EXIST_REFUND_CANT_DELETE);
+        }
 
         // 删除
         appMapper.deleteById(id);
@@ -92,49 +111,6 @@ public class PayAppServiceImpl implements PayAppService {
         return appMapper.selectPage(pageReqVO);
     }
 
-    @Override
-    public void updateAppStatus(Long id, Integer status) {
-        // 校验商户存在
-        this.checkAppExists(id);
-        // 更新状态
-        PayAppDO app = new PayAppDO();
-        app.setId(id);
-        app.setStatus(status);
-        appMapper.updateById(app);
-    }
-
-    /**
-     * 检查商户是否存在
-     *
-     * @param id 商户编号
-     */
-    @VisibleForTesting
-    public void checkAppExists(Long id) {
-        if (id == null) {
-            return;
-        }
-        PayAppDO payApp = appMapper.selectById(id);
-        if (payApp == null) {
-            throw exception(PAY_APP_NOT_FOUND);
-        }
-    }
-
-    /**
-     * 验证是否存在交易中或者退款中等处理中状态的订单
-     *
-     * @param appId 应用 ID
-     */
-    private void validateOrderTransactionExist(Long appId) {
-        // 查看交易订单
-        if (orderMapper.selectCount(appId, PayOrderStatusEnum.WAITING.getStatus()) > 0) {
-            throw exception(PAY_APP_EXIST_TRANSACTION_ORDER_CANT_DELETE);
-        }
-        // 查看退款订单
-        if (refundMapper.selectCount(appId, PayRefundStatusEnum.CREATE.getStatus()) > 0) {
-            throw exception(PAY_APP_EXIST_TRANSACTION_ORDER_CANT_DELETE);
-        }
-    }
-
     @Override
     public PayAppDO validPayApp(Long id) {
         PayAppDO app = appMapper.selectById(id);

+ 8 - 0
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/order/PayOrderService.java

@@ -32,6 +32,14 @@ public interface PayOrderService {
      */
     PayOrderDO getOrder(Long id);
 
+    /**
+     * 获得指定应用的订单数量
+     *
+     * @param appId 应用编号
+     * @return 订单数量
+     */
+    Long getOrderCountByAppId(Long appId);
+
     /**
      * 获得支付订单
      * 分页

+ 5 - 0
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/order/PayOrderServiceImpl.java

@@ -82,6 +82,11 @@ public class PayOrderServiceImpl implements PayOrderService {
         return orderMapper.selectById(id);
     }
 
+    @Override
+    public Long getOrderCountByAppId(Long appId) {
+        return orderMapper.selectCountByAppId(appId);
+    }
+
     @Override
     public PageResult<PayOrderDO> getOrderPage(PayOrderPageReqVO pageReqVO) {
         return orderMapper.selectPage(pageReqVO);

+ 8 - 0
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/refund/PayRefundService.java

@@ -25,6 +25,14 @@ public interface PayRefundService {
      */
     PayRefundDO getRefund(Long id);
 
+    /**
+     * 获得指定应用的退款数量
+     *
+     * @param appId 应用编号
+     * @return 退款数量
+     */
+    Long getRefundCountByAppId(Long appId);
+
     /**
      * 获得退款订单分页
      *

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

@@ -80,6 +80,11 @@ public class PayRefundServiceImpl implements PayRefundService {
         return refundMapper.selectById(id);
     }
 
+    @Override
+    public Long getRefundCountByAppId(Long appId) {
+        return refundMapper.selectCountByApp(appId);
+    }
+
     @Override
     public PageResult<PayRefundDO> getRefundPage(PayRefundPageReqVO pageReqVO) {
         return refundMapper.selectPage(pageReqVO);

+ 22 - 17
yudao-module-pay/yudao-module-pay-biz/src/test/java/cn/iocoder/yudao/module/pay/service/app/PayAppServiceTest.java

@@ -3,27 +3,37 @@ package cn.iocoder.yudao.module.pay.service.app;
 import cn.hutool.core.util.RandomUtil;
 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
 import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils;
 import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
+import cn.iocoder.yudao.framework.test.core.util.RandomUtils;
 import cn.iocoder.yudao.module.pay.controller.admin.app.vo.PayAppCreateReqVO;
 import cn.iocoder.yudao.module.pay.controller.admin.app.vo.PayAppPageReqVO;
 import cn.iocoder.yudao.module.pay.controller.admin.app.vo.PayAppUpdateReqVO;
 import cn.iocoder.yudao.module.pay.dal.dataobject.app.PayAppDO;
 import cn.iocoder.yudao.module.pay.dal.mysql.app.PayAppMapper;
+import cn.iocoder.yudao.module.pay.service.order.PayOrderService;
+import cn.iocoder.yudao.module.pay.service.refund.PayRefundService;
 import org.junit.jupiter.api.Test;
+import org.springframework.boot.test.mock.mockito.MockBean;
 import org.springframework.context.annotation.Import;
 
 import javax.annotation.Resource;
 import java.time.LocalDateTime;
 
+import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.buildBetweenTime;
 import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.buildTime;
 import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId;
 import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals;
 import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException;
-import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomLongId;
-import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo;
+import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*;
 import static cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants.PAY_APP_NOT_FOUND;
 import static org.junit.jupiter.api.Assertions.*;
 
+/**
+ * {@link PayAppServiceImpl} 的单元测试
+ *
+ * @author aquan
+ */
 @Import(PayAppServiceImpl.class)
 public class PayAppServiceTest extends BaseDbUnitTest {
 
@@ -33,17 +43,23 @@ public class PayAppServiceTest extends BaseDbUnitTest {
     @Resource
     private PayAppMapper appMapper;
 
+    @MockBean
+    private PayOrderService orderService;
+    @MockBean
+    private PayRefundService refundService;
+
     @Test
     public void testCreateApp_success() {
         // 准备参数
         PayAppCreateReqVO reqVO = randomPojo(PayAppCreateReqVO.class, o ->
-                o.setStatus((RandomUtil.randomEle(CommonStatusEnum.values()).getStatus())));
+                o.setStatus((RandomUtil.randomEle(CommonStatusEnum.values()).getStatus()))
+                        .setPayNotifyUrl(randomURL())
+                        .setRefundNotifyUrl(randomURL()));
 
         // 调用
         Long appId = appService.createApp(reqVO);
         // 断言
         assertNotNull(appId);
-        // 校验记录的属性是否正确
         PayAppDO app = appMapper.selectById(appId);
         assertPojoEquals(reqVO, app);
     }
@@ -57,6 +73,7 @@ public class PayAppServiceTest extends BaseDbUnitTest {
         // 准备参数
         PayAppUpdateReqVO reqVO = randomPojo(PayAppUpdateReqVO.class, o -> {
             o.setStatus(CommonStatusEnum.ENABLE.getStatus());
+            o.setPayNotifyUrl(randomURL()).setRefundNotifyUrl(randomURL());
             o.setId(dbApp.getId()); // 设置更新的 ID
         });
 
@@ -106,9 +123,6 @@ public class PayAppServiceTest extends BaseDbUnitTest {
         PayAppDO dbApp = randomPojo(PayAppDO.class, o -> { // 等会查询到
             o.setName("灿灿姐的杂货铺");
             o.setStatus(CommonStatusEnum.ENABLE.getStatus());
-            o.setRemark("敏敏姐的小卖铺");
-            o.setPayNotifyUrl("https://www.hc.com");
-            o.setRefundNotifyUrl("https://www.xm.com");
             o.setCreateTime(buildTime(2021,11,20));
         });
 
@@ -117,22 +131,13 @@ public class PayAppServiceTest extends BaseDbUnitTest {
         appMapper.insert(cloneIgnoreId(dbApp, o -> o.setName("敏敏姐的杂货铺")));
         // 测试 status 不匹配
         appMapper.insert(cloneIgnoreId(dbApp, o -> o.setStatus(CommonStatusEnum.DISABLE.getStatus())));
-        // 测试 remark 不匹配
-        appMapper.insert(cloneIgnoreId(dbApp, o -> o.setRemark("灿灿姐的小卖部")));
-        // 测试 payNotifyUrl 不匹配
-        appMapper.insert(cloneIgnoreId(dbApp, o -> o.setPayNotifyUrl("xm.com")));
-        // 测试 refundNotifyUrl 不匹配
-        appMapper.insert(cloneIgnoreId(dbApp, o -> o.setRefundNotifyUrl("hc.com")));
         // 测试 createTime 不匹配
         appMapper.insert(cloneIgnoreId(dbApp, o -> o.setCreateTime(buildTime(2021,12,21))));
         // 准备参数
         PayAppPageReqVO reqVO = new PayAppPageReqVO();
         reqVO.setName("灿灿姐的杂货铺");
         reqVO.setStatus(CommonStatusEnum.ENABLE.getStatus());
-        reqVO.setRemark("敏敏姐的小卖铺");
-        reqVO.setPayNotifyUrl("https://www.hc.com");
-        reqVO.setRefundNotifyUrl("https://www.xm.com");
-        reqVO.setCreateTime((new LocalDateTime[]{buildTime(2021,11,19),buildTime(2021,11,21)}));
+        reqVO.setCreateTime(buildBetweenTime(2021, 11, 19, 2021, 11, 21));
 
         // 调用
         PageResult<PayAppDO> pageResult = appService.getAppPage(reqVO);

+ 0 - 1
yudao-module-pay/yudao-module-pay-biz/src/test/resources/sql/clean.sql

@@ -1,4 +1,3 @@
-DELETE FROM pay_merchant;
 DELETE FROM pay_app;
 DELETE FROM pay_channel;
 DELETE FROM pay_order;

+ 1 - 20
yudao-module-pay/yudao-module-pay-biz/src/test/resources/sql/create_tables.sql

@@ -1,18 +1,3 @@
-CREATE TABLE IF NOT EXISTS "pay_merchant" (
-    "id" number NOT NULL GENERATED BY DEFAULT AS IDENTITY,
-    "no"          varchar(32) NOT NULL,
-    "name"        varchar(64) NOT NULL,
-    "short_name"  varchar(64) NOT NULL,
-    "status"      tinyint     NOT NULL,
-    "remark"      varchar(255)         DEFAULT NULL,
-    "creator"     varchar(64)          DEFAULT '',
-    "create_time" datetime    NOT NULL DEFAULT CURRENT_TIMESTAMP,
-    "updater"     varchar(64)          DEFAULT '',
-    "update_time" datetime    NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
-    "deleted"     bit(1)      NOT NULL DEFAULT FALSE,
-    PRIMARY KEY ("id")
-) COMMENT '支付商户信息';
-
 CREATE TABLE IF NOT EXISTS "pay_app" (
     "id" number NOT NULL GENERATED BY DEFAULT AS IDENTITY,
     "name"              varchar(64)   NOT NULL,
@@ -20,14 +5,13 @@ CREATE TABLE IF NOT EXISTS "pay_app" (
     "remark"            varchar(255)           DEFAULT NULL,
     `pay_notify_url`    varchar(1024) NOT NULL,
     `refund_notify_url` varchar(1024) NOT NULL,
-    `merchant_id`       bigint(20)    NOT NULL,
     "creator"           varchar(64)            DEFAULT '',
     "create_time"       datetime      NOT NULL DEFAULT CURRENT_TIMESTAMP,
     "updater"           varchar(64)            DEFAULT '',
     "update_time"       datetime      NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
     "deleted"           bit(1)        NOT NULL DEFAULT FALSE,
     PRIMARY KEY ("id")
-) COMMENT = '支付应用信息';
+) COMMENT = '支付应用';
 
 CREATE TABLE IF NOT EXISTS "pay_channel" (
     "id" number NOT NULL GENERATED BY DEFAULT AS IDENTITY,
@@ -35,7 +19,6 @@ CREATE TABLE IF NOT EXISTS "pay_channel" (
     "status"      tinyint(4)     NOT NULL,
     "remark"      varchar(255)            DEFAULT NULL,
     "fee_rate"    double         NOT NULL DEFAULT 0,
-    "merchant_id" bigint(20)     NOT NULL,
     "app_id"      bigint(20)     NOT NULL,
     "config"      varchar(10240) NOT NULL,
     "creator"     varchar(64)    NULL     DEFAULT '',
@@ -49,7 +32,6 @@ CREATE TABLE IF NOT EXISTS "pay_channel" (
 
 CREATE TABLE IF NOT EXISTS `pay_order` (
     "id" number NOT NULL GENERATED BY DEFAULT AS IDENTITY,
-    `merchant_id`          bigint(20)    NOT NULL,
     `app_id`               bigint(20)    NOT NULL,
     `channel_id`           bigint(20)             DEFAULT NULL,
     `channel_code`         varchar(32)            DEFAULT NULL,
@@ -82,7 +64,6 @@ CREATE TABLE IF NOT EXISTS `pay_order` (
 
 CREATE TABLE IF NOT EXISTS `pay_refund` (
     "id" number NOT NULL GENERATED BY DEFAULT AS IDENTITY,
-    `merchant_id`        bigint(20)    NOT NULL,
     `app_id`             bigint(20)    NOT NULL,
     `channel_id`         bigint(20)    NOT NULL,
     `channel_code`       varchar(32)   NOT NULL,