Commit 052e4689ee083ee2fdbbce3daa615bfaf9904249

Authored by zhijiantianya@gmail.com
1 parent f1c4c796

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

Showing 22 changed files with 142 additions and 184 deletions
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 {
102 102 return randomString() + "@qq.com";
103 103 }
104 104  
  105 + public static String randomURL() {
  106 + return "https://www.iocoder.cn/" + randomString();
  107 + }
  108 +
105 109 @SafeVarargs
106 110 public static <T> T randomPojo(Class<T> clazz, Consumer<T>... consumers) {
107 111 T pojo = PODAM_FACTORY.manufacturePojo(clazz);
... ...
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 {
12 12 // ========== APP 模块 1007000000 ==========
13 13 ErrorCode PAY_APP_NOT_FOUND = new ErrorCode(1007000000, "App 不存在");
14 14 ErrorCode PAY_APP_IS_DISABLE = new ErrorCode(1007000002, "App 已经被禁用");
15   - ErrorCode PAY_APP_EXIST_TRANSACTION_ORDER_CANT_DELETE = new ErrorCode(1007000003, "支付应用存在交易中的订单,无法删除");
  15 + ErrorCode PAY_APP_EXIST_ORDER_CANT_DELETE = new ErrorCode(1007000003, "支付应用存在支付订单,无法删除");
  16 + ErrorCode PAY_APP_EXIST_REFUND_CANT_DELETE = new ErrorCode(1007000004, "支付应用存在退款订单,无法删除");
16 17  
17 18 // ========== CHANNEL 模块 1007001000 ==========
18 19 ErrorCode PAY_CHANNEL_NOT_FOUND = new ErrorCode(1007001000, "支付渠道的配置不存在");
... ...
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;
24 24 import java.util.*;
25 25  
26 26 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
  27 +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
27 28  
28 29 @Slf4j
29 30 @Tag(name = "管理后台 - 支付应用信息")
... ... @@ -78,15 +79,6 @@ public class PayAppController {
78 79 return success(PayAppConvert.INSTANCE.convert(app));
79 80 }
80 81  
81   - @GetMapping("/list")
82   - @Operation(summary = "获得支付应用信息列表")
83   - @Parameter(name = "ids", description = "编号列表", required = true, example = "1024,2048")
84   - @PreAuthorize("@ss.hasPermission('pay:app:query')")
85   - public CommonResult<List<PayAppRespVO>> getAppList(@RequestParam("ids") Collection<Long> ids) {
86   - List<PayAppDO> list = appService.getAppList(ids);
87   - return success(PayAppConvert.INSTANCE.convertList(list));
88   - }
89   -
90 82 @GetMapping("/page")
91 83 @Operation(summary = "获得支付应用信息分页")
92 84 @PreAuthorize("@ss.hasPermission('pay:app:query')")
... ... @@ -94,34 +86,15 @@ public class PayAppController {
94 86 // 得到应用分页列表
95 87 PageResult<PayAppDO> pageResult = appService.getAppPage(pageVO);
96 88 if (CollUtil.isEmpty(pageResult.getList())) {
97   - return success(new PageResult<>(pageResult.getTotal()));
  89 + return success(PageResult.empty());
98 90 }
99 91  
100 92 // 得到所有的应用编号,查出所有的渠道
101   - Collection<Long> payAppIds = CollectionUtils.convertList(pageResult.getList(), PayAppDO::getId);
102   - List<PayChannelDO> channels = channelService.getChannelListByAppIds(payAppIds);
103   - // TODO @aquan:可以基于 appId 简历一个 multiMap。这样下面,直接 get 到之后,CollUtil buildSet 即可
104   - Iterator<PayChannelDO> iterator = channels.iterator();
105   -
106   - // 利用反射将渠道数据复制到返回的数据结构中去
107   - List<PayAppPageItemRespVO> appList = new ArrayList<>(pageResult.getList().size());
108   - pageResult.getList().forEach(app -> {
109   - // 写入应用信息的数据
110   - PayAppPageItemRespVO respVO = PayAppConvert.INSTANCE.pageConvert(app);
111   - // 写入支付渠道信息的数据
112   - Set<String> channelCodes = new HashSet<>(PayChannelEnum.values().length);
113   - while (iterator.hasNext()) {
114   - PayChannelDO channelDO = iterator.next();
115   - if (channelDO.getAppId().equals(app.getId())) {
116   - channelCodes.add(channelDO.getCode());
117   - iterator.remove();
118   - }
119   - }
120   - respVO.setChannelCodes(channelCodes);
121   - appList.add(respVO);
122   - });
  93 + Collection<Long> appIds = convertList(pageResult.getList(), PayAppDO::getId);
  94 + List<PayChannelDO> channels = channelService.getChannelListByAppIds(appIds);
123 95  
124   - return success(new PageResult<>(appList, pageResult.getTotal()));
  96 + // 拼接后返回
  97 + return success(PayAppConvert.INSTANCE.convertPage(pageResult, channels));
125 98 }
126 99  
127 100 }
... ...
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/app/vo/PayAppBaseVO.java
1 1 package cn.iocoder.yudao.module.pay.controller.admin.app.vo;
2 2 import io.swagger.v3.oas.annotations.media.Schema;
3 3 import lombok.*;
  4 +import org.hibernate.validator.constraints.URL;
  5 +
4 6 import javax.validation.constraints.*;
5 7  
6 8 /**
... ... @@ -10,23 +12,25 @@ import javax.validation.constraints.*;
10 12 @Data
11 13 public class PayAppBaseVO {
12 14  
13   - @Schema(description = "应用名", requiredMode = Schema.RequiredMode.REQUIRED)
  15 + @Schema(description = "应用名", requiredMode = Schema.RequiredMode.REQUIRED, example = "小豆")
14 16 @NotNull(message = "应用名不能为空")
15 17 private String name;
16 18  
17   - @Schema(description = "开启状态", requiredMode = Schema.RequiredMode.REQUIRED)
  19 + @Schema(description = "开启状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "0")
18 20 @NotNull(message = "开启状态不能为空")
19 21 private Integer status;
20 22  
21   - @Schema(description = "备注")
  23 + @Schema(description = "备注", example = "我是一个测试应用")
22 24 private String remark;
23 25  
24   - @Schema(description = "支付结果的回调地址", requiredMode = Schema.RequiredMode.REQUIRED)
  26 + @Schema(description = "支付结果的回调地址", requiredMode = Schema.RequiredMode.REQUIRED, example = "http://127.0.0.1:48080/pay-callback")
25 27 @NotNull(message = "支付结果的回调地址不能为空")
  28 + @URL(message = "支付结果的回调地址必须为 URL 格式")
26 29 private String payNotifyUrl;
27 30  
28   - @Schema(description = "退款结果的回调地址", requiredMode = Schema.RequiredMode.REQUIRED)
  31 + @Schema(description = "退款结果的回调地址", requiredMode = Schema.RequiredMode.REQUIRED, example = "http://127.0.0.1:48080/refund-callback")
29 32 @NotNull(message = "退款结果的回调地址不能为空")
  33 + @URL(message = "退款结果的回调地址必须为 URL 格式")
30 34 private String refundNotifyUrl;
31 35  
32 36 }
... ...
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;
14 14 @ToString(callSuper = true)
15 15 public class PayAppPageItemRespVO extends PayAppBaseVO {
16 16  
17   - @Schema(description = "应用编号", requiredMode = Schema.RequiredMode.REQUIRED)
  17 + @Schema(description = "应用编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
18 18 private Long id;
19 19  
20 20 @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
21 21 private LocalDateTime createTime;
22 22  
23   - @Schema(description = "渠道编码集合", requiredMode = Schema.RequiredMode.REQUIRED, example = "[alipay_pc, alipay_wap]")
  23 + @Schema(description = "已配置的支付渠道编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "[alipay_pc, alipay_wap]")
24 24 private Set<String> channelCodes;
25 25  
26 26 }
... ...
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_
17 17 @ToString(callSuper = true)
18 18 public class PayAppPageReqVO extends PageParam {
19 19  
20   - @Schema(description = "应用名")
  20 + @Schema(description = "应用名", example = "小豆")
21 21 private String name;
22 22  
23   - @Schema(description = "开启状态")
  23 + @Schema(description = "开启状态", example = "0")
24 24 private Integer status;
25 25  
26   - @Schema(description = "备注")
27   - private String remark;
28   -
29   - @Schema(description = "支付结果的回调地址")
30   - private String payNotifyUrl;
31   -
32   - @Schema(description = "退款结果的回调地址")
33   - private String refundNotifyUrl;
34   -
35 26 @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
36 27 @Schema(description = "创建时间")
37 28 private LocalDateTime[] createTime;
... ...
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;
10 10 @ToString(callSuper = true)
11 11 public class PayAppRespVO extends PayAppBaseVO {
12 12  
13   - @Schema(description = "应用编号", requiredMode = Schema.RequiredMode.REQUIRED)
  13 + @Schema(description = "应用编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
14 14 private Long id;
15 15  
16 16 @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
... ...
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.*;
9 9 @ToString(callSuper = true)
10 10 public class PayAppUpdateReqVO extends PayAppBaseVO {
11 11  
12   - @Schema(description = "应用编号", requiredMode = Schema.RequiredMode.REQUIRED)
  12 + @Schema(description = "应用编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
13 13 @NotNull(message = "应用编号不能为空")
14 14 private Long id;
15 15  
... ...
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;
9 9 @Data
10 10 public class PayAppUpdateStatusReqVO {
11 11  
12   - @Schema(description = "商户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
13   - @NotNull(message = "商户编号不能为空")
  12 + @Schema(description = "应用编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
  13 + @NotNull(message = "应用编号不能为空")
14 14 private Long id;
15 15  
16   - @Schema(description = "状态,见 SysCommonStatusEnum 枚举", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
  16 + @Schema(description = "状态,见 SysCommonStatusEnum 枚举", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
17 17 @NotNull(message = "状态不能为空")
18 18 private Integer status;
19 19  
... ...
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/convert/app/PayAppConvert.java
1 1 package cn.iocoder.yudao.module.pay.convert.app;
2 2  
3 3 import cn.iocoder.yudao.framework.common.pojo.PageResult;
  4 +import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
4 5 import cn.iocoder.yudao.module.pay.controller.admin.app.vo.PayAppCreateReqVO;
5 6 import cn.iocoder.yudao.module.pay.controller.admin.app.vo.PayAppPageItemRespVO;
6 7 import cn.iocoder.yudao.module.pay.controller.admin.app.vo.PayAppRespVO;
7 8 import cn.iocoder.yudao.module.pay.controller.admin.app.vo.PayAppUpdateReqVO;
8 9 import cn.iocoder.yudao.module.pay.dal.dataobject.app.PayAppDO;
  10 +import cn.iocoder.yudao.module.pay.dal.dataobject.channel.PayChannelDO;
9 11 import org.mapstruct.Mapper;
10 12 import org.mapstruct.factory.Mappers;
11 13  
12 14 import java.util.List;
  15 +import java.util.Map;
  16 +import java.util.Set;
  17 +import java.util.function.Consumer;
13 18  
14 19 /**
15 20 * 支付应用信息 Convert
... ... @@ -31,6 +36,14 @@ public interface PayAppConvert {
31 36  
32 37 List<PayAppRespVO> convertList(List<PayAppDO> list);
33 38  
34   - PageResult<PayAppRespVO> convertPage(PageResult<PayAppDO> page);
  39 + PageResult<PayAppPageItemRespVO> convertPage(PageResult<PayAppDO> page);
  40 +
  41 + default PageResult<PayAppPageItemRespVO> convertPage(PageResult<PayAppDO> pageResult, List<PayChannelDO> channels) {
  42 + PageResult<PayAppPageItemRespVO> voPageResult = convertPage(pageResult);
  43 + // 处理 channel 关系
  44 + Map<Long, Set<String>> appIdChannelMap = CollectionUtils.convertMultiMap2(channels, PayChannelDO::getAppId, PayChannelDO::getCode);
  45 + voPageResult.getList().forEach(app -> app.setChannelCodes(appIdChannelMap.get(app.getId())));
  46 + return voPageResult;
  47 + }
35 48  
36 49 }
... ...
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;
2 2  
3 3 import cn.iocoder.yudao.framework.common.pojo.PageResult;
4 4 import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
  5 +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
5 6 import cn.iocoder.yudao.framework.mybatis.core.query.QueryWrapperX;
6 7 import cn.iocoder.yudao.module.pay.controller.admin.app.vo.PayAppPageReqVO;
7 8 import cn.iocoder.yudao.module.pay.dal.dataobject.app.PayAppDO;
... ... @@ -11,14 +12,11 @@ import org.apache.ibatis.annotations.Mapper;
11 12 public interface PayAppMapper extends BaseMapperX<PayAppDO> {
12 13  
13 14 default PageResult<PayAppDO> selectPage(PayAppPageReqVO reqVO) {
14   - return selectPage(reqVO, new QueryWrapperX<PayAppDO>()
15   - .likeIfPresent("name", reqVO.getName())
16   - .eqIfPresent("status", reqVO.getStatus())
17   - .eqIfPresent("remark", reqVO.getRemark())
18   - .eqIfPresent("pay_notify_url", reqVO.getPayNotifyUrl())
19   - .eqIfPresent("refund_notify_url", reqVO.getRefundNotifyUrl())
20   - .betweenIfPresent("create_time", reqVO.getCreateTime())
21   - .orderByDesc("id"));
  15 + return selectPage(reqVO, new LambdaQueryWrapperX<PayAppDO>()
  16 + .likeIfPresent(PayAppDO::getName, reqVO.getName())
  17 + .eqIfPresent(PayAppDO::getStatus, reqVO.getStatus())
  18 + .betweenIfPresent(PayAppDO::getCreateTime, reqVO.getCreateTime())
  19 + .orderByDesc(PayAppDO::getId));
22 20 }
23 21  
24 22 }
... ...
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&lt;PayOrderDO&gt; {
50 50 .in(PayOrderDO::getId, idList));
51 51 }
52 52  
53   - /**
54   - * 查询符合的订单数量
55   - *
56   - * @param appId 应用编号
57   - * @param status 订单状态
58   - * @return 条数
59   - */
60   - default Long selectCount(Long appId, Integer status) {
61   - return selectCount(new LambdaQueryWrapper<PayOrderDO>()
62   - .eq(PayOrderDO::getAppId, appId)
63   - .in(PayOrderDO::getStatus, status));
  53 + default Long selectCountByAppId(Long appId) {
  54 + return selectCount(PayOrderDO::getAppId, appId);
64 55 }
65 56  
66 57 default PayOrderDO selectByAppIdAndMerchantOrderId(Long appId, String merchantOrderId) {
... ...
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;
6 6 import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
7 7 import cn.iocoder.yudao.framework.mybatis.core.query.QueryWrapperX;
8 8 import cn.iocoder.yudao.module.pay.dal.dataobject.refund.PayRefundDO;
9   -import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
10 9 import org.apache.ibatis.annotations.Mapper;
11 10  
12 11 import java.util.List;
... ... @@ -38,11 +37,8 @@ public interface PayRefundMapper extends BaseMapperX&lt;PayRefundDO&gt; {
38 37 .orderByDesc("id"));
39 38 }
40 39  
41   - default Long selectCount(Long appId, Integer status) {
42   -
43   - return selectCount(new LambdaQueryWrapper<PayRefundDO>()
44   - .eq(PayRefundDO::getAppId, appId)
45   - .eq(PayRefundDO::getStatus, status));
  40 + default Long selectCountByApp(Long appId) {
  41 + return selectCount(PayRefundDO::getAppId, appId);
46 42 }
47 43  
48 44 default PayRefundDO selectByReqNo(String reqNo) {
... ... @@ -52,4 +48,5 @@ public interface PayRefundMapper extends BaseMapperX&lt;PayRefundDO&gt; {
52 48 default PayRefundDO selectByTradeNoAndMerchantRefundNo(String tradeNo, String merchantRefundNo){
53 49 return selectOne("trade_no", tradeNo, "merchant_refund_no", merchantRefundNo);
54 50 }
  51 +
55 52 }
... ...
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/app/PayAppService.java
... ... @@ -36,6 +36,14 @@ public interface PayAppService {
36 36 void updateApp(@Valid PayAppUpdateReqVO updateReqVO);
37 37  
38 38 /**
  39 + * 修改应用信息状态
  40 + *
  41 + * @param id 应用编号
  42 + * @param status 状态
  43 + */
  44 + void updateAppStatus(Long id, Integer status);
  45 +
  46 + /**
39 47 * 删除支付应用信息
40 48 *
41 49 * @param id 编号
... ... @@ -67,14 +75,6 @@ public interface PayAppService {
67 75 PageResult<PayAppDO> getAppPage(PayAppPageReqVO pageReqVO);
68 76  
69 77 /**
70   - * 修改应用信息状态
71   - *
72   - * @param id 应用编号
73   - * @param status 状态{@link cn.iocoder.yudao.framework.common.enums.CommonStatusEnum}
74   - */
75   - void updateAppStatus(Long id, Integer status);
76   -
77   - /**
78 78 * 获得指定编号的商户 Map
79 79 *
80 80 * @param ids 应用编号集合
... ... @@ -85,7 +85,6 @@ public interface PayAppService {
85 85 return CollectionUtils.convertMap(list, PayAppDO::getId);
86 86 }
87 87  
88   -
89 88 /**
90 89 * 支付应用的合法性
91 90 *
... ...
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;
9 9 import cn.iocoder.yudao.module.pay.convert.app.PayAppConvert;
10 10 import cn.iocoder.yudao.module.pay.dal.dataobject.app.PayAppDO;
11 11 import cn.iocoder.yudao.module.pay.dal.mysql.app.PayAppMapper;
12   -import cn.iocoder.yudao.module.pay.dal.mysql.order.PayOrderMapper;
13 12 import cn.iocoder.yudao.module.pay.dal.mysql.refund.PayRefundMapper;
14 13 import cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants;
15 14 import cn.iocoder.yudao.module.pay.enums.order.PayOrderStatusEnum;
16 15 import cn.iocoder.yudao.module.pay.enums.refund.PayRefundStatusEnum;
17   -import com.google.common.annotations.VisibleForTesting;
  16 +import cn.iocoder.yudao.module.pay.service.order.PayOrderService;
  17 +import cn.iocoder.yudao.module.pay.service.refund.PayRefundService;
  18 +import org.springframework.context.annotation.Lazy;
18 19 import org.springframework.stereotype.Service;
19 20 import org.springframework.validation.annotation.Validated;
20 21  
... ... @@ -23,11 +24,10 @@ import java.util.Collection;
23 24 import java.util.List;
24 25  
25 26 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
26   -import static cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants.PAY_APP_EXIST_TRANSACTION_ORDER_CANT_DELETE;
27   -import static cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants.PAY_APP_NOT_FOUND;
  27 +import static cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants.*;
28 28  
29 29 /**
30   - * 支付应用信息 Service 实现类
  30 + * 支付应用 Service 实现类
31 31 *
32 32 * @author aquan
33 33 */
... ... @@ -37,11 +37,13 @@ public class PayAppServiceImpl implements PayAppService {
37 37  
38 38 @Resource
39 39 private PayAppMapper appMapper;
40   - // TODO 芋艿:不能调用对方的 mapper
  40 +
41 41 @Resource
42   - private PayOrderMapper orderMapper;
  42 + @Lazy // 延迟加载,避免循环依赖报错
  43 + private PayOrderService orderService;
43 44 @Resource
44   - private PayRefundMapper refundMapper;
  45 + @Lazy // 延迟加载,避免循环依赖报错
  46 + private PayRefundService refundService;
45 47  
46 48 @Override
47 49 public Long createApp(PayAppCreateReqVO createReqVO) {
... ... @@ -55,17 +57,34 @@ public class PayAppServiceImpl implements PayAppService {
55 57 @Override
56 58 public void updateApp(PayAppUpdateReqVO updateReqVO) {
57 59 // 校验存在
58   - this.validateAppExists(updateReqVO.getId());
  60 + validateAppExists(updateReqVO.getId());
59 61 // 更新
60 62 PayAppDO updateObj = PayAppConvert.INSTANCE.convert(updateReqVO);
61 63 appMapper.updateById(updateObj);
62 64 }
63 65  
64 66 @Override
  67 + public void updateAppStatus(Long id, Integer status) {
  68 + // 校验商户存在
  69 + validateAppExists(id);
  70 + // 更新状态
  71 + PayAppDO app = new PayAppDO();
  72 + app.setId(id);
  73 + app.setStatus(status);
  74 + appMapper.updateById(app);
  75 + }
  76 +
  77 + @Override
65 78 public void deleteApp(Long id) {
66 79 // 校验存在
67   - this.validateAppExists(id);
68   - this.validateOrderTransactionExist(id);
  80 + validateAppExists(id);
  81 + // 校验关联数据是否存在
  82 + if (orderService.getOrderCountByAppId(id) > 0) {
  83 + throw exception(PAY_APP_EXIST_ORDER_CANT_DELETE);
  84 + }
  85 + if (refundService.getRefundCountByAppId(id) > 0) {
  86 + throw exception(PAY_APP_EXIST_REFUND_CANT_DELETE);
  87 + }
69 88  
70 89 // 删除
71 90 appMapper.deleteById(id);
... ... @@ -93,49 +112,6 @@ public class PayAppServiceImpl implements PayAppService {
93 112 }
94 113  
95 114 @Override
96   - public void updateAppStatus(Long id, Integer status) {
97   - // 校验商户存在
98   - this.checkAppExists(id);
99   - // 更新状态
100   - PayAppDO app = new PayAppDO();
101   - app.setId(id);
102   - app.setStatus(status);
103   - appMapper.updateById(app);
104   - }
105   -
106   - /**
107   - * 检查商户是否存在
108   - *
109   - * @param id 商户编号
110   - */
111   - @VisibleForTesting
112   - public void checkAppExists(Long id) {
113   - if (id == null) {
114   - return;
115   - }
116   - PayAppDO payApp = appMapper.selectById(id);
117   - if (payApp == null) {
118   - throw exception(PAY_APP_NOT_FOUND);
119   - }
120   - }
121   -
122   - /**
123   - * 验证是否存在交易中或者退款中等处理中状态的订单
124   - *
125   - * @param appId 应用 ID
126   - */
127   - private void validateOrderTransactionExist(Long appId) {
128   - // 查看交易订单
129   - if (orderMapper.selectCount(appId, PayOrderStatusEnum.WAITING.getStatus()) > 0) {
130   - throw exception(PAY_APP_EXIST_TRANSACTION_ORDER_CANT_DELETE);
131   - }
132   - // 查看退款订单
133   - if (refundMapper.selectCount(appId, PayRefundStatusEnum.CREATE.getStatus()) > 0) {
134   - throw exception(PAY_APP_EXIST_TRANSACTION_ORDER_CANT_DELETE);
135   - }
136   - }
137   -
138   - @Override
139 115 public PayAppDO validPayApp(Long id) {
140 116 PayAppDO app = appMapper.selectById(id);
141 117 // 校验是否存在
... ...
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/order/PayOrderService.java
... ... @@ -33,6 +33,14 @@ public interface PayOrderService {
33 33 PayOrderDO getOrder(Long id);
34 34  
35 35 /**
  36 + * 获得指定应用的订单数量
  37 + *
  38 + * @param appId 应用编号
  39 + * @return 订单数量
  40 + */
  41 + Long getOrderCountByAppId(Long appId);
  42 +
  43 + /**
36 44 * 获得支付订单
37 45 * 分页
38 46 *
... ...
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/order/PayOrderServiceImpl.java
... ... @@ -83,6 +83,11 @@ public class PayOrderServiceImpl implements PayOrderService {
83 83 }
84 84  
85 85 @Override
  86 + public Long getOrderCountByAppId(Long appId) {
  87 + return orderMapper.selectCountByAppId(appId);
  88 + }
  89 +
  90 + @Override
86 91 public PageResult<PayOrderDO> getOrderPage(PayOrderPageReqVO pageReqVO) {
87 92 return orderMapper.selectPage(pageReqVO);
88 93 }
... ...
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/refund/PayRefundService.java
... ... @@ -26,6 +26,14 @@ public interface PayRefundService {
26 26 PayRefundDO getRefund(Long id);
27 27  
28 28 /**
  29 + * 获得指定应用的退款数量
  30 + *
  31 + * @param appId 应用编号
  32 + * @return 退款数量
  33 + */
  34 + Long getRefundCountByAppId(Long appId);
  35 +
  36 + /**
29 37 * 获得退款订单分页
30 38 *
31 39 * @param pageReqVO 分页查询
... ...
yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/refund/PayRefundServiceImpl.java
... ... @@ -81,6 +81,11 @@ public class PayRefundServiceImpl implements PayRefundService {
81 81 }
82 82  
83 83 @Override
  84 + public Long getRefundCountByAppId(Long appId) {
  85 + return refundMapper.selectCountByApp(appId);
  86 + }
  87 +
  88 + @Override
84 89 public PageResult<PayRefundDO> getRefundPage(PayRefundPageReqVO pageReqVO) {
85 90 return refundMapper.selectPage(pageReqVO);
86 91 }
... ...
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;
3 3 import cn.hutool.core.util.RandomUtil;
4 4 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
5 5 import cn.iocoder.yudao.framework.common.pojo.PageResult;
  6 +import cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils;
6 7 import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
  8 +import cn.iocoder.yudao.framework.test.core.util.RandomUtils;
7 9 import cn.iocoder.yudao.module.pay.controller.admin.app.vo.PayAppCreateReqVO;
8 10 import cn.iocoder.yudao.module.pay.controller.admin.app.vo.PayAppPageReqVO;
9 11 import cn.iocoder.yudao.module.pay.controller.admin.app.vo.PayAppUpdateReqVO;
10 12 import cn.iocoder.yudao.module.pay.dal.dataobject.app.PayAppDO;
11 13 import cn.iocoder.yudao.module.pay.dal.mysql.app.PayAppMapper;
  14 +import cn.iocoder.yudao.module.pay.service.order.PayOrderService;
  15 +import cn.iocoder.yudao.module.pay.service.refund.PayRefundService;
12 16 import org.junit.jupiter.api.Test;
  17 +import org.springframework.boot.test.mock.mockito.MockBean;
13 18 import org.springframework.context.annotation.Import;
14 19  
15 20 import javax.annotation.Resource;
16 21 import java.time.LocalDateTime;
17 22  
  23 +import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.buildBetweenTime;
18 24 import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.buildTime;
19 25 import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId;
20 26 import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals;
21 27 import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException;
22   -import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomLongId;
23   -import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo;
  28 +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*;
24 29 import static cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants.PAY_APP_NOT_FOUND;
25 30 import static org.junit.jupiter.api.Assertions.*;
26 31  
  32 +/**
  33 + * {@link PayAppServiceImpl} 的单元测试
  34 + *
  35 + * @author aquan
  36 + */
27 37 @Import(PayAppServiceImpl.class)
28 38 public class PayAppServiceTest extends BaseDbUnitTest {
29 39  
... ... @@ -33,17 +43,23 @@ public class PayAppServiceTest extends BaseDbUnitTest {
33 43 @Resource
34 44 private PayAppMapper appMapper;
35 45  
  46 + @MockBean
  47 + private PayOrderService orderService;
  48 + @MockBean
  49 + private PayRefundService refundService;
  50 +
36 51 @Test
37 52 public void testCreateApp_success() {
38 53 // 准备参数
39 54 PayAppCreateReqVO reqVO = randomPojo(PayAppCreateReqVO.class, o ->
40   - o.setStatus((RandomUtil.randomEle(CommonStatusEnum.values()).getStatus())));
  55 + o.setStatus((RandomUtil.randomEle(CommonStatusEnum.values()).getStatus()))
  56 + .setPayNotifyUrl(randomURL())
  57 + .setRefundNotifyUrl(randomURL()));
41 58  
42 59 // 调用
43 60 Long appId = appService.createApp(reqVO);
44 61 // 断言
45 62 assertNotNull(appId);
46   - // 校验记录的属性是否正确
47 63 PayAppDO app = appMapper.selectById(appId);
48 64 assertPojoEquals(reqVO, app);
49 65 }
... ... @@ -57,6 +73,7 @@ public class PayAppServiceTest extends BaseDbUnitTest {
57 73 // 准备参数
58 74 PayAppUpdateReqVO reqVO = randomPojo(PayAppUpdateReqVO.class, o -> {
59 75 o.setStatus(CommonStatusEnum.ENABLE.getStatus());
  76 + o.setPayNotifyUrl(randomURL()).setRefundNotifyUrl(randomURL());
60 77 o.setId(dbApp.getId()); // 设置更新的 ID
61 78 });
62 79  
... ... @@ -106,9 +123,6 @@ public class PayAppServiceTest extends BaseDbUnitTest {
106 123 PayAppDO dbApp = randomPojo(PayAppDO.class, o -> { // 等会查询到
107 124 o.setName("灿灿姐的杂货铺");
108 125 o.setStatus(CommonStatusEnum.ENABLE.getStatus());
109   - o.setRemark("敏敏姐的小卖铺");
110   - o.setPayNotifyUrl("https://www.hc.com");
111   - o.setRefundNotifyUrl("https://www.xm.com");
112 126 o.setCreateTime(buildTime(2021,11,20));
113 127 });
114 128  
... ... @@ -117,22 +131,13 @@ public class PayAppServiceTest extends BaseDbUnitTest {
117 131 appMapper.insert(cloneIgnoreId(dbApp, o -> o.setName("敏敏姐的杂货铺")));
118 132 // 测试 status 不匹配
119 133 appMapper.insert(cloneIgnoreId(dbApp, o -> o.setStatus(CommonStatusEnum.DISABLE.getStatus())));
120   - // 测试 remark 不匹配
121   - appMapper.insert(cloneIgnoreId(dbApp, o -> o.setRemark("灿灿姐的小卖部")));
122   - // 测试 payNotifyUrl 不匹配
123   - appMapper.insert(cloneIgnoreId(dbApp, o -> o.setPayNotifyUrl("xm.com")));
124   - // 测试 refundNotifyUrl 不匹配
125   - appMapper.insert(cloneIgnoreId(dbApp, o -> o.setRefundNotifyUrl("hc.com")));
126 134 // 测试 createTime 不匹配
127 135 appMapper.insert(cloneIgnoreId(dbApp, o -> o.setCreateTime(buildTime(2021,12,21))));
128 136 // 准备参数
129 137 PayAppPageReqVO reqVO = new PayAppPageReqVO();
130 138 reqVO.setName("灿灿姐的杂货铺");
131 139 reqVO.setStatus(CommonStatusEnum.ENABLE.getStatus());
132   - reqVO.setRemark("敏敏姐的小卖铺");
133   - reqVO.setPayNotifyUrl("https://www.hc.com");
134   - reqVO.setRefundNotifyUrl("https://www.xm.com");
135   - reqVO.setCreateTime((new LocalDateTime[]{buildTime(2021,11,19),buildTime(2021,11,21)}));
  140 + reqVO.setCreateTime(buildBetweenTime(2021, 11, 19, 2021, 11, 21));
136 141  
137 142 // 调用
138 143 PageResult<PayAppDO> pageResult = appService.getAppPage(reqVO);
... ...
yudao-module-pay/yudao-module-pay-biz/src/test/resources/sql/clean.sql
1   -DELETE FROM pay_merchant;
2 1 DELETE FROM pay_app;
3 2 DELETE FROM pay_channel;
4 3 DELETE FROM pay_order;
... ...
yudao-module-pay/yudao-module-pay-biz/src/test/resources/sql/create_tables.sql
1   -CREATE TABLE IF NOT EXISTS "pay_merchant" (
2   - "id" number NOT NULL GENERATED BY DEFAULT AS IDENTITY,
3   - "no" varchar(32) NOT NULL,
4   - "name" varchar(64) NOT NULL,
5   - "short_name" varchar(64) NOT NULL,
6   - "status" tinyint NOT NULL,
7   - "remark" varchar(255) DEFAULT NULL,
8   - "creator" varchar(64) DEFAULT '',
9   - "create_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
10   - "updater" varchar(64) DEFAULT '',
11   - "update_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
12   - "deleted" bit(1) NOT NULL DEFAULT FALSE,
13   - PRIMARY KEY ("id")
14   -) COMMENT '支付商户信息';
15   -
16 1 CREATE TABLE IF NOT EXISTS "pay_app" (
17 2 "id" number NOT NULL GENERATED BY DEFAULT AS IDENTITY,
18 3 "name" varchar(64) NOT NULL,
... ... @@ -20,14 +5,13 @@ CREATE TABLE IF NOT EXISTS &quot;pay_app&quot; (
20 5 "remark" varchar(255) DEFAULT NULL,
21 6 `pay_notify_url` varchar(1024) NOT NULL,
22 7 `refund_notify_url` varchar(1024) NOT NULL,
23   - `merchant_id` bigint(20) NOT NULL,
24 8 "creator" varchar(64) DEFAULT '',
25 9 "create_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
26 10 "updater" varchar(64) DEFAULT '',
27 11 "update_time" datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
28 12 "deleted" bit(1) NOT NULL DEFAULT FALSE,
29 13 PRIMARY KEY ("id")
30   -) COMMENT = '支付应用信息';
  14 +) COMMENT = '支付应用';
31 15  
32 16 CREATE TABLE IF NOT EXISTS "pay_channel" (
33 17 "id" number NOT NULL GENERATED BY DEFAULT AS IDENTITY,
... ... @@ -35,7 +19,6 @@ CREATE TABLE IF NOT EXISTS &quot;pay_channel&quot; (
35 19 "status" tinyint(4) NOT NULL,
36 20 "remark" varchar(255) DEFAULT NULL,
37 21 "fee_rate" double NOT NULL DEFAULT 0,
38   - "merchant_id" bigint(20) NOT NULL,
39 22 "app_id" bigint(20) NOT NULL,
40 23 "config" varchar(10240) NOT NULL,
41 24 "creator" varchar(64) NULL DEFAULT '',
... ... @@ -49,7 +32,6 @@ CREATE TABLE IF NOT EXISTS &quot;pay_channel&quot; (
49 32  
50 33 CREATE TABLE IF NOT EXISTS `pay_order` (
51 34 "id" number NOT NULL GENERATED BY DEFAULT AS IDENTITY,
52   - `merchant_id` bigint(20) NOT NULL,
53 35 `app_id` bigint(20) NOT NULL,
54 36 `channel_id` bigint(20) DEFAULT NULL,
55 37 `channel_code` varchar(32) DEFAULT NULL,
... ... @@ -82,7 +64,6 @@ CREATE TABLE IF NOT EXISTS `pay_order` (
82 64  
83 65 CREATE TABLE IF NOT EXISTS `pay_refund` (
84 66 "id" number NOT NULL GENERATED BY DEFAULT AS IDENTITY,
85   - `merchant_id` bigint(20) NOT NULL,
86 67 `app_id` bigint(20) NOT NULL,
87 68 `channel_id` bigint(20) NOT NULL,
88 69 `channel_code` varchar(32) NOT NULL,
... ...