Commit 1c5544fc9d69d3949cb025307cc5687105d05cfd

Authored by aquan
1 parent dfde260e

优化渠道 config 校验和逻辑转换问题

Showing 15 changed files with 136 additions and 149 deletions
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/controller/merchant/PayMerchantController.java
@@ -80,7 +80,7 @@ public class PayMerchantController { @@ -80,7 +80,7 @@ public class PayMerchantController {
80 @ApiImplicitParam(name = "name", value = "商户名称", required = true, example = "芋道", dataTypeClass = Long.class) 80 @ApiImplicitParam(name = "name", value = "商户名称", required = true, example = "芋道", dataTypeClass = Long.class)
81 @PreAuthorize("@ss.hasPermission('pay:merchant:query')") 81 @PreAuthorize("@ss.hasPermission('pay:merchant:query')")
82 public CommonResult<List<PayMerchantRespVO>> getMerchantListByName(@RequestParam("name") String name) { 82 public CommonResult<List<PayMerchantRespVO>> getMerchantListByName(@RequestParam("name") String name) {
83 - List<PayMerchantDO> merchantListDO = merchantService.getMerchantListByNameLimit(name); 83 + List<PayMerchantDO> merchantListDO = merchantService.getMerchantListByName(name);
84 return success(PayMerchantConvert.INSTANCE.convertList(merchantListDO)); 84 return success(PayMerchantConvert.INSTANCE.convertList(merchantListDO));
85 } 85 }
86 86
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/dal/mysql/merchant/PayMerchantMapper.java
@@ -6,6 +6,7 @@ import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayMerch @@ -6,6 +6,7 @@ import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayMerch
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 com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; 10 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
10 import org.apache.ibatis.annotations.Mapper; 11 import org.apache.ibatis.annotations.Mapper;
11 12
@@ -48,8 +49,6 @@ public interface PayMerchantMapper extends BaseMapperX&lt;PayMerchantDO&gt; { @@ -48,8 +49,6 @@ public interface PayMerchantMapper extends BaseMapperX&lt;PayMerchantDO&gt; {
48 * @return 商户集合 49 * @return 商户集合
49 */ 50 */
50 default List<PayMerchantDO> getMerchantListByName(String merchantName) { 51 default List<PayMerchantDO> getMerchantListByName(String merchantName) {
51 - // TODO @aquan:全模糊匹配,暂时不考虑索引的事;另外,可以直接 new Lambada 的 QueryWrapper 实现类呀  
52 - return this.selectList(new QueryWrapper<PayMerchantDO>()  
53 - .lambda().likeRight(PayMerchantDO::getName, merchantName)); 52 + return this.selectList(new LambdaQueryWrapper<PayMerchantDO>().like(PayMerchantDO::getName, merchantName));
54 } 53 }
55 } 54 }
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/service/app/impl/PayAppServiceImpl.java
@@ -22,7 +22,7 @@ import org.springframework.validation.annotation.Validated; @@ -22,7 +22,7 @@ import org.springframework.validation.annotation.Validated;
22 import javax.annotation.Resource; 22 import javax.annotation.Resource;
23 import java.util.*; 23 import java.util.*;
24 24
25 -import static cn.iocoder.yudao.coreservice.modules.pay.enums.PayErrorCodeCoreConstants.APP_NOT_EXISTS; 25 +import static cn.iocoder.yudao.coreservice.modules.pay.enums.PayErrorCodeCoreConstants.*;
26 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; 26 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
27 import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; 27 import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
28 28
@@ -72,7 +72,7 @@ public class PayAppServiceImpl implements PayAppService { @@ -72,7 +72,7 @@ public class PayAppServiceImpl implements PayAppService {
72 72
73 private void validateAppExists(Long id) { 73 private void validateAppExists(Long id) {
74 if (appMapper.selectById(id) == null) { 74 if (appMapper.selectById(id) == null) {
75 - throw exception(APP_NOT_EXISTS); 75 + throw exception(PAY_APP_NOT_FOUND);
76 } 76 }
77 } 77 }
78 78
@@ -148,7 +148,7 @@ public class PayAppServiceImpl implements PayAppService { @@ -148,7 +148,7 @@ public class PayAppServiceImpl implements PayAppService {
148 } 148 }
149 PayAppDO payApp = appMapper.selectById(id); 149 PayAppDO payApp = appMapper.selectById(id);
150 if (payApp == null) { 150 if (payApp == null) {
151 - throw exception(APP_NOT_EXISTS); 151 + throw exception(PAY_APP_NOT_FOUND);
152 } 152 }
153 } 153 }
154 } 154 }
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.json.JSONUtil;
3 import cn.iocoder.yudao.adminserver.modules.pay.controller.channel.vo.PayChannelCreateReqVO; 4 import cn.iocoder.yudao.adminserver.modules.pay.controller.channel.vo.PayChannelCreateReqVO;
4 import cn.iocoder.yudao.adminserver.modules.pay.controller.channel.vo.PayChannelExportReqVO; 5 import cn.iocoder.yudao.adminserver.modules.pay.controller.channel.vo.PayChannelExportReqVO;
5 import cn.iocoder.yudao.adminserver.modules.pay.controller.channel.vo.PayChannelPageReqVO; 6 import cn.iocoder.yudao.adminserver.modules.pay.controller.channel.vo.PayChannelPageReqVO;
@@ -9,24 +10,20 @@ import cn.iocoder.yudao.adminserver.modules.pay.dal.mysql.channel.PayChannelMapp @@ -9,24 +10,20 @@ import cn.iocoder.yudao.adminserver.modules.pay.dal.mysql.channel.PayChannelMapp
9 import cn.iocoder.yudao.adminserver.modules.pay.service.channel.PayChannelService; 10 import cn.iocoder.yudao.adminserver.modules.pay.service.channel.PayChannelService;
10 import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayChannelDO; 11 import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayChannelDO;
11 import cn.iocoder.yudao.framework.common.pojo.PageResult; 12 import cn.iocoder.yudao.framework.common.pojo.PageResult;
12 -import cn.iocoder.yudao.framework.pay.core.client.impl.alipay.AlipayPayClientConfig; 13 +import cn.iocoder.yudao.framework.pay.core.client.PayClientConfig;
13 import cn.iocoder.yudao.framework.pay.core.client.impl.wx.WXPayClientConfig; 14 import cn.iocoder.yudao.framework.pay.core.client.impl.wx.WXPayClientConfig;
14 import cn.iocoder.yudao.framework.pay.core.enums.PayChannelEnum; 15 import cn.iocoder.yudao.framework.pay.core.enums.PayChannelEnum;
15 -import com.alibaba.fastjson.JSON;  
16 import lombok.extern.slf4j.Slf4j; 16 import lombok.extern.slf4j.Slf4j;
  17 +import org.springframework.beans.factory.annotation.Autowired;
  18 +import org.springframework.beans.factory.annotation.Qualifier;
17 import org.springframework.stereotype.Service; 19 import org.springframework.stereotype.Service;
18 import org.springframework.util.Assert; 20 import org.springframework.util.Assert;
19 import org.springframework.validation.annotation.Validated; 21 import org.springframework.validation.annotation.Validated;
20 22
21 import javax.annotation.Resource; 23 import javax.annotation.Resource;
22 -import javax.validation.ConstraintViolation;  
23 -import javax.validation.Validation;  
24 import javax.validation.Validator; 24 import javax.validation.Validator;
25 -import javax.validation.ValidatorFactory;  
26 import java.util.Collection; 25 import java.util.Collection;
27 import java.util.List; 26 import java.util.List;
28 -import java.util.Set;  
29 -import java.util.stream.Collectors;  
30 27
31 import static cn.iocoder.yudao.coreservice.modules.pay.enums.PayErrorCodeCoreConstants.*; 28 import static cn.iocoder.yudao.coreservice.modules.pay.enums.PayErrorCodeCoreConstants.*;
32 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; 29 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
@@ -44,14 +41,15 @@ public class PayChannelServiceImpl implements PayChannelService { @@ -44,14 +41,15 @@ public class PayChannelServiceImpl implements PayChannelService {
44 @Resource 41 @Resource
45 private PayChannelMapper channelMapper; 42 private PayChannelMapper channelMapper;
46 43
  44 + @Resource
  45 + private Validator validator;
  46 +
47 @Override 47 @Override
48 public Long createChannel(PayChannelCreateReqVO reqVO) { 48 public Long createChannel(PayChannelCreateReqVO reqVO) {
49 - // TODO @aquan:感觉获得那一条比较合适。因为是有唯一性的。注释有错别字哈。  
50 - // 判断是否有重复的有责无法新增  
51 - Integer channelCount = this.getChannelCountByConditions(reqVO.getMerchantId(), reqVO.getAppId(), reqVO.getCode());  
52 - if (channelCount > 0) {  
53 - throw exception(CHANNEL_EXIST_SAME_CHANNEL_ERROR);  
54 - } 49 +
  50 + // 断言是否有重复的
  51 + PayChannelDO channelDO = this.getChannelByConditions(reqVO.getMerchantId(), reqVO.getAppId(), reqVO.getCode());
  52 + Assert.isNull(channelDO, CHANNEL_EXIST_SAME_CHANNEL_ERROR.getMsg());
55 53
56 // 新增渠道 54 // 新增渠道
57 PayChannelDO channel = PayChannelConvert.INSTANCE.convert(reqVO); 55 PayChannelDO channel = PayChannelConvert.INSTANCE.convert(reqVO);
@@ -143,24 +141,6 @@ public class PayChannelServiceImpl implements PayChannelService { @@ -143,24 +141,6 @@ public class PayChannelServiceImpl implements PayChannelService {
143 } 141 }
144 142
145 /** 143 /**
146 - * 检测微信秘钥参数  
147 - *  
148 - * @param config 信秘钥参数  
149 - */  
150 - private void wechatParamCheck(WXPayClientConfig config) {  
151 - // 针对于 V2 或者 V3 版本的参数校验  
152 - if (WXPayClientConfig.API_VERSION_V2.equals(config.getApiVersion())) {  
153 - Assert.notNull(config.getMchKey(), CHANNEL_WECHAT_VERSION_2_MCH_KEY_IS_NULL.getMsg());  
154 - }  
155 - if (WXPayClientConfig.API_VERSION_V3.equals(config.getApiVersion())) {  
156 - Assert.notNull(config.getPrivateKeyContent(), CHANNEL_WECHAT_VERSION_3_PRIVATE_KEY_IS_NULL.getMsg());  
157 - Assert.notNull(config.getPrivateCertContent(), CHANNEL_WECHAT_VERSION_3_CERT_KEY_IS_NULL.getMsg());  
158 - }  
159 - }  
160 -  
161 -  
162 -  
163 - /**  
164 * 设置渠道配置以及参数校验 144 * 设置渠道配置以及参数校验
165 * 145 *
166 * @param channel 渠道 146 * @param channel 渠道
@@ -168,48 +148,11 @@ public class PayChannelServiceImpl implements PayChannelService { @@ -168,48 +148,11 @@ public class PayChannelServiceImpl implements PayChannelService {
168 */ 148 */
169 private void settingConfigAndCheckParam(PayChannelDO channel, String configStr) { 149 private void settingConfigAndCheckParam(PayChannelDO channel, String configStr) {
170 // 得到这个渠道是微信的还是支付宝的 150 // 得到这个渠道是微信的还是支付宝的
171 - String channelType = PayChannelEnum.verifyWechatOrAliPay(channel.getCode());  
172 - Assert.notNull(channelType, CHANNEL_NOT_EXISTS.getMsg());  
173 -  
174 - // 进行验证  
175 - // TODO @阿全:Spring 可以注入 Validator 哈  
176 - ValidatorFactory validatorFactory = Validation.buildDefaultValidatorFactory();  
177 - Validator validator = validatorFactory.getValidator();  
178 -  
179 - // 微信的验证  
180 - // TODO @aquan:这么实现,可扩性不好。@AssertTrue 注解。  
181 - if (PayChannelEnum.WECHAT.equals(channelType)) {  
182 -  
183 - WXPayClientConfig config = JSON.parseObject(configStr, WXPayClientConfig.class);  
184 - // 判断是V2 版本还是 V3 版本  
185 - Class clazz = config.getApiVersion().equals(WXPayClientConfig.API_VERSION_V2)  
186 - ? WXPayClientConfig.V2.class : WXPayClientConfig.V3.class;  
187 - // 手动调用validate进行验证  
188 - Set<ConstraintViolation<WXPayClientConfig>> validate = validator.validate(config,clazz);  
189 -  
190 - // 断言没有异常  
191 - Assert.isTrue(validate.isEmpty(), validate.stream().map(ConstraintViolation::getMessage)  
192 - .collect(Collectors.joining(",")));  
193 -  
194 - channel.setConfig(config);  
195 - }  
196 -  
197 - // 支付宝验证  
198 - if (PayChannelEnum.ALIPAY.equals(channelType)) {  
199 -  
200 - AlipayPayClientConfig config = JSON.parseObject(configStr, AlipayPayClientConfig.class);  
201 -  
202 - // 判断是V2 版本还是 V3 版本  
203 - Class clazz = config.getMode().equals(AlipayPayClientConfig.MODE_PUBLIC_KEY)  
204 - ? AlipayPayClientConfig.ModePublicKey.class : AlipayPayClientConfig.ModeCertificate.class;  
205 - // 手动调用validate进行验证  
206 - Set<ConstraintViolation<AlipayPayClientConfig>> validate = validator.validate(config,clazz);  
207 -  
208 - // 断言没有异常  
209 - Assert.isTrue(validate.isEmpty(), validate.stream().map(ConstraintViolation::getMessage)  
210 - .collect(Collectors.joining(",")));  
211 - channel.setConfig(config);  
212 - }  
213 - 151 + Class<? extends PayClientConfig> payClass = PayChannelEnum.findByCodeGetClass(channel.getCode());
  152 + Assert.notNull(payClass, CHANNEL_NOT_EXISTS.getMsg());
  153 + PayClientConfig config = JSONUtil.toBean(configStr, payClass);
  154 + // 验证参数
  155 + config.verifyParam(validator);
  156 + channel.setConfig(config);
214 } 157 }
215 } 158 }
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/service/merchant/PayMerchantService.java
@@ -92,14 +92,6 @@ public interface PayMerchantService { @@ -92,14 +92,6 @@ public interface PayMerchantService {
92 */ 92 */
93 List<PayMerchantDO> getMerchantListByName(String merchantName); 93 List<PayMerchantDO> getMerchantListByName(String merchantName);
94 94
95 - // TODO aquan:暂时不用提供这样的检索。商户不多的。  
96 - /**  
97 - * 根据商户名称模糊查询一定数量的商户集合  
98 - * @param merchantName 商户名称  
99 - * @return 商户集合  
100 - */  
101 - List<PayMerchantDO> getMerchantListByNameLimit(String merchantName);  
102 -  
103 /** 95 /**
104 * 获得指定编号的商户 Map 96 * 获得指定编号的商户 Map
105 * 97 *
yudao-admin-server/src/main/java/cn/iocoder/yudao/adminserver/modules/pay/service/merchant/impl/PayMerchantServiceImpl.java
@@ -10,8 +10,6 @@ import cn.iocoder.yudao.adminserver.modules.pay.dal.mysql.merchant.PayMerchantMa @@ -10,8 +10,6 @@ import cn.iocoder.yudao.adminserver.modules.pay.dal.mysql.merchant.PayMerchantMa
10 import cn.iocoder.yudao.adminserver.modules.pay.service.merchant.PayMerchantService; 10 import cn.iocoder.yudao.adminserver.modules.pay.service.merchant.PayMerchantService;
11 import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayMerchantDO; 11 import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayMerchantDO;
12 import cn.iocoder.yudao.framework.common.pojo.PageResult; 12 import cn.iocoder.yudao.framework.common.pojo.PageResult;
13 -import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;  
14 -import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;  
15 import com.google.common.annotations.VisibleForTesting; 13 import com.google.common.annotations.VisibleForTesting;
16 import org.springframework.stereotype.Service; 14 import org.springframework.stereotype.Service;
17 import org.springframework.validation.annotation.Validated; 15 import org.springframework.validation.annotation.Validated;
@@ -21,7 +19,7 @@ import java.time.LocalDateTime; @@ -21,7 +19,7 @@ import java.time.LocalDateTime;
21 import java.util.Collection; 19 import java.util.Collection;
22 import java.util.List; 20 import java.util.List;
23 21
24 -import static cn.iocoder.yudao.coreservice.modules.pay.enums.PayErrorCodeCoreConstants.MERCHANT_NOT_EXISTS; 22 +import static cn.iocoder.yudao.coreservice.modules.pay.enums.PayErrorCodeCoreConstants.PAY_MERCHANT_NOT_EXISTS;
25 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; 23 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
26 /** 24 /**
27 * 支付商户信息 Service 实现类 25 * 支付商户信息 Service 实现类
@@ -64,7 +62,7 @@ public class PayMerchantServiceImpl implements PayMerchantService { @@ -64,7 +62,7 @@ public class PayMerchantServiceImpl implements PayMerchantService {
64 62
65 private void validateMerchantExists(Long id) { 63 private void validateMerchantExists(Long id) {
66 if (merchantMapper.selectById(id) == null) { 64 if (merchantMapper.selectById(id) == null) {
67 - throw exception(MERCHANT_NOT_EXISTS); 65 + throw exception(PAY_MERCHANT_NOT_EXISTS);
68 } 66 }
69 } 67 }
70 68
@@ -116,22 +114,6 @@ public class PayMerchantServiceImpl implements PayMerchantService { @@ -116,22 +114,6 @@ public class PayMerchantServiceImpl implements PayMerchantService {
116 return this.merchantMapper.getMerchantListByName(merchantName); 114 return this.merchantMapper.getMerchantListByName(merchantName);
117 } 115 }
118 116
119 - /**  
120 - * 根据商户名称模糊查询一定数量的商户集合  
121 - *  
122 - * @param merchantName 商户名称  
123 - * @return 商户集合  
124 - */  
125 - @Override  
126 - public List<PayMerchantDO> getMerchantListByNameLimit(String merchantName) {  
127 - // TODO @aquan:mybatis plus 哈  
128 - LambdaQueryWrapper<PayMerchantDO> queryWrapper = new QueryWrapper<PayMerchantDO>().lambda()  
129 - .select(PayMerchantDO::getId, PayMerchantDO::getName)  
130 - .likeRight(PayMerchantDO::getName, merchantName)  
131 - .last("limit 200");  
132 -  
133 - return this.merchantMapper.selectList(queryWrapper);  
134 - }  
135 117
136 /** 118 /**
137 * 检查商户是否存在 119 * 检查商户是否存在
@@ -144,7 +126,7 @@ public class PayMerchantServiceImpl implements PayMerchantService { @@ -144,7 +126,7 @@ public class PayMerchantServiceImpl implements PayMerchantService {
144 } 126 }
145 PayMerchantDO merchant = merchantMapper.selectById(id); 127 PayMerchantDO merchant = merchantMapper.selectById(id);
146 if (merchant == null) { 128 if (merchant == null) {
147 - throw exception(MERCHANT_NOT_EXISTS); 129 + throw exception(PAY_MERCHANT_NOT_EXISTS);
148 } 130 }
149 } 131 }
150 132
yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/pay/service/app/PayAppServiceTest.java
@@ -92,7 +92,7 @@ public class PayAppServiceTest extends BaseDbUnitTest { @@ -92,7 +92,7 @@ public class PayAppServiceTest extends BaseDbUnitTest {
92 PayAppUpdateReqVO reqVO = randomPojo(PayAppUpdateReqVO.class, o -> 92 PayAppUpdateReqVO reqVO = randomPojo(PayAppUpdateReqVO.class, o ->
93 o.setStatus((RandomUtil.randomEle(CommonStatusEnum.values()).getStatus()))); 93 o.setStatus((RandomUtil.randomEle(CommonStatusEnum.values()).getStatus())));
94 // 调用, 并断言异常 94 // 调用, 并断言异常
95 - assertServiceException(() -> appService.updateApp(reqVO), APP_NOT_EXISTS); 95 + assertServiceException(() -> appService.updateApp(reqVO), PAY_APP_NOT_FOUND);
96 } 96 }
97 97
98 @Test 98 @Test
@@ -116,7 +116,7 @@ public class PayAppServiceTest extends BaseDbUnitTest { @@ -116,7 +116,7 @@ public class PayAppServiceTest extends BaseDbUnitTest {
116 Long id = randomLongId(); 116 Long id = randomLongId();
117 117
118 // 调用, 并断言异常 118 // 调用, 并断言异常
119 - assertServiceException(() -> appService.deleteApp(id), APP_NOT_EXISTS); 119 + assertServiceException(() -> appService.deleteApp(id), PAY_APP_NOT_FOUND);
120 } 120 }
121 121
122 @Test 122 @Test
yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/pay/service/channel/PayChannelConfig.java 0 → 100644
  1 +package cn.iocoder.yudao.adminserver.modules.pay.service.channel;
  2 +
  3 +import org.springframework.context.annotation.Bean;
  4 +import org.springframework.context.annotation.Configuration;
  5 +
  6 +import javax.validation.Validation;
  7 +import javax.validation.Validator;
  8 +
  9 +/**
  10 + * 用于初始化 validator Bean 对象
  11 + * @author aquan
  12 + */
  13 +@Configuration
  14 +public class PayChannelConfig {
  15 +
  16 + @Bean
  17 + public Validator validator(){
  18 + return Validation.buildDefaultValidatorFactory().getValidator();
  19 + }
  20 +}
yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/pay/service/channel/PayChannelServiceTest.java
@@ -34,7 +34,10 @@ import static org.junit.jupiter.api.Assertions.*; @@ -34,7 +34,10 @@ import static org.junit.jupiter.api.Assertions.*;
34 * 34 *
35 * @author 芋艿 35 * @author 芋艿
36 */ 36 */
37 -@Import(PayChannelServiceImpl.class) 37 +@Import({
  38 + PayChannelServiceImpl.class,
  39 + PayChannelConfig.class
  40 +})
38 public class PayChannelServiceTest extends BaseDbUnitTest { 41 public class PayChannelServiceTest extends BaseDbUnitTest {
39 42
40 @Resource 43 @Resource
@@ -43,7 +46,6 @@ public class PayChannelServiceTest extends BaseDbUnitTest { @@ -43,7 +46,6 @@ public class PayChannelServiceTest extends BaseDbUnitTest {
43 @Resource 46 @Resource
44 private PayChannelMapper channelMapper; 47 private PayChannelMapper channelMapper;
45 48
46 -  
47 @Test 49 @Test
48 public void testCreateWechatVersion2Channel_success() { 50 public void testCreateWechatVersion2Channel_success() {
49 // 准备参数 51 // 准备参数
@@ -69,8 +71,7 @@ public class PayChannelServiceTest extends BaseDbUnitTest { @@ -69,8 +71,7 @@ public class PayChannelServiceTest extends BaseDbUnitTest {
69 71
70 @Test 72 @Test
71 public void testCreateWechatVersion3Channel_success() { 73 public void testCreateWechatVersion3Channel_success() {
72 - // 准备参数 TODO @aquan:多余的空行去掉哈。例如说 74 行。  
73 - 74 + // 准备参数
74 WXPayClientConfig v3Config = getV3Config(); 75 WXPayClientConfig v3Config = getV3Config();
75 PayChannelCreateReqVO reqVO = randomPojo(PayChannelCreateReqVO.class, o -> { 76 PayChannelCreateReqVO reqVO = randomPojo(PayChannelCreateReqVO.class, o -> {
76 o.setCode(PayChannelEnum.WX_PUB.getCode()); 77 o.setCode(PayChannelEnum.WX_PUB.getCode());
yudao-admin-server/src/test/java/cn/iocoder/yudao/adminserver/modules/pay/service/merchant/PayMerchantServiceTest.java
@@ -18,7 +18,7 @@ import org.springframework.context.annotation.Import; @@ -18,7 +18,7 @@ import org.springframework.context.annotation.Import;
18 import javax.annotation.Resource; 18 import javax.annotation.Resource;
19 import java.util.List; 19 import java.util.List;
20 20
21 -import static cn.iocoder.yudao.coreservice.modules.pay.enums.PayErrorCodeCoreConstants.MERCHANT_NOT_EXISTS; 21 +import static cn.iocoder.yudao.coreservice.modules.pay.enums.PayErrorCodeCoreConstants.PAY_MERCHANT_NOT_EXISTS;
22 import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; 22 import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals;
23 import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException; 23 import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException;
24 import static cn.iocoder.yudao.framework.common.util.date.DateUtils.buildTime; 24 import static cn.iocoder.yudao.framework.common.util.date.DateUtils.buildTime;
@@ -79,7 +79,7 @@ public class PayMerchantServiceTest extends BaseDbUnitTest { @@ -79,7 +79,7 @@ public class PayMerchantServiceTest extends BaseDbUnitTest {
79 PayMerchantUpdateReqVO reqVO = randomPojo(PayMerchantUpdateReqVO.class); 79 PayMerchantUpdateReqVO reqVO = randomPojo(PayMerchantUpdateReqVO.class);
80 80
81 // 调用, 并断言异常 81 // 调用, 并断言异常
82 - assertServiceException(() -> merchantService.updateMerchant(reqVO), MERCHANT_NOT_EXISTS); 82 + assertServiceException(() -> merchantService.updateMerchant(reqVO), PAY_MERCHANT_NOT_EXISTS);
83 } 83 }
84 84
85 @Test 85 @Test
@@ -103,7 +103,7 @@ public class PayMerchantServiceTest extends BaseDbUnitTest { @@ -103,7 +103,7 @@ public class PayMerchantServiceTest extends BaseDbUnitTest {
103 Long id = randomLongId(); 103 Long id = randomLongId();
104 104
105 // 调用, 并断言异常 105 // 调用, 并断言异常
106 - assertServiceException(() -> merchantService.deleteMerchant(id), MERCHANT_NOT_EXISTS); 106 + assertServiceException(() -> merchantService.deleteMerchant(id), PAY_MERCHANT_NOT_EXISTS);
107 } 107 }
108 108
109 @Test 109 @Test
yudao-core-service/src/main/java/cn/iocoder/yudao/coreservice/modules/pay/enums/PayErrorCodeCoreConstants.java
@@ -22,7 +22,6 @@ public interface PayErrorCodeCoreConstants { @@ -22,7 +22,6 @@ public interface PayErrorCodeCoreConstants {
22 ErrorCode PAY_CHANNEL_IS_DISABLE = new ErrorCode(1007001001, "支付渠道已经禁用"); 22 ErrorCode PAY_CHANNEL_IS_DISABLE = new ErrorCode(1007001001, "支付渠道已经禁用");
23 ErrorCode PAY_CHANNEL_CLIENT_NOT_FOUND = new ErrorCode(1007001002, "支付渠道的客户端不存在"); 23 ErrorCode PAY_CHANNEL_CLIENT_NOT_FOUND = new ErrorCode(1007001002, "支付渠道的客户端不存在");
24 ErrorCode CHANNEL_NOT_EXISTS = new ErrorCode(1007001003, "支付渠道不存在"); 24 ErrorCode CHANNEL_NOT_EXISTS = new ErrorCode(1007001003, "支付渠道不存在");
25 - ErrorCode CHANNEL_KEY_READ_ERROR = new ErrorCode(1007001004, "支付渠道秘钥文件读取失败");  
26 ErrorCode CHANNEL_EXIST_SAME_CHANNEL_ERROR = new ErrorCode(1007001005, "已存在相同的渠道"); 25 ErrorCode CHANNEL_EXIST_SAME_CHANNEL_ERROR = new ErrorCode(1007001005, "已存在相同的渠道");
27 ErrorCode CHANNEL_WECHAT_VERSION_2_MCH_KEY_IS_NULL = new ErrorCode(1007001006,"微信渠道v2版本中商户密钥不可为空"); 26 ErrorCode CHANNEL_WECHAT_VERSION_2_MCH_KEY_IS_NULL = new ErrorCode(1007001006,"微信渠道v2版本中商户密钥不可为空");
28 ErrorCode CHANNEL_WECHAT_VERSION_3_PRIVATE_KEY_IS_NULL = new ErrorCode(1007001006,"微信渠道v3版本apiclient_key.pem不可为空"); 27 ErrorCode CHANNEL_WECHAT_VERSION_3_PRIVATE_KEY_IS_NULL = new ErrorCode(1007001006,"微信渠道v3版本apiclient_key.pem不可为空");
@@ -49,18 +48,14 @@ public interface PayErrorCodeCoreConstants { @@ -49,18 +48,14 @@ public interface PayErrorCodeCoreConstants {
49 ErrorCode PAY_REFUND_CHN_ORDER_NO_IS_NULL = new ErrorCode(1007006002, "该订单的渠道订单为空"); 48 ErrorCode PAY_REFUND_CHN_ORDER_NO_IS_NULL = new ErrorCode(1007006002, "该订单的渠道订单为空");
50 ErrorCode PAY_REFUND_POST_HANDLER_NOT_FOUND = new ErrorCode(1007006003, "未找到对应的退款后置处理类"); 49 ErrorCode PAY_REFUND_POST_HANDLER_NOT_FOUND = new ErrorCode(1007006003, "未找到对应的退款后置处理类");
51 ErrorCode PAY_REFUND_NOT_FOUND = new ErrorCode(1007006004, "支付退款单不存在"); 50 ErrorCode PAY_REFUND_NOT_FOUND = new ErrorCode(1007006004, "支付退款单不存在");
52 - // TODO @aquan:下面还两个要合并上去哈。另外一般中英文之间要有空格。例如说, 新建一个 order 数据;这样可读性更好。  
53 51
54 /** 52 /**
55 * ========== 支付商户信息 1-007-004-000 ========== 53 * ========== 支付商户信息 1-007-004-000 ==========
56 */ 54 */
57 - ErrorCode MERCHANT_NOT_EXISTS = new ErrorCode(1007004000, "支付商户信息不存在"); 55 + ErrorCode PAY_MERCHANT_NOT_EXISTS = new ErrorCode(1007004000, "支付商户信息不存在");
  56 +
58 57
59 58
60 - /**  
61 - * ========== 支付应用信息 1-007-005-000 ==========  
62 - */  
63 - ErrorCode APP_NOT_EXISTS = new ErrorCode(1007005000, "支付应用信息不存在");  
64 59
65 60
66 } 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;
3 import com.fasterxml.jackson.annotation.JsonTypeInfo; 5 import com.fasterxml.jackson.annotation.JsonTypeInfo;
4 6
  7 +import javax.validation.Validator;
  8 +
5 /** 9 /**
6 * 支付客户端的配置,本质是支付渠道的配置 10 * 支付客户端的配置,本质是支付渠道的配置
7 * 每个不同的渠道,需要不同的配置,通过子类来定义 11 * 每个不同的渠道,需要不同的配置,通过子类来定义
@@ -13,4 +17,10 @@ import com.fasterxml.jackson.annotation.JsonTypeInfo; @@ -13,4 +17,10 @@ import com.fasterxml.jackson.annotation.JsonTypeInfo;
13 // 1. 序列化到时数据库时,增加 @class 属性。 17 // 1. 序列化到时数据库时,增加 @class 属性。
14 // 2. 反序列化到内存对象时,通过 @class 属性,可以创建出正确的类型 18 // 2. 反序列化到内存对象时,通过 @class 属性,可以创建出正确的类型
15 public interface PayClientConfig { 19 public interface PayClientConfig {
  20 +
  21 + /**
  22 + * 验证配置参数是否正确
  23 + * @param validator 校验对象
  24 + */
  25 + void verifyParam(Validator validator);
16 } 26 }
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/alipay/AlipayPayClientConfig.java
@@ -2,9 +2,17 @@ package cn.iocoder.yudao.framework.pay.core.client.impl.alipay; @@ -2,9 +2,17 @@ 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;
5 7
  8 +import javax.annotation.Resource;
  9 +import javax.validation.ConstraintViolation;
  10 +import javax.validation.Validator;
  11 +import javax.validation.constraints.AssertTrue;
6 import javax.validation.constraints.NotBlank; 12 import javax.validation.constraints.NotBlank;
7 import javax.validation.constraints.NotNull; 13 import javax.validation.constraints.NotNull;
  14 +import java.util.Set;
  15 +import java.util.stream.Collectors;
8 16
9 // TODO 芋艿:参数校验 17 // TODO 芋艿:参数校验
10 18
@@ -106,4 +114,18 @@ public class AlipayPayClientConfig implements PayClientConfig { @@ -106,4 +114,18 @@ public class AlipayPayClientConfig implements PayClientConfig {
106 public interface ModeCertificate { 114 public interface ModeCertificate {
107 } 115 }
108 116
  117 + /**
  118 + * 验证配置参数是否正确
  119 + * @param validator 校验对象
  120 + */
  121 + @Override
  122 + public void verifyParam(Validator validator) {
  123 + // 手动调用validate进行验证
  124 + Set<ConstraintViolation<AlipayPayClientConfig>> validate = validator.validate(this,
  125 + 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 + }
109 } 131 }
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/wx/WXPayClientConfig.java
1 package cn.iocoder.yudao.framework.pay.core.client.impl.wx; 1 package cn.iocoder.yudao.framework.pay.core.client.impl.wx;
2 2
3 import cn.hutool.core.io.IoUtil; 3 import cn.hutool.core.io.IoUtil;
  4 +import cn.hutool.json.JSONObject;
  5 +import cn.hutool.json.JSONUtil;
4 import cn.iocoder.yudao.framework.pay.core.client.PayClientConfig; 6 import cn.iocoder.yudao.framework.pay.core.client.PayClientConfig;
  7 +import com.alibaba.fastjson.JSON;
5 import lombok.Data; 8 import lombok.Data;
  9 +import org.springframework.beans.factory.annotation.Autowired;
  10 +import org.springframework.util.Assert;
6 11
  12 +import javax.annotation.Resource;
  13 +import javax.validation.ConstraintViolation;
  14 +import javax.validation.Validator;
  15 +import javax.validation.constraints.AssertTrue;
7 import javax.validation.constraints.NotBlank; 16 import javax.validation.constraints.NotBlank;
8 import java.io.FileInputStream; 17 import java.io.FileInputStream;
9 import java.io.FileNotFoundException; 18 import java.io.FileNotFoundException;
  19 +import java.util.Set;
  20 +import java.util.stream.Collectors;
10 21
11 // TODO 芋艿:参数校验 22 // TODO 芋艿:参数校验
12 23
13 -// TODO @aquan: 不要全文件格式化哈,去掉下 <p> 看着不太友好哈  
14 -  
15 /** 24 /**
16 * 微信支付的 PayClientConfig 实现类 25 * 微信支付的 PayClientConfig 实现类
17 * 属性主要来自 {@link com.github.binarywang.wxpay.config.WxPayConfig} 的必要属性 26 * 属性主要来自 {@link com.github.binarywang.wxpay.config.WxPayConfig} 的必要属性
@@ -24,13 +33,11 @@ public class WXPayClientConfig implements PayClientConfig { @@ -24,13 +33,11 @@ public class WXPayClientConfig implements PayClientConfig {
24 // TODO 芋艿:V2 or V3 客户端 33 // TODO 芋艿:V2 or V3 客户端
25 /** 34 /**
26 * API 版本 - V2 35 * API 版本 - V2
27 - * <p>  
28 * https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=4_1 36 * https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=4_1
29 */ 37 */
30 public static final String API_VERSION_V2 = "v2"; 38 public static final String API_VERSION_V2 = "v2";
31 /** 39 /**
32 * API 版本 - V3 40 * API 版本 - V3
33 - * <p>  
34 * https://pay.weixin.qq.com/wiki/doc/apiv3/wechatpay/wechatpay-1.shtml 41 * https://pay.weixin.qq.com/wiki/doc/apiv3/wechatpay/wechatpay-1.shtml
35 */ 42 */
36 public static final String API_VERSION_V3 = "v3"; 43 public static final String API_VERSION_V3 = "v3";
@@ -56,7 +63,7 @@ public class WXPayClientConfig implements PayClientConfig { @@ -56,7 +63,7 @@ public class WXPayClientConfig implements PayClientConfig {
56 /** 63 /**
57 * 商户密钥 64 * 商户密钥
58 */ 65 */
59 - @NotBlank(message = "商户密钥 不能为空", groups = {V2.class}) 66 + @NotBlank(message = "商户密钥 不能为空", groups = V2.class)
60 private String mchKey; 67 private String mchKey;
61 /** 68 /**
62 * apiclient_cert.p12 证书文件的绝对路径或者以 classpath: 开头的类路径. 69 * apiclient_cert.p12 证书文件的绝对路径或者以 classpath: 开头的类路径.
@@ -70,11 +77,9 @@ public class WXPayClientConfig implements PayClientConfig { @@ -70,11 +77,9 @@ public class WXPayClientConfig implements PayClientConfig {
70 /** 77 /**
71 * apiclient_key.pem 证书文件的绝对路径或者以 classpath: 开头的类路径. 78 * apiclient_key.pem 证书文件的绝对路径或者以 classpath: 开头的类路径.
72 * 对应的字符串 79 * 对应的字符串
73 - * <p>  
74 * 注意,可通过 {@link #main(String[])} 读取 80 * 注意,可通过 {@link #main(String[])} 读取
75 */ 81 */
76 - // TODO @aquan:对于只有一个值的时候,直接 groups = V3.class 即可,简洁。例如说,我们在 Spring MVC 注解,url 可以多个,也只写单个,一个道理哈  
77 - @NotBlank(message = "apiclient_key 不能为空", groups = {V3.class}) 82 + @NotBlank(message = "apiclient_key 不能为空", groups = V3.class)
78 private String privateKeyContent; 83 private String privateKeyContent;
79 /** 84 /**
80 * apiclient_cert.pem 证书文件的绝对路径或者以 classpath: 开头的类路径. 85 * apiclient_cert.pem 证书文件的绝对路径或者以 classpath: 开头的类路径.
@@ -82,21 +87,14 @@ public class WXPayClientConfig implements PayClientConfig { @@ -82,21 +87,14 @@ public class WXPayClientConfig implements PayClientConfig {
82 * <p> 87 * <p>
83 * 注意,可通过 {@link #main(String[])} 读取 88 * 注意,可通过 {@link #main(String[])} 读取
84 */ 89 */
85 - @NotBlank(message = "apiclient_cert 不能为空", groups = {V3.class}) 90 + @NotBlank(message = "apiclient_cert 不能为空", groups = V3.class)
86 private String privateCertContent; 91 private String privateCertContent;
87 /** 92 /**
88 * apiV3 秘钥值 93 * apiV3 秘钥值
89 */ 94 */
90 - @NotBlank(message = "apiV3 秘钥值 不能为空", groups = {V3.class}) 95 + @NotBlank(message = "apiV3 秘钥值 不能为空", groups = V3.class)
91 private String apiV3Key; 96 private String apiV3Key;
92 97
93 - public static void main(String[] args) throws FileNotFoundException {  
94 - String path = "/Users/yunai/Downloads/wx_pay/apiclient_cert.p12";  
95 -// String path = "/Users/yunai/Downloads/wx_pay/apiclient_key.pem";  
96 -// String path = "/Users/yunai/Downloads/wx_pay/apiclient_cert.pem";  
97 - System.out.println(IoUtil.readUtf8(new FileInputStream(path)));  
98 - }  
99 -  
100 98
101 /** 99 /**
102 * 分组校验 v2版本 100 * 分组校验 v2版本
@@ -110,4 +108,26 @@ public class WXPayClientConfig implements PayClientConfig { @@ -110,4 +108,26 @@ public class WXPayClientConfig implements PayClientConfig {
110 public interface V3 { 108 public interface V3 {
111 } 109 }
112 110
  111 + /**
  112 + * 验证配置参数是否正确
  113 + * @param validator 校验对象
  114 + */
  115 + @Override
  116 + public void verifyParam(Validator validator) {
  117 + // 手动调用validate进行验证
  118 + Set<ConstraintViolation<PayClientConfig>> validate = validator.validate(this,
  119 + this.getApiVersion().equals(API_VERSION_V2) ? V2.class : V3.class);
  120 + // 断言没有异常
  121 + Assert.isTrue(validate.isEmpty(), validate.stream().map(ConstraintViolation::getMessage)
  122 + .collect(Collectors.joining(",")));
  123 + }
  124 +
  125 + public static void main(String[] args) throws FileNotFoundException {
  126 + String path = "/Users/yunai/Downloads/wx_pay/apiclient_cert.p12";
  127 + /// String path = "/Users/yunai/Downloads/wx_pay/apiclient_key.pem";
  128 + /// String path = "/Users/yunai/Downloads/wx_pay/apiclient_cert.pem";
  129 + System.out.println(IoUtil.readUtf8(new FileInputStream(path)));
  130 + }
  131 +
  132 +
113 } 133 }
yudao-framework/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/enums/PayChannelEnum.java
1 package cn.iocoder.yudao.framework.pay.core.enums; 1 package cn.iocoder.yudao.framework.pay.core.enums;
2 2
3 import cn.hutool.core.util.ArrayUtil; 3 import cn.hutool.core.util.ArrayUtil;
  4 +import cn.iocoder.yudao.framework.pay.core.client.PayClientConfig;
  5 +import cn.iocoder.yudao.framework.pay.core.client.impl.alipay.AlipayPayClientConfig;
  6 +import cn.iocoder.yudao.framework.pay.core.client.impl.wx.WXPayClientConfig;
4 import lombok.AllArgsConstructor; 7 import lombok.AllArgsConstructor;
5 import lombok.Getter; 8 import lombok.Getter;
6 9
@@ -49,21 +52,21 @@ public enum PayChannelEnum { @@ -49,21 +52,21 @@ public enum PayChannelEnum {
49 } 52 }
50 53
51 /** 54 /**
52 - * 判断当前渠道是那种支付方式  
53 - * @param code  
54 - * @return 55 + * 根据编码得到支付类
  56 + * @param code 编码
  57 + * @return 支付配置类
55 */ 58 */
56 - public static String verifyWechatOrAliPay(String code){ 59 + public static Class<? extends PayClientConfig> findByCodeGetClass(String code){
57 switch (PayChannelEnum.getByCode(code)){ 60 switch (PayChannelEnum.getByCode(code)){
58 case WX_PUB: 61 case WX_PUB:
59 case WX_LITE: 62 case WX_LITE:
60 case WX_APP: 63 case WX_APP:
61 - return WECHAT; 64 + return WXPayClientConfig.class;
62 case ALIPAY_PC: 65 case ALIPAY_PC:
63 case ALIPAY_WAP: 66 case ALIPAY_WAP:
64 case ALIPAY_APP: 67 case ALIPAY_APP:
65 case ALIPAY_QR: 68 case ALIPAY_QR:
66 - return ALIPAY; 69 + return AlipayPayClientConfig.class;
67 } 70 }
68 return null; 71 return null;
69 } 72 }