Commit d556eae5569ad2faedd74e82f8973dd5c61ccf0d

Authored by chen quan
1 parent 08103685

优化 支付配置校验方式,优化业务层异常抛出类型,优化支付应用渲染逻辑,添加删除支付商户 支付应用的校验,退款订单去除reqNo字段,支付订单去除 channelExtras 参数展示

Showing 34 changed files with 267 additions and 300 deletions
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/app/PayAppController.java
1 package cn.iocoder.yudao.adminserver.modules.pay.controller.app; 1 package cn.iocoder.yudao.adminserver.modules.pay.controller.app;
2 2
3 import cn.hutool.core.collection.CollUtil; 3 import cn.hutool.core.collection.CollUtil;
4 -import cn.hutool.core.util.StrUtil;  
5 import cn.iocoder.yudao.adminserver.modules.pay.controller.app.vo.*; 4 import cn.iocoder.yudao.adminserver.modules.pay.controller.app.vo.*;
6 import cn.iocoder.yudao.adminserver.modules.pay.convert.app.PayAppConvert; 5 import cn.iocoder.yudao.adminserver.modules.pay.convert.app.PayAppConvert;
7 import cn.iocoder.yudao.adminserver.modules.pay.service.app.PayAppService; 6 import cn.iocoder.yudao.adminserver.modules.pay.service.app.PayAppService;
@@ -10,12 +9,12 @@ import cn.iocoder.yudao.adminserver.modules.pay.service.merchant.PayMerchantServ @@ -10,12 +9,12 @@ import cn.iocoder.yudao.adminserver.modules.pay.service.merchant.PayMerchantServ
10 import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayAppDO; 9 import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayAppDO;
11 import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayChannelDO; 10 import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayChannelDO;
12 import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayMerchantDO; 11 import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayMerchantDO;
13 -import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;  
14 import cn.iocoder.yudao.framework.common.pojo.CommonResult; 12 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
15 import cn.iocoder.yudao.framework.common.pojo.PageResult; 13 import cn.iocoder.yudao.framework.common.pojo.PageResult;
16 import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; 14 import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
17 import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; 15 import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
18 import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; 16 import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog;
  17 +import cn.iocoder.yudao.framework.pay.core.enums.PayChannelEnum;
19 import io.swagger.annotations.Api; 18 import io.swagger.annotations.Api;
20 import io.swagger.annotations.ApiImplicitParam; 19 import io.swagger.annotations.ApiImplicitParam;
21 import io.swagger.annotations.ApiOperation; 20 import io.swagger.annotations.ApiOperation;
@@ -28,20 +27,11 @@ import javax.annotation.Resource; @@ -28,20 +27,11 @@ import javax.annotation.Resource;
28 import javax.servlet.http.HttpServletResponse; 27 import javax.servlet.http.HttpServletResponse;
29 import javax.validation.Valid; 28 import javax.validation.Valid;
30 import java.io.IOException; 29 import java.io.IOException;
31 -import java.lang.reflect.InvocationTargetException;  
32 -import java.util.ArrayList;  
33 -import java.util.Collection;  
34 -import java.util.List;  
35 -import java.util.Map; 30 +import java.util.*;
36 31
37 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; 32 import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
38 import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; 33 import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT;
39 34
40 -/**  
41 - * 支付应用信息 controller 组件  
42 - *  
43 - * @author aquan  
44 - */ // TODO @aquan:一般 controller 上就不写注释了,因为有 swagger 注解,不然就重复啦  
45 @Slf4j 35 @Slf4j
46 @Api(tags = "支付应用信息") 36 @Api(tags = "支付应用信息")
47 @RestController 37 @RestController
@@ -119,6 +109,7 @@ public class PayAppController { @@ -119,6 +109,7 @@ public class PayAppController {
119 // 得到所有的应用编号,查出所有的通道 109 // 得到所有的应用编号,查出所有的通道
120 Collection<Long> payAppIds = CollectionUtils.convertList(pageResult.getList(), PayAppDO::getId); 110 Collection<Long> payAppIds = CollectionUtils.convertList(pageResult.getList(), PayAppDO::getId);
121 List<PayChannelDO> channels = channelService.getChannelListByAppIds(payAppIds); 111 List<PayChannelDO> channels = channelService.getChannelListByAppIds(payAppIds);
  112 + Iterator<PayChannelDO> iterator = channels.iterator();
122 113
123 // 得到所有的商户信息 114 // 得到所有的商户信息
124 Collection<Long> merchantIds = CollectionUtils.convertList(pageResult.getList(), PayAppDO::getMerchantId); 115 Collection<Long> merchantIds = CollectionUtils.convertList(pageResult.getList(), PayAppDO::getMerchantId);
@@ -132,22 +123,15 @@ public class PayAppController { @@ -132,22 +123,15 @@ public class PayAppController {
132 // 写入商户的数据 123 // 写入商户的数据
133 respVO.setPayMerchant(PayAppConvert.INSTANCE.convert(deptMap.get(app.getMerchantId()))); 124 respVO.setPayMerchant(PayAppConvert.INSTANCE.convert(deptMap.get(app.getMerchantId())));
134 // 写入支付渠道信息的数据 125 // 写入支付渠道信息的数据
135 - // TODO @aquan:VO 里返回的 payChannel,是不是用一个 Set 集合就好了,里面是渠道的枚举值  
136 - PayAppPageItemRespVO.PayChannel payChannel = new PayAppPageItemRespVO.PayChannel();  
137 - channels.forEach(c -> {  
138 - if (c.getAppId().equals(app.getId())) {  
139 - // 获取 set 方法  
140 - String methodName = StrUtil.toCamelCase("set_" + c.getCode());  
141 - try {  
142 - // 根据 set 方法将值写入  
143 - payChannel.getClass().getMethod(methodName, Integer.class)  
144 - .invoke(payChannel, CommonStatusEnum.ENABLE.getStatus());  
145 - } catch (IllegalAccessException | NoSuchMethodException | InvocationTargetException e) {  
146 - log.error("[getAppPage]调用方法[{}]设置参数[{}]异常", c.getCode(), methodName);  
147 - } 126 + Set<String> channelCodes = new HashSet<>(PayChannelEnum.values().length);
  127 + while (iterator.hasNext()) {
  128 + PayChannelDO channelDO = iterator.next();
  129 + if (channelDO.getAppId().equals(app.getId())) {
  130 + channelCodes.add(channelDO.getCode());
  131 + iterator.remove();
148 } 132 }
149 - });  
150 - respVO.setPayChannel(payChannel); 133 + }
  134 + respVO.setChannelCodes(channelCodes);
151 appList.add(respVO); 135 appList.add(respVO);
152 }); 136 });
153 137
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/app/vo/PayAppPageItemRespVO.java
1 package cn.iocoder.yudao.adminserver.modules.pay.controller.app.vo; 1 package cn.iocoder.yudao.adminserver.modules.pay.controller.app.vo;
2 2
3 -import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;  
4 import io.swagger.annotations.ApiModel; 3 import io.swagger.annotations.ApiModel;
5 import io.swagger.annotations.ApiModelProperty; 4 import io.swagger.annotations.ApiModelProperty;
6 import lombok.Data; 5 import lombok.Data;
@@ -8,7 +7,13 @@ import lombok.EqualsAndHashCode; @@ -8,7 +7,13 @@ import lombok.EqualsAndHashCode;
8 import lombok.ToString; 7 import lombok.ToString;
9 8
10 import java.util.Date; 9 import java.util.Date;
  10 +import java.util.Set;
11 11
  12 +/**
  13 + * 支付应用信息分页查询 Response VO
  14 + *
  15 + * @author aquan
  16 + */
12 @ApiModel(value = "支付应用信息分页查询 Response VO", description = "相比于支付信息,还会多出应用渠道的开关信息") 17 @ApiModel(value = "支付应用信息分页查询 Response VO", description = "相比于支付信息,还会多出应用渠道的开关信息")
13 @Data 18 @Data
14 @EqualsAndHashCode(callSuper = true) 19 @EqualsAndHashCode(callSuper = true)
@@ -38,39 +43,8 @@ public class PayAppPageItemRespVO extends PayAppBaseVO { @@ -38,39 +43,8 @@ public class PayAppPageItemRespVO extends PayAppBaseVO {
38 43
39 } 44 }
40 45
41 - /**  
42 - * 支付渠道  
43 - */  
44 - private PayChannel payChannel;  
45 -  
46 - /**  
47 - * 支付渠道开通情况  
48 - * 1默认为未开通当前支付渠道,0为已开通支付渠道  
49 - */  
50 - @Data  
51 - @ApiModel("支付渠道")  
52 - public static class PayChannel {  
53 -  
54 - @ApiModelProperty(value = "微信 JSAPI 支付", required = true, example = "1")  
55 - private Integer wxPub = CommonStatusEnum.DISABLE.getStatus(); 46 + @ApiModelProperty(value = "渠道编码集合", required = true, example = "alipay_pc,alipay_wap...")
  47 + private Set<String> channelCodes;
56 48
57 - @ApiModelProperty(value = "微信小程序支付", required = true, example = "1")  
58 - private Integer wxLite = CommonStatusEnum.DISABLE.getStatus();  
59 -  
60 - @ApiModelProperty(value = "微信 App 支付", required = true, example = "1")  
61 - private Integer wxApp = CommonStatusEnum.DISABLE.getStatus();  
62 -  
63 - @ApiModelProperty(value = "支付宝 PC 网站支付", required = true, example = "1")  
64 - private Integer alipayPc = CommonStatusEnum.DISABLE.getStatus();  
65 -  
66 - @ApiModelProperty(value = "支付宝 Wap 网站支付", required = true, example = "1")  
67 - private Integer alipayWap = CommonStatusEnum.DISABLE.getStatus();  
68 -  
69 - @ApiModelProperty(value = "支付宝App 支付", required = true, example = "1")  
70 - private Integer alipayApp = CommonStatusEnum.DISABLE.getStatus();  
71 -  
72 - @ApiModelProperty(value = "支付宝扫码支付", required = true, example = "1")  
73 - private Integer alipayQr = CommonStatusEnum.DISABLE.getStatus();  
74 - }  
75 49
76 } 50 }
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/merchant/PayMerchantController.java
@@ -75,7 +75,7 @@ public class PayMerchantController { @@ -75,7 +75,7 @@ public class PayMerchantController {
75 return success(PayMerchantConvert.INSTANCE.convert(merchant)); 75 return success(PayMerchantConvert.INSTANCE.convert(merchant));
76 } 76 }
77 77
78 - @GetMapping("/list-name") // TODO @aquan:/list-name =》/list-by-name 78 + @GetMapping("/list-by-name")
79 @ApiOperation("根据商户名称获得支付商户信息列表") 79 @ApiOperation("根据商户名称获得支付商户信息列表")
80 @ApiImplicitParam(name = "name", value = "商户名称", example = "芋道", dataTypeClass = Long.class) 80 @ApiImplicitParam(name = "name", value = "商户名称", example = "芋道", dataTypeClass = Long.class)
81 @PreAuthorize("@ss.hasPermission('pay:merchant:query')") 81 @PreAuthorize("@ss.hasPermission('pay:merchant:query')")
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/merchant/vo/PayMerchantExcelVO.java
@@ -2,11 +2,10 @@ package cn.iocoder.yudao.adminserver.modules.pay.controller.merchant.vo; @@ -2,11 +2,10 @@ package cn.iocoder.yudao.adminserver.modules.pay.controller.merchant.vo;
2 2
3 import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; 3 import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat;
4 import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; 4 import cn.iocoder.yudao.framework.excel.core.convert.DictConvert;
5 -import lombok.*;  
6 -import java.util.*;  
7 -import io.swagger.annotations.*;  
8 -  
9 import com.alibaba.excel.annotation.ExcelProperty; 5 import com.alibaba.excel.annotation.ExcelProperty;
  6 +import lombok.Data;
  7 +
  8 +import java.util.Date;
10 9
11 /** 10 /**
12 * 支付商户信息 Excel VO 11 * 支付商户信息 Excel VO
@@ -29,7 +28,7 @@ public class PayMerchantExcelVO { @@ -29,7 +28,7 @@ public class PayMerchantExcelVO {
29 private String shortName; 28 private String shortName;
30 29
31 @ExcelProperty(value = "开启状态",converter = DictConvert.class) 30 @ExcelProperty(value = "开启状态",converter = DictConvert.class)
32 - @DictFormat("pay_merchant_status") 31 + @DictFormat("sys_common_status")
33 private Integer status; 32 private Integer status;
34 33
35 @ExcelProperty("备注") 34 @ExcelProperty("备注")
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/order/vo/order/PayOrderDetailsRespVO.java
@@ -46,9 +46,6 @@ public class PayOrderDetailsRespVO extends PayOrderBaseVO { @@ -46,9 +46,6 @@ public class PayOrderDetailsRespVO extends PayOrderBaseVO {
46 @ApiModelProperty(value = "支付订单号") 46 @ApiModelProperty(value = "支付订单号")
47 private String no; 47 private String no;
48 48
49 - @ApiModelProperty(value = "支付渠道的额外参数")  
50 - private String channelExtras;  
51 -  
52 @ApiModelProperty(value = "支付异步通知的内容") 49 @ApiModelProperty(value = "支付异步通知的内容")
53 private String channelNotifyData; 50 private String channelNotifyData;
54 } 51 }
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/order/vo/refund/vo/PayRefundBaseVO.java
@@ -16,10 +16,6 @@ import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_ @@ -16,10 +16,6 @@ import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_
16 @Data 16 @Data
17 public class PayRefundBaseVO { 17 public class PayRefundBaseVO {
18 18
19 - @ApiModelProperty(value = "退款单请求号", required = true)  
20 - @NotNull(message = "退款单请求号不能为空")  
21 - private String reqNo;  
22 -  
23 @ApiModelProperty(value = "商户编号", required = true) 19 @ApiModelProperty(value = "商户编号", required = true)
24 @NotNull(message = "商户编号不能为空") 20 @NotNull(message = "商户编号不能为空")
25 private Long merchantId; 21 private Long merchantId;
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/order/vo/refund/vo/PayRefundExcelVO.java
@@ -22,9 +22,6 @@ public class PayRefundExcelVO { @@ -22,9 +22,6 @@ public class PayRefundExcelVO {
22 @ExcelProperty("商品名称") 22 @ExcelProperty("商品名称")
23 private String subject; 23 private String subject;
24 24
25 - @ExcelProperty("退款单请求号")  
26 - private String reqNo;  
27 -  
28 @ExcelProperty(value = "商户名称") 25 @ExcelProperty(value = "商户名称")
29 private String merchantName; 26 private String merchantName;
30 27
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/order/vo/refund/vo/PayRefundExportReqVO.java
@@ -13,9 +13,6 @@ import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_ @@ -13,9 +13,6 @@ import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_
13 @Data 13 @Data
14 public class PayRefundExportReqVO { 14 public class PayRefundExportReqVO {
15 15
16 - @ApiModelProperty(value = "退款单请求号")  
17 - private String reqNo;  
18 -  
19 @ApiModelProperty(value = "商户编号") 16 @ApiModelProperty(value = "商户编号")
20 private Long merchantId; 17 private Long merchantId;
21 18
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/order/vo/refund/vo/PayRefundPageReqVO.java
@@ -18,9 +18,6 @@ import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_ @@ -18,9 +18,6 @@ import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_
18 @ToString(callSuper = true) 18 @ToString(callSuper = true)
19 public class PayRefundPageReqVO extends PageParam { 19 public class PayRefundPageReqVO extends PageParam {
20 20
21 - @ApiModelProperty(value = "退款单请求号")  
22 - private String reqNo;  
23 -  
24 @ApiModelProperty(value = "商户编号") 21 @ApiModelProperty(value = "商户编号")
25 private Long merchantId; 22 private Long merchantId;
26 23
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/convert/order/PayOrderConvert.java
@@ -8,8 +8,6 @@ import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.order.PayOrderDO; @@ -8,8 +8,6 @@ import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.order.PayOrderDO;
8 import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.order.PayOrderExtensionDO; 8 import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.order.PayOrderExtensionDO;
9 import cn.iocoder.yudao.framework.common.pojo.PageResult; 9 import cn.iocoder.yudao.framework.common.pojo.PageResult;
10 import org.mapstruct.Mapper; 10 import org.mapstruct.Mapper;
11 -import org.mapstruct.Mapping;  
12 -import org.mapstruct.Mappings;  
13 import org.mapstruct.factory.Mappers; 11 import org.mapstruct.factory.Mappers;
14 12
15 import java.math.BigDecimal; 13 import java.math.BigDecimal;
@@ -44,10 +42,6 @@ public interface PayOrderConvert { @@ -44,10 +42,6 @@ public interface PayOrderConvert {
44 * @param bean 订单扩展DO 42 * @param bean 订单扩展DO
45 * @return 详细订单扩展 RespVO 43 * @return 详细订单扩展 RespVO
46 */ 44 */
47 - @Mappings({  
48 - @Mapping(target = "channelExtras"  
49 - , expression = "java(bean.getChannelExtras() != null ? bean.getChannelExtras().toString():null)")  
50 - })  
51 PayOrderDetailsRespVO.PayOrderExtension orderDetailExtensionConvert(PayOrderExtensionDO bean); 45 PayOrderDetailsRespVO.PayOrderExtension orderDetailExtensionConvert(PayOrderExtensionDO bean);
52 46
53 List<PayOrderRespVO> convertList(List<PayOrderDO> list); 47 List<PayOrderRespVO> convertList(List<PayOrderDO> list);
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/convert/refund/PayRefundConvert.java
@@ -62,7 +62,6 @@ public interface PayRefundConvert { @@ -62,7 +62,6 @@ public interface PayRefundConvert {
62 PayRefundExcelVO payRefundExcelVO = new PayRefundExcelVO(); 62 PayRefundExcelVO payRefundExcelVO = new PayRefundExcelVO();
63 63
64 payRefundExcelVO.setId(bean.getId()); 64 payRefundExcelVO.setId(bean.getId());
65 - payRefundExcelVO.setReqNo(bean.getReqNo());  
66 payRefundExcelVO.setTradeNo(bean.getTradeNo()); 65 payRefundExcelVO.setTradeNo(bean.getTradeNo());
67 payRefundExcelVO.setMerchantOrderId(bean.getMerchantOrderId()); 66 payRefundExcelVO.setMerchantOrderId(bean.getMerchantOrderId());
68 payRefundExcelVO.setMerchantRefundNo(bean.getMerchantRefundNo()); 67 payRefundExcelVO.setMerchantRefundNo(bean.getMerchantRefundNo());
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/dal/mysql/app/PayAppMapper.java
@@ -60,12 +60,24 @@ public interface PayAppMapper extends BaseMapperX&lt;PayAppDO&gt; { @@ -60,12 +60,24 @@ public interface PayAppMapper extends BaseMapperX&lt;PayAppDO&gt; {
60 60
61 /** 61 /**
62 * 根据 商户 ID 查询支付应用信息 62 * 根据 商户 ID 查询支付应用信息
  63 + *
63 * @param merchantId 商户 ID 64 * @param merchantId 商户 ID
64 * @return 支付应用信息列表 65 * @return 支付应用信息列表
65 */ 66 */
66 - default List<PayAppDO> getListByMerchantId(String merchantId){ 67 + default List<PayAppDO> getListByMerchantId(String merchantId) {
67 return selectList(new LambdaQueryWrapper<PayAppDO>() 68 return selectList(new LambdaQueryWrapper<PayAppDO>()
68 .select(PayAppDO::getId, PayAppDO::getName) 69 .select(PayAppDO::getId, PayAppDO::getName)
69 .eq(PayAppDO::getMerchantId, merchantId)); 70 .eq(PayAppDO::getMerchantId, merchantId));
70 } 71 }
  72 +
  73 + /**
  74 + * 根据商户号统计存在的支付应用数量
  75 + *
  76 + * @param merchantId 商户 ID
  77 + * @return 支付应用数量
  78 + */
  79 + default Long selectCount(Long merchantId) {
  80 + return selectCount(new LambdaQueryWrapper<PayAppDO>().eq(PayAppDO::getMerchantId, merchantId));
  81 + }
  82 +
71 } 83 }
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/dal/mysql/channel/PayChannelMapper.java
@@ -55,8 +55,7 @@ public interface PayChannelMapper extends BaseMapperX&lt;PayChannelDO&gt; { @@ -55,8 +55,7 @@ public interface PayChannelMapper extends BaseMapperX&lt;PayChannelDO&gt; {
55 * @param code 通道编码 55 * @param code 通道编码
56 * @return 数量 56 * @return 数量
57 */ 57 */
58 - // TODO @aquan:Mapper 的操作,和 db 保持一致  
59 - default Integer getChannelCountByConditions(Long merchantId, Long appid, String code) { 58 + default Integer selectCount(Long merchantId, Long appid, String code) {
60 return this.selectCount(new QueryWrapper<PayChannelDO>().lambda() 59 return this.selectCount(new QueryWrapper<PayChannelDO>().lambda()
61 .eq(PayChannelDO::getMerchantId, merchantId) 60 .eq(PayChannelDO::getMerchantId, merchantId)
62 .eq(PayChannelDO::getAppId, appid) 61 .eq(PayChannelDO::getAppId, appid)
@@ -71,7 +70,7 @@ public interface PayChannelMapper extends BaseMapperX&lt;PayChannelDO&gt; { @@ -71,7 +70,7 @@ public interface PayChannelMapper extends BaseMapperX&lt;PayChannelDO&gt; {
71 * @param code 通道编码 70 * @param code 通道编码
72 * @return 数量 71 * @return 数量
73 */ 72 */
74 - default PayChannelDO getChannelByConditions(Long merchantId, Long appid, String code) { 73 + default PayChannelDO selectOne(Long merchantId, Long appid, String code) {
75 return this.selectOne((new QueryWrapper<PayChannelDO>().lambda() 74 return this.selectOne((new QueryWrapper<PayChannelDO>().lambda()
76 .eq(PayChannelDO::getMerchantId, merchantId) 75 .eq(PayChannelDO::getMerchantId, merchantId)
77 .eq(PayChannelDO::getAppId, appid) 76 .eq(PayChannelDO::getAppId, appid)
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/dal/mysql/order/PayOrderMapper.java
@@ -62,4 +62,18 @@ public interface PayOrderMapper extends BaseMapperX&lt;PayOrderDO&gt; { @@ -62,4 +62,18 @@ public interface PayOrderMapper extends BaseMapperX&lt;PayOrderDO&gt; {
62 .in(PayOrderDO::getId, idList)); 62 .in(PayOrderDO::getId, idList));
63 } 63 }
64 64
  65 + /**
  66 + * 查询符合的订单数量
  67 + *
  68 + * @param appId 应用编号
  69 + * @param status 订单状态
  70 + * @return 条数
  71 + */
  72 + default Long selectCount(Long appId, Integer status) {
  73 +
  74 + return selectCount(new LambdaQueryWrapper<PayOrderDO>()
  75 + .eq(PayOrderDO::getAppId, appId)
  76 + .in(PayOrderDO::getStatus, status));
  77 + }
  78 +
65 } 79 }
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/dal/mysql/order/PayRefundMapper.java
@@ -6,6 +6,7 @@ import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.order.PayRefundDO @@ -6,6 +6,7 @@ import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.order.PayRefundDO
6 import cn.iocoder.yudao.framework.common.pojo.PageResult; 6 import cn.iocoder.yudao.framework.common.pojo.PageResult;
7 import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; 7 import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
8 import cn.iocoder.yudao.framework.mybatis.core.query.QueryWrapperX; 8 import cn.iocoder.yudao.framework.mybatis.core.query.QueryWrapperX;
  9 +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
9 import org.apache.ibatis.annotations.Mapper; 10 import org.apache.ibatis.annotations.Mapper;
10 11
11 import java.util.List; 12 import java.util.List;
@@ -20,7 +21,6 @@ public interface PayRefundMapper extends BaseMapperX&lt;PayRefundDO&gt; { @@ -20,7 +21,6 @@ public interface PayRefundMapper extends BaseMapperX&lt;PayRefundDO&gt; {
20 21
21 default PageResult<PayRefundDO> selectPage(PayRefundPageReqVO reqVO) { 22 default PageResult<PayRefundDO> selectPage(PayRefundPageReqVO reqVO) {
22 return selectPage(reqVO, new QueryWrapperX<PayRefundDO>() 23 return selectPage(reqVO, new QueryWrapperX<PayRefundDO>()
23 - .likeIfPresent("req_no", reqVO.getReqNo())  
24 .eqIfPresent("merchant_id", reqVO.getMerchantId()) 24 .eqIfPresent("merchant_id", reqVO.getMerchantId())
25 .eqIfPresent("app_id", reqVO.getAppId()) 25 .eqIfPresent("app_id", reqVO.getAppId())
26 .eqIfPresent("channel_code", reqVO.getChannelCode()) 26 .eqIfPresent("channel_code", reqVO.getChannelCode())
@@ -37,7 +37,6 @@ public interface PayRefundMapper extends BaseMapperX&lt;PayRefundDO&gt; { @@ -37,7 +37,6 @@ public interface PayRefundMapper extends BaseMapperX&lt;PayRefundDO&gt; {
37 .eqIfPresent("merchant_id", reqVO.getMerchantId()) 37 .eqIfPresent("merchant_id", reqVO.getMerchantId())
38 .eqIfPresent("app_id", reqVO.getAppId()) 38 .eqIfPresent("app_id", reqVO.getAppId())
39 .eqIfPresent("channel_code", reqVO.getChannelCode()) 39 .eqIfPresent("channel_code", reqVO.getChannelCode())
40 - .likeIfPresent("req_no", reqVO.getReqNo())  
41 .likeIfPresent("merchant_refund_no", reqVO.getMerchantRefundNo()) 40 .likeIfPresent("merchant_refund_no", reqVO.getMerchantRefundNo())
42 .eqIfPresent("type", reqVO.getType()) 41 .eqIfPresent("type", reqVO.getType())
43 .eqIfPresent("status", reqVO.getStatus()) 42 .eqIfPresent("status", reqVO.getStatus())
@@ -46,4 +45,17 @@ public interface PayRefundMapper extends BaseMapperX&lt;PayRefundDO&gt; { @@ -46,4 +45,17 @@ public interface PayRefundMapper extends BaseMapperX&lt;PayRefundDO&gt; {
46 .orderByDesc("id")); 45 .orderByDesc("id"));
47 } 46 }
48 47
  48 + /**
  49 + * 查询符合的订单数量
  50 + *
  51 + * @param appId 应用编号
  52 + * @param status 订单状态
  53 + * @return 条数
  54 + */
  55 + default Long selectCount(Long appId, Integer status) {
  56 +
  57 + return selectCount(new LambdaQueryWrapper<PayRefundDO>()
  58 + .eq(PayRefundDO::getAppId, appId)
  59 + .eq(PayRefundDO::getStatus, status));
  60 + }
49 } 61 }
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/service/app/impl/PayAppServiceImpl.java
@@ -9,9 +9,13 @@ import cn.iocoder.yudao.adminserver.modules.pay.controller.app.vo.PayAppUpdateRe @@ -9,9 +9,13 @@ import cn.iocoder.yudao.adminserver.modules.pay.controller.app.vo.PayAppUpdateRe
9 import cn.iocoder.yudao.adminserver.modules.pay.convert.app.PayAppConvert; 9 import cn.iocoder.yudao.adminserver.modules.pay.convert.app.PayAppConvert;
10 import cn.iocoder.yudao.adminserver.modules.pay.dal.mysql.app.PayAppMapper; 10 import cn.iocoder.yudao.adminserver.modules.pay.dal.mysql.app.PayAppMapper;
11 import cn.iocoder.yudao.adminserver.modules.pay.dal.mysql.merchant.PayMerchantMapper; 11 import cn.iocoder.yudao.adminserver.modules.pay.dal.mysql.merchant.PayMerchantMapper;
  12 +import cn.iocoder.yudao.adminserver.modules.pay.dal.mysql.order.PayOrderMapper;
  13 +import cn.iocoder.yudao.adminserver.modules.pay.dal.mysql.order.PayRefundMapper;
12 import cn.iocoder.yudao.adminserver.modules.pay.service.app.PayAppService; 14 import cn.iocoder.yudao.adminserver.modules.pay.service.app.PayAppService;
13 import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayAppDO; 15 import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayAppDO;
14 import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayMerchantDO; 16 import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayMerchantDO;
  17 +import cn.iocoder.yudao.coreservice.modules.pay.enums.order.PayOrderStatusEnum;
  18 +import cn.iocoder.yudao.coreservice.modules.pay.enums.order.PayRefundStatusEnum;
15 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; 19 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
16 import cn.iocoder.yudao.framework.common.pojo.PageResult; 20 import cn.iocoder.yudao.framework.common.pojo.PageResult;
17 import com.google.common.annotations.VisibleForTesting; 21 import com.google.common.annotations.VisibleForTesting;
@@ -21,7 +25,7 @@ import org.springframework.validation.annotation.Validated; @@ -21,7 +25,7 @@ import org.springframework.validation.annotation.Validated;
21 import javax.annotation.Resource; 25 import javax.annotation.Resource;
22 import java.util.*; 26 import java.util.*;
23 27
24 -import static cn.iocoder.yudao.coreservice.modules.pay.enums.PayErrorCodeCoreConstants.PAY_APP_NOT_FOUND; 28 +import static cn.iocoder.yudao.coreservice.modules.pay.enums.PayErrorCodeCoreConstants.*;
25 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; 29 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
26 import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; 30 import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
27 31
@@ -36,9 +40,17 @@ public class PayAppServiceImpl implements PayAppService { @@ -36,9 +40,17 @@ public class PayAppServiceImpl implements PayAppService {
36 40
37 @Resource 41 @Resource
38 private PayAppMapper appMapper; 42 private PayAppMapper appMapper;
  43 +
39 @Resource 44 @Resource
40 private PayMerchantMapper merchantMapper; 45 private PayMerchantMapper merchantMapper;
41 46
  47 + @Resource
  48 + private PayOrderMapper orderMapper;
  49 +
  50 + @Resource
  51 + private PayRefundMapper refundMapper;
  52 +
  53 +
42 @Override 54 @Override
43 public Long createApp(PayAppCreateReqVO createReqVO) { 55 public Long createApp(PayAppCreateReqVO createReqVO) {
44 // 插入 56 // 插入
@@ -61,7 +73,8 @@ public class PayAppServiceImpl implements PayAppService { @@ -61,7 +73,8 @@ public class PayAppServiceImpl implements PayAppService {
61 public void deleteApp(Long id) { 73 public void deleteApp(Long id) {
62 // 校验存在 74 // 校验存在
63 this.validateAppExists(id); 75 this.validateAppExists(id);
64 - // TODO aquan:校验是否存在进行中的支付单、退款单,如果是,则不允许删除。 76 + this.validateOrderTransactionExist(id);
  77 +
65 // 删除 78 // 删除
66 appMapper.deleteById(id); 79 appMapper.deleteById(id);
67 } 80 }
@@ -157,4 +170,21 @@ public class PayAppServiceImpl implements PayAppService { @@ -157,4 +170,21 @@ public class PayAppServiceImpl implements PayAppService {
157 } 170 }
158 } 171 }
159 172
  173 + /**
  174 + * 验证是否存在交易中或者退款中等处理中状态的订单
  175 + *
  176 + * @param appId 应用 ID
  177 + */
  178 + private void validateOrderTransactionExist(Long appId) {
  179 + // 查看交易订单
  180 + if (orderMapper.selectCount(appId, PayOrderStatusEnum.WAITING.getStatus()) > 0) {
  181 + throw exception(PAY_APP_EXIST_TRANSACTION_ORDER_CANT_DELETE);
  182 + }
  183 + // 查看退款订单
  184 + if (refundMapper.selectCount(appId, PayRefundStatusEnum.CREATE.getStatus()) > 0) {
  185 + throw exception(PAY_APP_EXIST_TRANSACTION_ORDER_CANT_DELETE);
  186 + }
  187 +
  188 + }
  189 +
160 } 190 }
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/service/channel/impl/PayChannelServiceImpl.java
1 package cn.iocoder.yudao.adminserver.modules.pay.service.channel.impl; 1 package cn.iocoder.yudao.adminserver.modules.pay.service.channel.impl;
2 2
  3 +import cn.hutool.core.util.ObjectUtil;
3 import cn.hutool.json.JSONUtil; 4 import cn.hutool.json.JSONUtil;
4 import cn.iocoder.yudao.adminserver.modules.pay.controller.channel.vo.PayChannelCreateReqVO; 5 import cn.iocoder.yudao.adminserver.modules.pay.controller.channel.vo.PayChannelCreateReqVO;
5 import cn.iocoder.yudao.adminserver.modules.pay.controller.channel.vo.PayChannelExportReqVO; 6 import cn.iocoder.yudao.adminserver.modules.pay.controller.channel.vo.PayChannelExportReqVO;
@@ -14,7 +15,6 @@ import cn.iocoder.yudao.framework.pay.core.client.PayClientConfig; @@ -14,7 +15,6 @@ import cn.iocoder.yudao.framework.pay.core.client.PayClientConfig;
14 import cn.iocoder.yudao.framework.pay.core.enums.PayChannelEnum; 15 import cn.iocoder.yudao.framework.pay.core.enums.PayChannelEnum;
15 import lombok.extern.slf4j.Slf4j; 16 import lombok.extern.slf4j.Slf4j;
16 import org.springframework.stereotype.Service; 17 import org.springframework.stereotype.Service;
17 -import org.springframework.util.Assert;  
18 import org.springframework.validation.annotation.Validated; 18 import org.springframework.validation.annotation.Validated;
19 19
20 import javax.annotation.Resource; 20 import javax.annotation.Resource;
@@ -46,8 +46,9 @@ public class PayChannelServiceImpl implements PayChannelService { @@ -46,8 +46,9 @@ public class PayChannelServiceImpl implements PayChannelService {
46 public Long createChannel(PayChannelCreateReqVO reqVO) { 46 public Long createChannel(PayChannelCreateReqVO reqVO) {
47 // 断言是否有重复的 47 // 断言是否有重复的
48 PayChannelDO channelDO = this.getChannelByConditions(reqVO.getMerchantId(), reqVO.getAppId(), reqVO.getCode()); 48 PayChannelDO channelDO = this.getChannelByConditions(reqVO.getMerchantId(), reqVO.getAppId(), reqVO.getCode());
49 - // TODO @aquan:这里会抛出系统异常,不会抛出 ServiceException  
50 - Assert.isNull(channelDO, CHANNEL_EXIST_SAME_CHANNEL_ERROR.getMsg()); 49 + if (ObjectUtil.isNotNull(channelDO)) {
  50 + throw exception(CHANNEL_EXIST_SAME_CHANNEL_ERROR);
  51 + }
51 52
52 // 新增渠道 53 // 新增渠道
53 PayChannelDO channel = PayChannelConvert.INSTANCE.convert(reqVO); 54 PayChannelDO channel = PayChannelConvert.INSTANCE.convert(reqVO);
@@ -122,7 +123,7 @@ public class PayChannelServiceImpl implements PayChannelService { @@ -122,7 +123,7 @@ public class PayChannelServiceImpl implements PayChannelService {
122 */ 123 */
123 @Override 124 @Override
124 public Integer getChannelCountByConditions(Long merchantId, Long appid, String code) { 125 public Integer getChannelCountByConditions(Long merchantId, Long appid, String code) {
125 - return this.channelMapper.getChannelCountByConditions(merchantId, appid, code); 126 + return this.channelMapper.selectCount(merchantId, appid, code);
126 } 127 }
127 128
128 /** 129 /**
@@ -135,7 +136,7 @@ public class PayChannelServiceImpl implements PayChannelService { @@ -135,7 +136,7 @@ public class PayChannelServiceImpl implements PayChannelService {
135 */ 136 */
136 @Override 137 @Override
137 public PayChannelDO getChannelByConditions(Long merchantId, Long appid, String code) { 138 public PayChannelDO getChannelByConditions(Long merchantId, Long appid, String code) {
138 - return this.channelMapper.getChannelByConditions(merchantId, appid, code); 139 + return this.channelMapper.selectOne(merchantId, appid, code);
139 } 140 }
140 141
141 /** 142 /**
@@ -146,11 +147,14 @@ public class PayChannelServiceImpl implements PayChannelService { @@ -146,11 +147,14 @@ public class PayChannelServiceImpl implements PayChannelService {
146 */ 147 */
147 private void settingConfigAndCheckParam(PayChannelDO channel, String configStr) { 148 private void settingConfigAndCheckParam(PayChannelDO channel, String configStr) {
148 // 得到这个渠道是微信的还是支付宝的 149 // 得到这个渠道是微信的还是支付宝的
149 - Class<? extends PayClientConfig> payClass = PayChannelEnum.findByCodeGetClass(channel.getCode());  
150 - Assert.notNull(payClass, CHANNEL_NOT_EXISTS.getMsg()); 150 + Class<? extends PayClientConfig> payClass = PayChannelEnum.getByCode(channel.getCode()).getConfigClass();
  151 + if (ObjectUtil.isNull(payClass)) {
  152 + throw exception(CHANNEL_NOT_EXISTS);
  153 + }
151 PayClientConfig config = JSONUtil.toBean(configStr, payClass); 154 PayClientConfig config = JSONUtil.toBean(configStr, payClass);
  155 +
152 // 验证参数 156 // 验证参数
153 - config.verifyParam(validator); 157 + config.validate(validator);
154 channel.setConfig(config); 158 channel.setConfig(config);
155 } 159 }
156 160
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/service/merchant/PayMerchantService.java
@@ -16,7 +16,7 @@ import java.util.Map; @@ -16,7 +16,7 @@ import java.util.Map;
16 /** 16 /**
17 * 支付商户信息 Service 接口 17 * 支付商户信息 Service 接口
18 * 18 *
19 - * @author 芋艿 TODO @aquan:作者是你哈 19 + * @author aquan
20 */ 20 */
21 public interface PayMerchantService { 21 public interface PayMerchantService {
22 22
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/service/merchant/impl/PayMerchantServiceImpl.java
1 package cn.iocoder.yudao.adminserver.modules.pay.service.merchant.impl; 1 package cn.iocoder.yudao.adminserver.modules.pay.service.merchant.impl;
2 2
3 import cn.hutool.core.date.DateUtil; 3 import cn.hutool.core.date.DateUtil;
  4 +import cn.hutool.core.util.ObjectUtil;
4 import cn.iocoder.yudao.adminserver.modules.pay.controller.merchant.vo.PayMerchantCreateReqVO; 5 import cn.iocoder.yudao.adminserver.modules.pay.controller.merchant.vo.PayMerchantCreateReqVO;
5 import cn.iocoder.yudao.adminserver.modules.pay.controller.merchant.vo.PayMerchantExportReqVO; 6 import cn.iocoder.yudao.adminserver.modules.pay.controller.merchant.vo.PayMerchantExportReqVO;
6 import cn.iocoder.yudao.adminserver.modules.pay.controller.merchant.vo.PayMerchantPageReqVO; 7 import cn.iocoder.yudao.adminserver.modules.pay.controller.merchant.vo.PayMerchantPageReqVO;
7 import cn.iocoder.yudao.adminserver.modules.pay.controller.merchant.vo.PayMerchantUpdateReqVO; 8 import cn.iocoder.yudao.adminserver.modules.pay.controller.merchant.vo.PayMerchantUpdateReqVO;
8 import cn.iocoder.yudao.adminserver.modules.pay.convert.merchant.PayMerchantConvert; 9 import cn.iocoder.yudao.adminserver.modules.pay.convert.merchant.PayMerchantConvert;
  10 +import cn.iocoder.yudao.adminserver.modules.pay.dal.mysql.app.PayAppMapper;
9 import cn.iocoder.yudao.adminserver.modules.pay.dal.mysql.merchant.PayMerchantMapper; 11 import cn.iocoder.yudao.adminserver.modules.pay.dal.mysql.merchant.PayMerchantMapper;
10 import cn.iocoder.yudao.adminserver.modules.pay.service.merchant.PayMerchantService; 12 import cn.iocoder.yudao.adminserver.modules.pay.service.merchant.PayMerchantService;
11 import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayMerchantDO; 13 import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayMerchantDO;
@@ -19,6 +21,7 @@ import java.time.LocalDateTime; @@ -19,6 +21,7 @@ import java.time.LocalDateTime;
19 import java.util.Collection; 21 import java.util.Collection;
20 import java.util.List; 22 import java.util.List;
21 23
  24 +import static cn.iocoder.yudao.coreservice.modules.pay.enums.PayErrorCodeCoreConstants.PAY_MERCHANT_EXIST_APP_CANT_DELETE;
22 import static cn.iocoder.yudao.coreservice.modules.pay.enums.PayErrorCodeCoreConstants.PAY_MERCHANT_NOT_EXISTS; 25 import static cn.iocoder.yudao.coreservice.modules.pay.enums.PayErrorCodeCoreConstants.PAY_MERCHANT_NOT_EXISTS;
23 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; 26 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
24 27
@@ -34,6 +37,9 @@ public class PayMerchantServiceImpl implements PayMerchantService { @@ -34,6 +37,9 @@ public class PayMerchantServiceImpl implements PayMerchantService {
34 @Resource 37 @Resource
35 private PayMerchantMapper merchantMapper; 38 private PayMerchantMapper merchantMapper;
36 39
  40 + @Resource
  41 + private PayAppMapper appMapper;
  42 +
37 @Override 43 @Override
38 public Long createMerchant(PayMerchantCreateReqVO createReqVO) { 44 public Long createMerchant(PayMerchantCreateReqVO createReqVO) {
39 // 插入 45 // 插入
@@ -55,19 +61,13 @@ public class PayMerchantServiceImpl implements PayMerchantService { @@ -55,19 +61,13 @@ public class PayMerchantServiceImpl implements PayMerchantService {
55 61
56 @Override 62 @Override
57 public void deleteMerchant(Long id) { 63 public void deleteMerchant(Long id) {
58 - // 校验存在 64 + // 校验
59 this.validateMerchantExists(id); 65 this.validateMerchantExists(id);
60 - // TODO @aquan:需要校验 PayApp 是否都在。如果在的情况下,不允许删除 66 + this.validateAppExists(id);
61 // 删除 67 // 删除
62 merchantMapper.deleteById(id); 68 merchantMapper.deleteById(id);
63 } 69 }
64 70
65 - private void validateMerchantExists(Long id) {  
66 - if (merchantMapper.selectById(id) == null) {  
67 - throw exception(PAY_MERCHANT_NOT_EXISTS);  
68 - }  
69 - }  
70 -  
71 @Override 71 @Override
72 public PayMerchantDO getMerchant(Long id) { 72 public PayMerchantDO getMerchant(Long id) {
73 return merchantMapper.selectById(id); 73 return merchantMapper.selectById(id);
@@ -88,13 +88,6 @@ public class PayMerchantServiceImpl implements PayMerchantService { @@ -88,13 +88,6 @@ public class PayMerchantServiceImpl implements PayMerchantService {
88 return merchantMapper.selectList(exportReqVO); 88 return merchantMapper.selectList(exportReqVO);
89 } 89 }
90 90
91 - // TODO @aquan:接口上已经有注释,这里不用在有啦  
92 - /**  
93 - * 修改商户状态  
94 - *  
95 - * @param id 商户编号  
96 - * @param status 状态  
97 - */  
98 @Override 91 @Override
99 public void updateMerchantStatus(Long id, Integer status) { 92 public void updateMerchantStatus(Long id, Integer status) {
100 // 校验商户存在 93 // 校验商户存在
@@ -106,21 +99,11 @@ public class PayMerchantServiceImpl implements PayMerchantService { @@ -106,21 +99,11 @@ public class PayMerchantServiceImpl implements PayMerchantService {
106 merchantMapper.updateById(merchant); 99 merchantMapper.updateById(merchant);
107 } 100 }
108 101
109 - /**  
110 - * 根据商户名称模糊查询商户集合  
111 - *  
112 - * @param merchantName 商户名称  
113 - * @return 商户集合  
114 - */  
115 @Override 102 @Override
116 public List<PayMerchantDO> getMerchantListByName(String merchantName) { 103 public List<PayMerchantDO> getMerchantListByName(String merchantName) {
117 return this.merchantMapper.getMerchantListByName(merchantName); 104 return this.merchantMapper.getMerchantListByName(merchantName);
118 } 105 }
119 106
120 - /**  
121 - * 检查商户是否存在  
122 - * @param id 商户编号  
123 - */  
124 @VisibleForTesting 107 @VisibleForTesting
125 public void checkMerchantExists(Long id) { 108 public void checkMerchantExists(Long id) {
126 if (id == null) { 109 if (id == null) {
@@ -132,6 +115,27 @@ public class PayMerchantServiceImpl implements PayMerchantService { @@ -132,6 +115,27 @@ public class PayMerchantServiceImpl implements PayMerchantService {
132 } 115 }
133 } 116 }
134 117
  118 + /**
  119 + * 校验商户是否存在
  120 + *
  121 + * @param id 商户 ID
  122 + */
  123 + private void validateMerchantExists(Long id) {
  124 + if (ObjectUtil.isNull(merchantMapper.selectById(id))) {
  125 + throw exception(PAY_MERCHANT_NOT_EXISTS);
  126 + }
  127 + }
  128 +
  129 + /**
  130 + * 校验商户是否还存在支付应用
  131 + *
  132 + * @param id 商户ID
  133 + */
  134 + private void validateAppExists(Long id) {
  135 + if (appMapper.selectCount(id) > 0) {
  136 + throw exception(PAY_MERCHANT_EXIST_APP_CANT_DELETE);
  137 + }
  138 + }
135 139
136 // TODO @芋艿:后续增加下合适的算法 140 // TODO @芋艿:后续增加下合适的算法
137 /** 141 /**
@@ -139,8 +143,8 @@ public class PayMerchantServiceImpl implements PayMerchantService { @@ -139,8 +143,8 @@ public class PayMerchantServiceImpl implements PayMerchantService {
139 * 143 *
140 * @return 商户号 144 * @return 商户号
141 */ 145 */
142 - private String generateMerchantNo(){  
143 - return "M" + DateUtil.format(LocalDateTime.now(),"yyyyMMddHHmmssSSS"); 146 + private String generateMerchantNo() {
  147 + return "M" + DateUtil.format(LocalDateTime.now(), "yyyyMMddHHmmssSSS");
144 } 148 }
145 149
146 } 150 }
yudao-admin-server/src/main/resources/application.yaml
@@ -75,6 +75,4 @@ yudao: @@ -75,6 +75,4 @@ yudao:
75 - cn.iocoder.yudao.adminserver.modules.system.enums.SysErrorCodeConstants 75 - cn.iocoder.yudao.adminserver.modules.system.enums.SysErrorCodeConstants
76 tenant: # 多租户相关配置项 76 tenant: # 多租户相关配置项
77 tables: # 配置需要开启多租户的表;如果实体已经继承 TenantBaseDO 类,则无需重复配置 77 tables: # 配置需要开启多租户的表;如果实体已经继承 TenantBaseDO 类,则无需重复配置
78 - pay:  
79 - payReturnUrl: http://127.0.0.1 # TODO @aquan:这个变量,配置到 dev 或者 local 里,不同环境有差别哈  
80 debug: false 78 debug: false
yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/pay/service/refund/PayRefundServiceTest.java
@@ -72,8 +72,6 @@ public class PayRefundServiceTest extends BaseDbUnitTest { @@ -72,8 +72,6 @@ public class PayRefundServiceTest extends BaseDbUnitTest {
72 o.setUpdateTime(DateUtils.buildTime(2021, 1, 1, 10, 10, 35)); 72 o.setUpdateTime(DateUtils.buildTime(2021, 1, 1, 10, 10, 35));
73 }); 73 });
74 refundMapper.insert(dbRefund); 74 refundMapper.insert(dbRefund);
75 - // 测试 reqNo 不匹配  
76 - refundMapper.insert(cloneIgnoreId(dbRefund, o -> o.setReqNo("RF1111112")));  
77 // 测试 merchantId 不匹配 75 // 测试 merchantId 不匹配
78 refundMapper.insert(cloneIgnoreId(dbRefund, o -> o.setMerchantId(2L))); 76 refundMapper.insert(cloneIgnoreId(dbRefund, o -> o.setMerchantId(2L)));
79 // 测试 appId 不匹配 77 // 测试 appId 不匹配
@@ -94,7 +92,6 @@ public class PayRefundServiceTest extends BaseDbUnitTest { @@ -94,7 +92,6 @@ public class PayRefundServiceTest extends BaseDbUnitTest {
94 o.setCreateTime(DateUtils.buildTime(2022, 1, 1, 10, 10, 10)))); 92 o.setCreateTime(DateUtils.buildTime(2022, 1, 1, 10, 10, 10))));
95 // 准备参数 93 // 准备参数
96 PayRefundPageReqVO reqVO = new PayRefundPageReqVO(); 94 PayRefundPageReqVO reqVO = new PayRefundPageReqVO();
97 - reqVO.setReqNo("RF0000001");  
98 reqVO.setMerchantId(1L); 95 reqVO.setMerchantId(1L);
99 reqVO.setAppId(1L); 96 reqVO.setAppId(1L);
100 reqVO.setChannelCode(PayChannelEnum.WX_PUB.getCode()); 97 reqVO.setChannelCode(PayChannelEnum.WX_PUB.getCode());
@@ -147,8 +144,6 @@ public class PayRefundServiceTest extends BaseDbUnitTest { @@ -147,8 +144,6 @@ public class PayRefundServiceTest extends BaseDbUnitTest {
147 o.setUpdateTime(DateUtils.buildTime(2021, 1, 1, 10, 10, 35)); 144 o.setUpdateTime(DateUtils.buildTime(2021, 1, 1, 10, 10, 35));
148 }); 145 });
149 refundMapper.insert(dbRefund); 146 refundMapper.insert(dbRefund);
150 - // 测试 reqNo 不匹配  
151 - refundMapper.insert(cloneIgnoreId(dbRefund, o -> o.setReqNo("RF1111112")));  
152 // 测试 merchantId 不匹配 147 // 测试 merchantId 不匹配
153 refundMapper.insert(cloneIgnoreId(dbRefund, o -> o.setMerchantId(2L))); 148 refundMapper.insert(cloneIgnoreId(dbRefund, o -> o.setMerchantId(2L)));
154 // 测试 appId 不匹配 149 // 测试 appId 不匹配
@@ -170,7 +165,6 @@ public class PayRefundServiceTest extends BaseDbUnitTest { @@ -170,7 +165,6 @@ public class PayRefundServiceTest extends BaseDbUnitTest {
170 165
171 // 准备参数 166 // 准备参数
172 PayRefundExportReqVO reqVO = new PayRefundExportReqVO(); 167 PayRefundExportReqVO reqVO = new PayRefundExportReqVO();
173 - reqVO.setReqNo("RF0000001");  
174 reqVO.setMerchantId(1L); 168 reqVO.setMerchantId(1L);
175 reqVO.setAppId(1L); 169 reqVO.setAppId(1L);
176 reqVO.setChannelCode(PayChannelEnum.WX_PUB.getCode()); 170 reqVO.setChannelCode(PayChannelEnum.WX_PUB.getCode());
yudao-admin-ui/src/api/pay/merchant.js
@@ -49,7 +49,7 @@ export function getMerchant(id) { @@ -49,7 +49,7 @@ export function getMerchant(id) {
49 // 根据商户名称搜索商户列表 49 // 根据商户名称搜索商户列表
50 export function getMerchantListByName(name) { 50 export function getMerchantListByName(name) {
51 return request({ 51 return request({
52 - url: '/pay/merchant/list-name', 52 + url: '/pay/merchant/list-by-name',
53 params:{ 53 params:{
54 name:name 54 name:name
55 }, 55 },
yudao-admin-ui/src/utils/dict.js
@@ -34,12 +34,6 @@ export const DICT_TYPE = { @@ -34,12 +34,6 @@ export const DICT_TYPE = {
34 OA_LEAVE_STATUS: 'oa_leave_status', 34 OA_LEAVE_STATUS: 'oa_leave_status',
35 OA_LEAVE_TYPE: 'oa_leave_type', 35 OA_LEAVE_TYPE: 'oa_leave_type',
36 36
37 - // 商户状态  
38 - PAY_MERCHANT_STATUS: 'pay_merchant_status', // TODO @aquan:一般使用 COMMON_RESULT 即可。保持数值一致,以后加更多状态的时候,在单独数据字典  
39 - // 应用状态  
40 - PAY_APP_STATUS: 'pay_app_status',  
41 - // 渠道状态  
42 - PAY_CHANNEL_STATUS: 'pay_channel_status',  
43 // 微信渠道版本 37 // 微信渠道版本
44 PAY_CHANNEL_WECHAT_VERSION:'pay_channel_wechat_version', 38 PAY_CHANNEL_WECHAT_VERSION:'pay_channel_wechat_version',
45 // 支付渠道支付宝算法类型 39 // 支付渠道支付宝算法类型
yudao-admin-ui/src/views/pay/app/components/aliPayChannelForm.vue
1 <template> 1 <template>
2 <div> 2 <div>
3 - <el-dialog :visible.sync="transferParam.aliPayOpen" @closed="close" append-to-body width="800px"> 3 + <el-dialog :visible.sync="transferParam.aliPayOpen" :title="title" @closed="close" append-to-body width="800px">
4 <el-form ref="aliPayForm" :model="form" :rules="rules" size="medium" label-width="100px" 4 <el-form ref="aliPayForm" :model="form" :rules="rules" size="medium" label-width="100px"
5 v-loading="transferParam.loading"> 5 v-loading="transferParam.loading">
6 <el-form-item label-width="180px" label="渠道费率" prop="feeRate"> 6 <el-form-item label-width="180px" label="渠道费率" prop="feeRate">
@@ -172,6 +172,7 @@ export default { @@ -172,6 +172,7 @@ export default {
172 }, 172 },
173 data() { 173 data() {
174 return { 174 return {
  175 + title:'',
175 form: JSON.parse(JSON.stringify(defaultForm)), 176 form: JSON.parse(JSON.stringify(defaultForm)),
176 rules: { 177 rules: {
177 feeRate: [{ 178 feeRate: [{
@@ -232,7 +233,7 @@ export default { @@ -232,7 +233,7 @@ export default {
232 }, 233 },
233 fileAccept: ".crt", 234 fileAccept: ".crt",
234 // 渠道状态 数据字典 235 // 渠道状态 数据字典
235 - statusDictDatas: getDictDatas(DICT_TYPE.PAY_CHANNEL_STATUS), 236 + statusDictDatas: getDictDatas(DICT_TYPE.SYS_COMMON_STATUS),
236 // 支付宝加密方式 237 // 支付宝加密方式
237 aliPaySignTypeDatas: getDictDatas(DICT_TYPE.PAY_CHANNEL_ALIPAY_SIGN_TYPE), 238 aliPaySignTypeDatas: getDictDatas(DICT_TYPE.PAY_CHANNEL_ALIPAY_SIGN_TYPE),
238 // 版本状态 数据字典 239 // 版本状态 数据字典
@@ -251,7 +252,10 @@ export default { @@ -251,7 +252,10 @@ export default {
251 this.form.merchantId = newVal.payMerchant.id; 252 this.form.merchantId = newVal.payMerchant.id;
252 // 只有在初次进来为编辑 并且为加载中的时候才回去请求数据 253 // 只有在初次进来为编辑 并且为加载中的时候才回去请求数据
253 if (newVal.edit === true && newVal.loading) { 254 if (newVal.edit === true && newVal.loading) {
  255 + this.title = "编辑支付渠道";
254 this.init(); 256 this.init();
  257 + } else {
  258 + this.title = "创建支付渠道";
255 } 259 }
256 } 260 }
257 } 261 }
yudao-admin-ui/src/views/pay/app/components/wechatChannelForm.vue
1 <template> 1 <template>
2 <div> 2 <div>
3 - <el-dialog :visible.sync="transferParam.wechatOpen" @close="close" append-to-body width="800px"> 3 + <el-dialog :visible.sync="transferParam.wechatOpen" :title="title" @close="close" append-to-body width="800px">
4 <el-form ref="wechatJsApiForm" :model="form" :rules="rules" size="medium" label-width="100px" 4 <el-form ref="wechatJsApiForm" :model="form" :rules="rules" size="medium" label-width="100px"
5 v-loading="transferParam.loading"> 5 v-loading="transferParam.loading">
6 <el-form-item label-width="180px" label="渠道费率" prop="feeRate"> 6 <el-form-item label-width="180px" label="渠道费率" prop="feeRate">
@@ -134,6 +134,7 @@ export default { @@ -134,6 +134,7 @@ export default {
134 }, 134 },
135 data() { 135 data() {
136 return { 136 return {
  137 + title:'',
137 form: JSON.parse(JSON.stringify(defaultForm)), 138 form: JSON.parse(JSON.stringify(defaultForm)),
138 rules: { 139 rules: {
139 feeRate: [{ 140 feeRate: [{
@@ -188,7 +189,7 @@ export default { @@ -188,7 +189,7 @@ export default {
188 }, 189 },
189 fileAccept: ".pem", 190 fileAccept: ".pem",
190 // 渠道状态 数据字典 191 // 渠道状态 数据字典
191 - statusDictDatas: getDictDatas(DICT_TYPE.PAY_CHANNEL_STATUS), 192 + statusDictDatas: getDictDatas(DICT_TYPE.SYS_COMMON_STATUS),
192 versionDictDatas: getDictDatas(DICT_TYPE.PAY_CHANNEL_WECHAT_VERSION), 193 versionDictDatas: getDictDatas(DICT_TYPE.PAY_CHANNEL_WECHAT_VERSION),
193 } 194 }
194 }, 195 },
@@ -202,7 +203,10 @@ export default { @@ -202,7 +203,10 @@ export default {
202 this.form.merchantId = newVal.payMerchant.id; 203 this.form.merchantId = newVal.payMerchant.id;
203 // 只有在初次进来为编辑 并且为加载中的时候才回去请求数据 204 // 只有在初次进来为编辑 并且为加载中的时候才回去请求数据
204 if (newVal.edit && newVal.loading) { 205 if (newVal.edit && newVal.loading) {
  206 + this.title = "编辑支付渠道";
205 this.init(); 207 this.init();
  208 + } else {
  209 + this.title = "创建支付渠道";
206 } 210 }
207 } 211 }
208 } 212 }
yudao-admin-ui/src/views/pay/app/index.vue
@@ -57,59 +57,49 @@ @@ -57,59 +57,49 @@
57 <el-table-column label="支付宝配置" align="center"> 57 <el-table-column label="支付宝配置" align="center">
58 <el-table-column :label="payChannelEnum.ALIPAY_APP.name" align="center"> 58 <el-table-column :label="payChannelEnum.ALIPAY_APP.name" align="center">
59 <template slot-scope="scope"> 59 <template slot-scope="scope">
60 - <el-button  
61 - type="success" icon="el-icon-check" circle  
62 - @click="handleUpdateChannel(scope.row,payChannelEnum.ALIPAY_APP.code,payType.ALIPAY)"  
63 - v-if="scope.row.payChannel.alipayApp === sysCommonStatusEnum.ENABLE"> 60 + <el-button type="success" icon="el-icon-check" circle
  61 + v-if="judgeChannelExist(scope.row.channelCodes,payChannelEnum.ALIPAY_APP.code)"
  62 + @click="handleUpdateChannel(scope.row,payChannelEnum.ALIPAY_APP.code,payType.ALIPAY)">
64 </el-button> 63 </el-button>
65 - <el-button  
66 - type="danger" icon="el-icon-close" circle  
67 - @click="handleCreateChannel(scope.row,payChannelEnum.ALIPAY_APP.code,payType.ALIPAY)"  
68 - v-if="scope.row.payChannel.alipayApp === sysCommonStatusEnum.DISABLE"> 64 + <el-button v-else
  65 + type="danger" icon="el-icon-close" circle
  66 + @click="handleCreateChannel(scope.row,payChannelEnum.ALIPAY_APP.code,payType.ALIPAY)">
69 </el-button> 67 </el-button>
70 </template> 68 </template>
71 </el-table-column> 69 </el-table-column>
72 <el-table-column :label="payChannelEnum.ALIPAY_PC.name" align="center"> 70 <el-table-column :label="payChannelEnum.ALIPAY_PC.name" align="center">
73 <template slot-scope="scope"> 71 <template slot-scope="scope">
74 - <el-button  
75 - type="success" icon="el-icon-check" circle  
76 - @click="handleUpdateChannel(scope.row,payChannelEnum.ALIPAY_PC.code,payType.ALIPAY)"  
77 - v-if="scope.row.payChannel.alipayPc === sysCommonStatusEnum.ENABLE"> 72 + <el-button type="success" icon="el-icon-check" circle
  73 + v-if="judgeChannelExist(scope.row.channelCodes,payChannelEnum.ALIPAY_PC.code)"
  74 + @click="handleUpdateChannel(scope.row,payChannelEnum.ALIPAY_APP.code,payType.ALIPAY)">
78 </el-button> 75 </el-button>
79 - <el-button  
80 - type="danger" icon="el-icon-close" circle  
81 - @click="handleCreateChannel(scope.row,payChannelEnum.ALIPAY_PC.code,payType.ALIPAY)"  
82 - v-if="scope.row.payChannel.alipayPc === sysCommonStatusEnum.DISABLE"> 76 + <el-button v-else
  77 + type="danger" icon="el-icon-close" circle
  78 + @click="handleCreateChannel(scope.row,payChannelEnum.ALIPAY_PC.code,payType.ALIPAY)">
83 </el-button> 79 </el-button>
84 </template> 80 </template>
85 </el-table-column> 81 </el-table-column>
86 <el-table-column :label="payChannelEnum.ALIPAY_WAP.name" align="center"> 82 <el-table-column :label="payChannelEnum.ALIPAY_WAP.name" align="center">
87 <template slot-scope="scope"> 83 <template slot-scope="scope">
88 - <el-button  
89 - type="success" icon="el-icon-check" circle  
90 - @click="handleUpdateChannel(scope.row,payChannelEnum.ALIPAY_WAP.code,payType.ALIPAY)"  
91 - v-if="scope.row.payChannel.alipayWap === sysCommonStatusEnum.ENABLE"> 84 + <el-button type="success" icon="el-icon-check" circle
  85 + v-if="judgeChannelExist(scope.row.channelCodes,payChannelEnum.ALIPAY_WAP.code)"
  86 + @click="handleUpdateChannel(scope.row,payChannelEnum.ALIPAY_APP.code,payType.ALIPAY)">
92 </el-button> 87 </el-button>
93 - <el-button  
94 - type="danger" icon="el-icon-close" circle  
95 - @click="handleCreateChannel(scope.row,payChannelEnum.ALIPAY_WAP.code,payType.ALIPAY)"  
96 - v-if="scope.row.payChannel.alipayWap === sysCommonStatusEnum.DISABLE"> 88 + <el-button v-else
  89 + type="danger" icon="el-icon-close" circle
  90 + @click="handleCreateChannel(scope.row,payChannelEnum.ALIPAY_WAP.code,payType.ALIPAY)">
97 </el-button> 91 </el-button>
98 </template> 92 </template>
99 </el-table-column> 93 </el-table-column>
100 <el-table-column :label="payChannelEnum.ALIPAY_QR.name" align="center"> 94 <el-table-column :label="payChannelEnum.ALIPAY_QR.name" align="center">
101 <template slot-scope="scope"> 95 <template slot-scope="scope">
102 - <el-button  
103 - type="success" icon="el-icon-check" circle  
104 - @click="handleUpdateChannel(scope.row,payChannelEnum.ALIPAY_QR.code,payType.ALIPAY)"  
105 - v-if="scope.row.payChannel.alipayQr === sysCommonStatusEnum.ENABLE">  
106 - 96 + <el-button type="success" icon="el-icon-check" circle
  97 + v-if="judgeChannelExist(scope.row.channelCodes,payChannelEnum.ALIPAY_QR.code)"
  98 + @click="handleUpdateChannel(scope.row,payChannelEnum.ALIPAY_APP.code,payType.ALIPAY)">
107 </el-button> 99 </el-button>
108 - <el-button  
109 - type="danger" icon="el-icon-close" circle  
110 - @click="handleCreateChannel(scope.row,payChannelEnum.ALIPAY_QR.code,payType.ALIPAY)"  
111 - v-if="scope.row.payChannel.alipayQr === sysCommonStatusEnum.DISABLE">  
112 - 100 + <el-button v-else
  101 + type="danger" icon="el-icon-close" circle
  102 + @click="handleCreateChannel(scope.row,payChannelEnum.ALIPAY_QR.code,payType.ALIPAY)">
113 </el-button> 103 </el-button>
114 </template> 104 </template>
115 </el-table-column> 105 </el-table-column>
@@ -117,43 +107,37 @@ @@ -117,43 +107,37 @@
117 <el-table-column label="微信配置" align="center"> 107 <el-table-column label="微信配置" align="center">
118 <el-table-column :label="payChannelEnum.WX_LITE.name" align="center"> 108 <el-table-column :label="payChannelEnum.WX_LITE.name" align="center">
119 <template slot-scope="scope"> 109 <template slot-scope="scope">
120 - <el-button  
121 - type="success" icon="el-icon-check" circle  
122 - @click="handleUpdateChannel(scope.row,payChannelEnum.WX_LITE.code,payType.WECHAT)"  
123 - v-if="scope.row.payChannel.wxLite === sysCommonStatusEnum.ENABLE"> 110 + <el-button type="success" icon="el-icon-check" circle
  111 + v-if="judgeChannelExist(scope.row.channelCodes,payChannelEnum.WX_LITE.code)"
  112 + @click="handleUpdateChannel(scope.row,payChannelEnum.ALIPAY_APP.code,payType.WECHAT)">
124 </el-button> 113 </el-button>
125 - <el-button  
126 - type="danger" icon="el-icon-close" circle  
127 - @click="handleCreateChannel(scope.row,payChannelEnum.WX_LITE.code,payType.WECHAT)"  
128 - v-if="scope.row.payChannel.wxLite === sysCommonStatusEnum.DISABLE"> 114 + <el-button v-else
  115 + type="danger" icon="el-icon-close" circle
  116 + @click="handleCreateChannel(scope.row,payChannelEnum.WX_LITE.code,payType.WECHAT)">
129 </el-button> 117 </el-button>
130 </template> 118 </template>
131 </el-table-column> 119 </el-table-column>
132 <el-table-column :label="payChannelEnum.WX_PUB.name" align="center"> 120 <el-table-column :label="payChannelEnum.WX_PUB.name" align="center">
133 <template slot-scope="scope"> 121 <template slot-scope="scope">
134 - <el-button  
135 - type="success" icon="el-icon-check" circle  
136 - @click="handleUpdateChannel(scope.row,payChannelEnum.WX_PUB.code,payType.WECHAT)"  
137 - v-if="scope.row.payChannel.wxPub === sysCommonStatusEnum.ENABLE"> 122 + <el-button type="success" icon="el-icon-check" circle
  123 + v-if="judgeChannelExist(scope.row.channelCodes,payChannelEnum.WX_PUB.code)"
  124 + @click="handleUpdateChannel(scope.row,payChannelEnum.ALIPAY_APP.code,payType.WECHAT)">
138 </el-button> 125 </el-button>
139 - <el-button  
140 - type="danger" icon="el-icon-close" circle  
141 - @click="handleCreateChannel(scope.row,payChannelEnum.WX_PUB.code,payType.WECHAT)"  
142 - v-if="scope.row.payChannel.wxPub === sysCommonStatusEnum.DISABLE"> 126 + <el-button v-else
  127 + type="danger" icon="el-icon-close" circle
  128 + @click="handleCreateChannel(scope.row,payChannelEnum.WX_PUB.code,payType.WECHAT)">
143 </el-button> 129 </el-button>
144 </template> 130 </template>
145 </el-table-column> 131 </el-table-column>
146 <el-table-column :label="payChannelEnum.WX_APP.name" align="center"> 132 <el-table-column :label="payChannelEnum.WX_APP.name" align="center">
147 <template slot-scope="scope"> 133 <template slot-scope="scope">
148 - <el-button  
149 - type="success" icon="el-icon-check" circle  
150 - @click="handleUpdateChannel(scope.row,payChannelEnum.WX_APP.code,payType.WECHAT)"  
151 - v-if="scope.row.payChannel.wxApp === sysCommonStatusEnum.ENABLE"> 134 + <el-button type="success" icon="el-icon-check" circle
  135 + v-if="judgeChannelExist(scope.row.channelCodes,payChannelEnum.WX_APP.code)"
  136 + @click="handleUpdateChannel(scope.row,payChannelEnum.ALIPAY_APP.code,payType.WECHAT)">
152 </el-button> 137 </el-button>
153 - <el-button  
154 - type="danger" icon="el-icon-close" circle  
155 - @click="handleCreateChannel(scope.row,payChannelEnum.WX_APP.code,payType.WECHAT)"  
156 - v-if="scope.row.payChannel.wxApp === sysCommonStatusEnum.DISABLE"> 138 + <el-button v-else
  139 + type="danger" icon="el-icon-close" circle
  140 + @click="handleCreateChannel(scope.row,payChannelEnum.WX_APP.code,payType.WECHAT)">
157 </el-button> 141 </el-button>
158 </template> 142 </template>
159 </el-table-column> 143 </el-table-column>
@@ -276,7 +260,7 @@ export default { @@ -276,7 +260,7 @@ export default {
276 merchantId: [{required: true, message: "商户编号不能为空", trigger: "blur"}], 260 merchantId: [{required: true, message: "商户编号不能为空", trigger: "blur"}],
277 }, 261 },
278 // 数据字典 262 // 数据字典
279 - statusDictDatas: getDictDatas(DICT_TYPE.PAY_APP_STATUS), 263 + statusDictDatas: getDictDatas(DICT_TYPE.SYS_COMMON_STATUS),
280 sysCommonStatusEnum: SysCommonStatusEnum, 264 sysCommonStatusEnum: SysCommonStatusEnum,
281 // 支付渠道枚举 265 // 支付渠道枚举
282 payChannelEnum: PayChannelEnum, 266 payChannelEnum: PayChannelEnum,
@@ -322,6 +306,7 @@ export default { @@ -322,6 +306,7 @@ export default {
322 // 执行查询 306 // 执行查询
323 getAppPage(params).then(response => { 307 getAppPage(params).then(response => {
324 this.list = response.data.list; 308 this.list = response.data.list;
  309 + console.log(this.list);
325 this.total = response.data.total; 310 this.total = response.data.total;
326 this.loading = false; 311 this.loading = false;
327 }); 312 });
@@ -422,7 +407,12 @@ export default { @@ -422,7 +407,12 @@ export default {
422 }).then(() => { 407 }).then(() => {
423 this.getList(); 408 this.getList();
424 this.msgSuccess("删除成功"); 409 this.msgSuccess("删除成功");
425 - }) 410 + }).catch(() => {
  411 + this.$message({
  412 + type: 'info',
  413 + message: '已取消删除'
  414 + });
  415 + });
426 }, 416 },
427 /** 导出按钮操作 */ 417 /** 导出按钮操作 */
428 handleExport() { 418 handleExport() {
@@ -486,6 +476,14 @@ export default { @@ -486,6 +476,14 @@ export default {
486 this.channelParam.payCode = payCode; 476 this.channelParam.payCode = payCode;
487 this.channelParam.payMerchant = row.payMerchant; 477 this.channelParam.payMerchant = row.payMerchant;
488 }, 478 },
  479 + /**
  480 + * 根据渠道编码判断渠道列表中是否存在
  481 + * @param channels 渠道列表
  482 + * @param channelCode 渠道编码
  483 + */
  484 + judgeChannelExist(channels, channelCode) {
  485 + return channels.indexOf(channelCode) !== -1;
  486 + },
489 refreshTable() { 487 refreshTable() {
490 this.getList(); 488 this.getList();
491 } 489 }
yudao-admin-ui/src/views/pay/merchant/index.vue
@@ -154,8 +154,8 @@ export default { @@ -154,8 +154,8 @@ export default {
154 shortName: [{ required: true, message: "商户简称不能为空", trigger: "blur" }], 154 shortName: [{ required: true, message: "商户简称不能为空", trigger: "blur" }],
155 status: [{ required: true, message: "开启状态不能为空", trigger: "blur" }], 155 status: [{ required: true, message: "开启状态不能为空", trigger: "blur" }],
156 }, 156 },
157 - // 数据字典  
158 - statusDictDatas: getDictDatas(DICT_TYPE.PAY_MERCHANT_STATUS) 157 + // 商户状态数据字典
  158 + statusDictDatas: getDictDatas(DICT_TYPE.SYS_COMMON_STATUS)
159 }; 159 };
160 }, 160 },
161 created() { 161 created() {
yudao-admin-ui/src/views/pay/order/index.vue
@@ -236,9 +236,6 @@ @@ -236,9 +236,6 @@
236 <el-descriptions-item label="商品描述"> 236 <el-descriptions-item label="商品描述">
237 {{ orderDetail.body }} 237 {{ orderDetail.body }}
238 </el-descriptions-item> 238 </el-descriptions-item>
239 - <el-descriptions-item label="支付通道额外扩展参数">  
240 - {{ orderDetail.payOrderExtension.channelExtras }}  
241 - </el-descriptions-item>  
242 <el-descriptions-item label="支付通道异步回调内容"> 239 <el-descriptions-item label="支付通道异步回调内容">
243 {{ orderDetail.payOrderExtension.channelNotifyData }} 240 {{ orderDetail.payOrderExtension.channelNotifyData }}
244 </el-descriptions-item> 241 </el-descriptions-item>
@@ -278,7 +275,6 @@ const defaultOrderDetail = { @@ -278,7 +275,6 @@ const defaultOrderDetail = {
278 notifyTime: '', 275 notifyTime: '',
279 expireTime: '', 276 expireTime: '',
280 payOrderExtension: { 277 payOrderExtension: {
281 - channelExtras: '',  
282 channelNotifyData: '', 278 channelNotifyData: '',
283 no: '' 279 no: ''
284 } 280 }
yudao-admin-ui/src/views/pay/refund/index.vue
@@ -43,20 +43,17 @@ @@ -43,20 +43,17 @@
43 <el-option v-for="dict in payChannelCodeDictDatum" :key="dict.value" :label="dict.label" :value="dict.value"/> 43 <el-option v-for="dict in payChannelCodeDictDatum" :key="dict.value" :label="dict.label" :value="dict.value"/>
44 </el-select> 44 </el-select>
45 </el-form-item> 45 </el-form-item>
46 - <el-form-item label="退款单号" prop="reqNo">  
47 - <el-input v-model="queryParams.reqNo" placeholder="请输入退款单请求号" clearable size="small"  
48 - @keyup.enter.native="handleQuery"/>  
49 - </el-form-item>  
50 - <el-form-item label="商户退款订单号" prop="merchantRefundNo">  
51 - <el-input v-model="queryParams.merchantRefundNo" placeholder="请输入商户退款订单号" clearable size="small"  
52 - @keyup.enter.native="handleQuery"/>  
53 - </el-form-item>  
54 <el-form-item label="退款类型" prop="type"> 46 <el-form-item label="退款类型" prop="type">
55 <el-select v-model="queryParams.type" placeholder="请选择退款类型" clearable size="small"> 47 <el-select v-model="queryParams.type" placeholder="请选择退款类型" clearable size="small">
56 <el-option v-for="dict in payRefundOrderTypeDictDatum" :key="parseInt(dict.value)" 48 <el-option v-for="dict in payRefundOrderTypeDictDatum" :key="parseInt(dict.value)"
57 :label="dict.label" :value="parseInt(dict.value)"/> 49 :label="dict.label" :value="parseInt(dict.value)"/>
58 </el-select> 50 </el-select>
59 </el-form-item> 51 </el-form-item>
  52 + <el-form-item label="商户退款订单号" prop="merchantRefundNo">
  53 + <el-input v-model="queryParams.merchantRefundNo" placeholder="请输入商户退款订单号" clearable size="small"
  54 + @keyup.enter.native="handleQuery"/>
  55 + </el-form-item>
  56 +
60 <el-form-item label="退款状态" prop="status"> 57 <el-form-item label="退款状态" prop="status">
61 <el-select v-model="queryParams.status" placeholder="请选择退款状态" clearable size="small"> 58 <el-select v-model="queryParams.status" placeholder="请选择退款状态" clearable size="small">
62 <el-option v-for="dict in payRefundOrderDictDatum" :key="parseInt(dict.value)" 59 <el-option v-for="dict in payRefundOrderDictDatum" :key="parseInt(dict.value)"
@@ -112,15 +109,15 @@ @@ -112,15 +109,15 @@
112 </el-table-column> 109 </el-table-column>
113 <!-- <el-table-column label="交易订单号" align="center" prop="tradeNo" width="140"/>--> 110 <!-- <el-table-column label="交易订单号" align="center" prop="tradeNo" width="140"/>-->
114 <!-- <el-table-column label="商户订单编号" align="center" prop="merchantOrderId" width="140"/>--> 111 <!-- <el-table-column label="商户订单编号" align="center" prop="merchantOrderId" width="140"/>-->
115 - <el-table-column label="退款订单号" align="left" width="230"> 112 + <el-table-column label="商户订单号" align="left" width="230">
116 <template v-slot="scope"> 113 <template v-slot="scope">
117 <p class="order-font"> 114 <p class="order-font">
118 <el-tag size="mini">退款</el-tag> 115 <el-tag size="mini">退款</el-tag>
119 - {{ scope.row.reqNo }} 116 + {{ scope.row.merchantRefundNo }}
120 </p> 117 </p>
121 <p class="order-font"> 118 <p class="order-font">
122 - <el-tag size="mini" type="success">商户</el-tag>  
123 - {{ scope.row.merchantRefundNo }} 119 + <el-tag type="success">交易</el-tag>
  120 + {{ scope.row.merchantOrderId }}
124 </p> 121 </p>
125 </template> 122 </template>
126 </el-table-column> 123 </el-table-column>
@@ -202,9 +199,6 @@ @@ -202,9 +199,6 @@
202 <el-descriptions-item label="商户退款单号"> 199 <el-descriptions-item label="商户退款单号">
203 <el-tag size="mini">{{ refundDetail.merchantRefundNo }}</el-tag> 200 <el-tag size="mini">{{ refundDetail.merchantRefundNo }}</el-tag>
204 </el-descriptions-item> 201 </el-descriptions-item>
205 - <el-descriptions-item label="商户退款请求单号" size="mini">  
206 - <el-tag type="success" size="mini">{{ refundDetail.reqNo }}</el-tag>  
207 - </el-descriptions-item>  
208 <el-descriptions-item label="商户订单号">{{ refundDetail.merchantOrderId }}</el-descriptions-item> 202 <el-descriptions-item label="商户订单号">{{ refundDetail.merchantOrderId }}</el-descriptions-item>
209 <el-descriptions-item label="交易订单号">{{ refundDetail.tradeNo }}</el-descriptions-item> 203 <el-descriptions-item label="交易订单号">{{ refundDetail.tradeNo }}</el-descriptions-item>
210 </el-descriptions> 204 </el-descriptions>
@@ -299,7 +293,6 @@ const defaultRefundDetail = { @@ -299,7 +293,6 @@ const defaultRefundDetail = {
299 payAmount: null, 293 payAmount: null,
300 reason: '', 294 reason: '',
301 refundAmount: null, 295 refundAmount: null,
302 - reqNo: '',  
303 status: null, 296 status: null,
304 subject: '', 297 subject: '',
305 successTime: null, 298 successTime: null,
@@ -333,7 +326,6 @@ export default { @@ -333,7 +326,6 @@ export default {
333 queryParams: { 326 queryParams: {
334 pageNo: 1, 327 pageNo: 1,
335 pageSize: 10, 328 pageSize: 10,
336 - reqNo: null,  
337 merchantId: null, 329 merchantId: null,
338 appId: null, 330 appId: null,
339 channelId: null, 331 channelId: null,
yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/enums/PayErrorCodeCoreConstants.java
@@ -14,6 +14,7 @@ public interface PayErrorCodeCoreConstants { @@ -14,6 +14,7 @@ public interface PayErrorCodeCoreConstants {
14 */ 14 */
15 ErrorCode PAY_APP_NOT_FOUND = new ErrorCode(1007000000, "App 不存在"); 15 ErrorCode PAY_APP_NOT_FOUND = new ErrorCode(1007000000, "App 不存在");
16 ErrorCode PAY_APP_IS_DISABLE = new ErrorCode(1007000002, "App 已经被禁用"); 16 ErrorCode PAY_APP_IS_DISABLE = new ErrorCode(1007000002, "App 已经被禁用");
  17 + ErrorCode PAY_APP_EXIST_TRANSACTION_ORDER_CANT_DELETE = new ErrorCode(1007000003, "支付应用存在交易中的订单,无法删除");
17 18
18 /** 19 /**
19 * ========== CHANNEL 模块 1-007-001-000 ========== 20 * ========== CHANNEL 模块 1-007-001-000 ==========
@@ -54,6 +55,7 @@ public interface PayErrorCodeCoreConstants { @@ -54,6 +55,7 @@ public interface PayErrorCodeCoreConstants {
54 * ========== 支付商户信息 1-007-004-000 ========== 55 * ========== 支付商户信息 1-007-004-000 ==========
55 */ 56 */
56 ErrorCode PAY_MERCHANT_NOT_EXISTS = new ErrorCode(1007004000, "支付商户信息不存在"); 57 ErrorCode PAY_MERCHANT_NOT_EXISTS = new ErrorCode(1007004000, "支付商户信息不存在");
  58 + ErrorCode PAY_MERCHANT_EXIST_APP_CANT_DELETE = new ErrorCode(1007004001, "支付商户存在支付应用,无法删除");
57 59
58 60
59 61
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/PayClientConfig.java
1 package cn.iocoder.yudao.framework.pay.core.client; 1 package cn.iocoder.yudao.framework.pay.core.client;
2 2
3 -import cn.hutool.json.JSONUtil;  
4 -import cn.iocoder.yudao.framework.pay.core.enums.PayChannelEnum;  
5 import com.fasterxml.jackson.annotation.JsonTypeInfo; 3 import com.fasterxml.jackson.annotation.JsonTypeInfo;
6 4
  5 +import javax.validation.ConstraintViolation;
  6 +import javax.validation.ConstraintViolationException;
7 import javax.validation.Validator; 7 import javax.validation.Validator;
  8 +import java.util.Set;
8 9
9 /** 10 /**
10 * 支付客户端的配置,本质是支付渠道的配置 11 * 支付客户端的配置,本质是支付渠道的配置
@@ -19,8 +20,22 @@ import javax.validation.Validator; @@ -19,8 +20,22 @@ import javax.validation.Validator;
19 public interface PayClientConfig { 20 public interface PayClientConfig {
20 21
21 /** 22 /**
22 - * 验证配置参数是否正确 23 + * 配置验证参数是
  24 + *
23 * @param validator 校验对象 25 * @param validator 校验对象
  26 + * @return 配置好的验证参数
24 */ 27 */
25 - void verifyParam(Validator validator); 28 + Set<ConstraintViolation<PayClientConfig>> verifyParam(Validator validator);
  29 +
  30 + /**
  31 + * 参数校验
  32 + *
  33 + * @param validator 校验对象
  34 + */
  35 + default void validate(Validator validator) {
  36 + Set<ConstraintViolation<PayClientConfig>> violations = verifyParam(validator);
  37 + if (!violations.isEmpty()) {
  38 + throw new ConstraintViolationException(violations);
  39 + }
  40 + }
26 } 41 }
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/alipay/AlipayPayClientConfig.java
@@ -2,17 +2,12 @@ package cn.iocoder.yudao.framework.pay.core.client.impl.alipay; @@ -2,17 +2,12 @@ package cn.iocoder.yudao.framework.pay.core.client.impl.alipay;
2 2
3 import cn.iocoder.yudao.framework.pay.core.client.PayClientConfig; 3 import cn.iocoder.yudao.framework.pay.core.client.PayClientConfig;
4 import lombok.Data; 4 import lombok.Data;
5 -import org.springframework.beans.factory.annotation.Autowired;  
6 -import org.springframework.util.Assert;  
7 5
8 -import javax.annotation.Resource;  
9 import javax.validation.ConstraintViolation; 6 import javax.validation.ConstraintViolation;
10 import javax.validation.Validator; 7 import javax.validation.Validator;
11 -import javax.validation.constraints.AssertTrue;  
12 import javax.validation.constraints.NotBlank; 8 import javax.validation.constraints.NotBlank;
13 import javax.validation.constraints.NotNull; 9 import javax.validation.constraints.NotNull;
14 import java.util.Set; 10 import java.util.Set;
15 -import java.util.stream.Collectors;  
16 11
17 // TODO 芋艿:参数校验 12 // TODO 芋艿:参数校验
18 13
@@ -114,18 +109,9 @@ public class AlipayPayClientConfig implements PayClientConfig { @@ -114,18 +109,9 @@ public class AlipayPayClientConfig implements PayClientConfig {
114 public interface ModeCertificate { 109 public interface ModeCertificate {
115 } 110 }
116 111
117 - /**  
118 - * 验证配置参数是否正确  
119 - * @param validator 校验对象  
120 - */  
121 @Override 112 @Override
122 - public void verifyParam(Validator validator) {  
123 - // 手动调用validate进行验证  
124 - Set<ConstraintViolation<AlipayPayClientConfig>> validate = validator.validate(this, 113 + public Set<ConstraintViolation<PayClientConfig>> verifyParam(Validator validator) {
  114 + return validator.validate(this,
125 MODE_PUBLIC_KEY.equals(this.getMode()) ? ModePublicKey.class : ModeCertificate.class); 115 MODE_PUBLIC_KEY.equals(this.getMode()) ? ModePublicKey.class : ModeCertificate.class);
126 -  
127 - // 断言没有异常  
128 - Assert.isTrue(validate.isEmpty(), validate.stream().map(ConstraintViolation::getMessage)  
129 - .collect(Collectors.joining(",")));  
130 } 116 }
131 } 117 }
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/wx/WXPayClientConfig.java
@@ -3,7 +3,6 @@ package cn.iocoder.yudao.framework.pay.core.client.impl.wx; @@ -3,7 +3,6 @@ package cn.iocoder.yudao.framework.pay.core.client.impl.wx;
3 import cn.hutool.core.io.IoUtil; 3 import cn.hutool.core.io.IoUtil;
4 import cn.iocoder.yudao.framework.pay.core.client.PayClientConfig; 4 import cn.iocoder.yudao.framework.pay.core.client.PayClientConfig;
5 import lombok.Data; 5 import lombok.Data;
6 -import org.springframework.util.Assert;  
7 6
8 import javax.validation.ConstraintViolation; 7 import javax.validation.ConstraintViolation;
9 import javax.validation.Validator; 8 import javax.validation.Validator;
@@ -11,7 +10,6 @@ import javax.validation.constraints.NotBlank; @@ -11,7 +10,6 @@ import javax.validation.constraints.NotBlank;
11 import java.io.FileInputStream; 10 import java.io.FileInputStream;
12 import java.io.FileNotFoundException; 11 import java.io.FileNotFoundException;
13 import java.util.Set; 12 import java.util.Set;
14 -import java.util.stream.Collectors;  
15 13
16 // TODO 芋艿:参数校验 14 // TODO 芋艿:参数校验
17 15
@@ -101,19 +99,9 @@ public class WXPayClientConfig implements PayClientConfig { @@ -101,19 +99,9 @@ public class WXPayClientConfig implements PayClientConfig {
101 public interface V3 { 99 public interface V3 {
102 } 100 }
103 101
104 - // TODO @aquan:1)已经有注释,不用重复注释;2)方法名改成 validate,比较适合 validator;3)断言是否有异常,可以封一个 ConstraintViolationException 异常  
105 - /**  
106 - * 验证配置参数是否正确  
107 - * @param validator 校验对象  
108 - */  
109 @Override 102 @Override
110 - public void verifyParam(Validator validator) {  
111 - // 手动调用validate进行验证  
112 - Set<ConstraintViolation<PayClientConfig>> validate = validator.validate(this,  
113 - this.getApiVersion().equals(API_VERSION_V2) ? V2.class : V3.class);  
114 - // 断言没有异常  
115 - Assert.isTrue(validate.isEmpty(), validate.stream().map(ConstraintViolation::getMessage)  
116 - .collect(Collectors.joining(","))); 103 + public Set<ConstraintViolation<PayClientConfig>> verifyParam(Validator validator) {
  104 + return validator.validate(this, this.getApiVersion().equals(API_VERSION_V2) ? V2.class : V3.class);
117 } 105 }
118 106
119 public static void main(String[] args) throws FileNotFoundException { 107 public static void main(String[] args) throws FileNotFoundException {
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/enums/PayChannelEnum.java
@@ -17,18 +17,21 @@ import lombok.Getter; @@ -17,18 +17,21 @@ import lombok.Getter;
17 @AllArgsConstructor 17 @AllArgsConstructor
18 public enum PayChannelEnum { 18 public enum PayChannelEnum {
19 19
20 - WX_PUB("wx_pub", "微信 JSAPI 支付"), // 公众号的网页  
21 - WX_LITE("wx_lite","微信小程序支付"),  
22 - WX_APP("wx_app", "微信 App 支付"), 20 + /**
  21 + * 公众号网页
  22 + */
  23 + WX_PUB("wx_pub", "微信 JSAPI 支付", WXPayClientConfig.class),
  24 + WX_LITE("wx_lite", "微信小程序支付", WXPayClientConfig.class),
  25 + WX_APP("wx_app", "微信 App 支付", WXPayClientConfig.class),
23 26
24 - ALIPAY_PC("alipay_pc", "支付宝 PC 网站支付"),  
25 - ALIPAY_WAP("alipay_wap", "支付宝 Wap 网站支付"),  
26 - ALIPAY_APP("alipay_app", "支付宝App 支付"),  
27 - ALIPAY_QR("alipay_qr", "支付宝扫码支付"); 27 + ALIPAY_PC("alipay_pc", "支付宝 PC 网站支付", AlipayPayClientConfig.class),
  28 + ALIPAY_WAP("alipay_wap", "支付宝 Wap 网站支付", AlipayPayClientConfig.class),
  29 + ALIPAY_APP("alipay_app", "支付宝App 支付", AlipayPayClientConfig.class),
  30 + ALIPAY_QR("alipay_qr", "支付宝扫码支付", AlipayPayClientConfig.class);
28 31
29 /** 32 /**
30 * 编码 33 * 编码
31 - * 34 + * <p>
32 * 参考 https://www.pingxx.com/api/支付渠道属性值.html 35 * 参考 https://www.pingxx.com/api/支付渠道属性值.html
33 */ 36 */
34 private String code; 37 private String code;
@@ -38,6 +41,11 @@ public enum PayChannelEnum { @@ -38,6 +41,11 @@ public enum PayChannelEnum {
38 private String name; 41 private String name;
39 42
40 /** 43 /**
  44 + * 配置类
  45 + */
  46 + private Class<? extends PayClientConfig> configClass;
  47 +
  48 + /**
41 * 微信支付 49 * 微信支付
42 */ 50 */
43 public static final String WECHAT = "WECHAT"; 51 public static final String WECHAT = "WECHAT";
@@ -50,27 +58,6 @@ public enum PayChannelEnum { @@ -50,27 +58,6 @@ public enum PayChannelEnum {
50 public static PayChannelEnum getByCode(String code) { 58 public static PayChannelEnum getByCode(String code) {
51 return ArrayUtil.firstMatch(o -> o.getCode().equals(code), values()); 59 return ArrayUtil.firstMatch(o -> o.getCode().equals(code), values());
52 } 60 }
53 -  
54 - // TODO @aquan:加一个 configClass 字段,不用 switch 的方式哈。不然新增一个支付方式,需要改的方法有点多  
55 - /**  
56 - * 根据编码得到支付类  
57 - *  
58 - * @param code 编码  
59 - * @return 支付配置类  
60 - */  
61 - public static Class<? extends PayClientConfig> findByCodeGetClass(String code) {  
62 - switch (PayChannelEnum.getByCode(code)){  
63 - case WX_PUB:  
64 - case WX_LITE:  
65 - case WX_APP:  
66 - return WXPayClientConfig.class;  
67 - case ALIPAY_PC:  
68 - case ALIPAY_WAP:  
69 - case ALIPAY_APP:  
70 - case ALIPAY_QR:  
71 - return AlipayPayClientConfig.class;  
72 - }  
73 - return null;  
74 - } 61 +
75 62
76 } 63 }