Commit 1c5544fc9d69d3949cb025307cc5687105d05cfd
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 | 80 | @ApiImplicitParam(name = "name", value = "商户名称", required = true, example = "芋道", dataTypeClass = Long.class) |
| 81 | 81 | @PreAuthorize("@ss.hasPermission('pay:merchant:query')") |
| 82 | 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 | 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 | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| 7 | 7 | import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; |
| 8 | 8 | import cn.iocoder.yudao.framework.mybatis.core.query.QueryWrapperX; |
| 9 | +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; | |
| 9 | 10 | import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; |
| 10 | 11 | import org.apache.ibatis.annotations.Mapper; |
| 11 | 12 | |
| ... | ... | @@ -48,8 +49,6 @@ public interface PayMerchantMapper extends BaseMapperX<PayMerchantDO> { |
| 48 | 49 | * @return 商户集合 |
| 49 | 50 | */ |
| 50 | 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 | 22 | import javax.annotation.Resource; |
| 23 | 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 | 26 | import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; |
| 27 | 27 | import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; |
| 28 | 28 | |
| ... | ... | @@ -72,7 +72,7 @@ public class PayAppServiceImpl implements PayAppService { |
| 72 | 72 | |
| 73 | 73 | private void validateAppExists(Long id) { |
| 74 | 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 | 148 | } |
| 149 | 149 | PayAppDO payApp = appMapper.selectById(id); |
| 150 | 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 | 1 | package cn.iocoder.yudao.adminserver.modules.pay.service.channel.impl; |
| 2 | 2 | |
| 3 | +import cn.hutool.json.JSONUtil; | |
| 3 | 4 | import cn.iocoder.yudao.adminserver.modules.pay.controller.channel.vo.PayChannelCreateReqVO; |
| 4 | 5 | import cn.iocoder.yudao.adminserver.modules.pay.controller.channel.vo.PayChannelExportReqVO; |
| 5 | 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 | 10 | import cn.iocoder.yudao.adminserver.modules.pay.service.channel.PayChannelService; |
| 10 | 11 | import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayChannelDO; |
| 11 | 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 | 14 | import cn.iocoder.yudao.framework.pay.core.client.impl.wx.WXPayClientConfig; |
| 14 | 15 | import cn.iocoder.yudao.framework.pay.core.enums.PayChannelEnum; |
| 15 | -import com.alibaba.fastjson.JSON; | |
| 16 | 16 | import lombok.extern.slf4j.Slf4j; |
| 17 | +import org.springframework.beans.factory.annotation.Autowired; | |
| 18 | +import org.springframework.beans.factory.annotation.Qualifier; | |
| 17 | 19 | import org.springframework.stereotype.Service; |
| 18 | 20 | import org.springframework.util.Assert; |
| 19 | 21 | import org.springframework.validation.annotation.Validated; |
| 20 | 22 | |
| 21 | 23 | import javax.annotation.Resource; |
| 22 | -import javax.validation.ConstraintViolation; | |
| 23 | -import javax.validation.Validation; | |
| 24 | 24 | import javax.validation.Validator; |
| 25 | -import javax.validation.ValidatorFactory; | |
| 26 | 25 | import java.util.Collection; |
| 27 | 26 | import java.util.List; |
| 28 | -import java.util.Set; | |
| 29 | -import java.util.stream.Collectors; | |
| 30 | 27 | |
| 31 | 28 | import static cn.iocoder.yudao.coreservice.modules.pay.enums.PayErrorCodeCoreConstants.*; |
| 32 | 29 | import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; |
| ... | ... | @@ -44,14 +41,15 @@ public class PayChannelServiceImpl implements PayChannelService { |
| 44 | 41 | @Resource |
| 45 | 42 | private PayChannelMapper channelMapper; |
| 46 | 43 | |
| 44 | + @Resource | |
| 45 | + private Validator validator; | |
| 46 | + | |
| 47 | 47 | @Override |
| 48 | 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 | 55 | PayChannelDO channel = PayChannelConvert.INSTANCE.convert(reqVO); |
| ... | ... | @@ -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 | 146 | * @param channel 渠道 |
| ... | ... | @@ -168,48 +148,11 @@ public class PayChannelServiceImpl implements PayChannelService { |
| 168 | 148 | */ |
| 169 | 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 | 92 | */ |
| 93 | 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 | 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 | 10 | import cn.iocoder.yudao.adminserver.modules.pay.service.merchant.PayMerchantService; |
| 11 | 11 | import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayMerchantDO; |
| 12 | 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 | 13 | import com.google.common.annotations.VisibleForTesting; |
| 16 | 14 | import org.springframework.stereotype.Service; |
| 17 | 15 | import org.springframework.validation.annotation.Validated; |
| ... | ... | @@ -21,7 +19,7 @@ import java.time.LocalDateTime; |
| 21 | 19 | import java.util.Collection; |
| 22 | 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 | 23 | import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; |
| 26 | 24 | /** |
| 27 | 25 | * 支付商户信息 Service 实现类 |
| ... | ... | @@ -64,7 +62,7 @@ public class PayMerchantServiceImpl implements PayMerchantService { |
| 64 | 62 | |
| 65 | 63 | private void validateMerchantExists(Long id) { |
| 66 | 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 | 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 | 126 | } |
| 145 | 127 | PayMerchantDO merchant = merchantMapper.selectById(id); |
| 146 | 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 | 92 | PayAppUpdateReqVO reqVO = randomPojo(PayAppUpdateReqVO.class, o -> |
| 93 | 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 | 98 | @Test |
| ... | ... | @@ -116,7 +116,7 @@ public class PayAppServiceTest extends BaseDbUnitTest { |
| 116 | 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 | 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 | 34 | * |
| 35 | 35 | * @author 芋艿 |
| 36 | 36 | */ |
| 37 | -@Import(PayChannelServiceImpl.class) | |
| 37 | +@Import({ | |
| 38 | + PayChannelServiceImpl.class, | |
| 39 | + PayChannelConfig.class | |
| 40 | +}) | |
| 38 | 41 | public class PayChannelServiceTest extends BaseDbUnitTest { |
| 39 | 42 | |
| 40 | 43 | @Resource |
| ... | ... | @@ -43,7 +46,6 @@ public class PayChannelServiceTest extends BaseDbUnitTest { |
| 43 | 46 | @Resource |
| 44 | 47 | private PayChannelMapper channelMapper; |
| 45 | 48 | |
| 46 | - | |
| 47 | 49 | @Test |
| 48 | 50 | public void testCreateWechatVersion2Channel_success() { |
| 49 | 51 | // 准备参数 |
| ... | ... | @@ -69,8 +71,7 @@ public class PayChannelServiceTest extends BaseDbUnitTest { |
| 69 | 71 | |
| 70 | 72 | @Test |
| 71 | 73 | public void testCreateWechatVersion3Channel_success() { |
| 72 | - // 准备参数 TODO @aquan:多余的空行去掉哈。例如说 74 行。 | |
| 73 | - | |
| 74 | + // 准备参数 | |
| 74 | 75 | WXPayClientConfig v3Config = getV3Config(); |
| 75 | 76 | PayChannelCreateReqVO reqVO = randomPojo(PayChannelCreateReqVO.class, o -> { |
| 76 | 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 | 18 | import javax.annotation.Resource; |
| 19 | 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 | 22 | import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; |
| 23 | 23 | import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException; |
| 24 | 24 | import static cn.iocoder.yudao.framework.common.util.date.DateUtils.buildTime; |
| ... | ... | @@ -79,7 +79,7 @@ public class PayMerchantServiceTest extends BaseDbUnitTest { |
| 79 | 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 | 85 | @Test |
| ... | ... | @@ -103,7 +103,7 @@ public class PayMerchantServiceTest extends BaseDbUnitTest { |
| 103 | 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 | 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 | 22 | ErrorCode PAY_CHANNEL_IS_DISABLE = new ErrorCode(1007001001, "支付渠道已经禁用"); |
| 23 | 23 | ErrorCode PAY_CHANNEL_CLIENT_NOT_FOUND = new ErrorCode(1007001002, "支付渠道的客户端不存在"); |
| 24 | 24 | ErrorCode CHANNEL_NOT_EXISTS = new ErrorCode(1007001003, "支付渠道不存在"); |
| 25 | - ErrorCode CHANNEL_KEY_READ_ERROR = new ErrorCode(1007001004, "支付渠道秘钥文件读取失败"); | |
| 26 | 25 | ErrorCode CHANNEL_EXIST_SAME_CHANNEL_ERROR = new ErrorCode(1007001005, "已存在相同的渠道"); |
| 27 | 26 | ErrorCode CHANNEL_WECHAT_VERSION_2_MCH_KEY_IS_NULL = new ErrorCode(1007001006,"微信渠道v2版本中商户密钥不可为空"); |
| 28 | 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 | 48 | ErrorCode PAY_REFUND_CHN_ORDER_NO_IS_NULL = new ErrorCode(1007006002, "该订单的渠道订单为空"); |
| 50 | 49 | ErrorCode PAY_REFUND_POST_HANDLER_NOT_FOUND = new ErrorCode(1007006003, "未找到对应的退款后置处理类"); |
| 51 | 50 | ErrorCode PAY_REFUND_NOT_FOUND = new ErrorCode(1007006004, "支付退款单不存在"); |
| 52 | - // TODO @aquan:下面还两个要合并上去哈。另外一般中英文之间要有空格。例如说, 新建一个 order 数据;这样可读性更好。 | |
| 53 | 51 | |
| 54 | 52 | /** |
| 55 | 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 | 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 | 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 | 17 | // 1. 序列化到时数据库时,增加 @class 属性。 |
| 14 | 18 | // 2. 反序列化到内存对象时,通过 @class 属性,可以创建出正确的类型 |
| 15 | 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 | 2 | |
| 3 | 3 | import cn.iocoder.yudao.framework.pay.core.client.PayClientConfig; |
| 4 | 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 | 12 | import javax.validation.constraints.NotBlank; |
| 7 | 13 | import javax.validation.constraints.NotNull; |
| 14 | +import java.util.Set; | |
| 15 | +import java.util.stream.Collectors; | |
| 8 | 16 | |
| 9 | 17 | // TODO 芋艿:参数校验 |
| 10 | 18 | |
| ... | ... | @@ -106,4 +114,18 @@ public class AlipayPayClientConfig implements PayClientConfig { |
| 106 | 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 | 1 | package cn.iocoder.yudao.framework.pay.core.client.impl.wx; |
| 2 | 2 | |
| 3 | 3 | import cn.hutool.core.io.IoUtil; |
| 4 | +import cn.hutool.json.JSONObject; | |
| 5 | +import cn.hutool.json.JSONUtil; | |
| 4 | 6 | import cn.iocoder.yudao.framework.pay.core.client.PayClientConfig; |
| 7 | +import com.alibaba.fastjson.JSON; | |
| 5 | 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 | 16 | import javax.validation.constraints.NotBlank; |
| 8 | 17 | import java.io.FileInputStream; |
| 9 | 18 | import java.io.FileNotFoundException; |
| 19 | +import java.util.Set; | |
| 20 | +import java.util.stream.Collectors; | |
| 10 | 21 | |
| 11 | 22 | // TODO 芋艿:参数校验 |
| 12 | 23 | |
| 13 | -// TODO @aquan: 不要全文件格式化哈,去掉下 <p> 看着不太友好哈 | |
| 14 | - | |
| 15 | 24 | /** |
| 16 | 25 | * 微信支付的 PayClientConfig 实现类 |
| 17 | 26 | * 属性主要来自 {@link com.github.binarywang.wxpay.config.WxPayConfig} 的必要属性 |
| ... | ... | @@ -24,13 +33,11 @@ public class WXPayClientConfig implements PayClientConfig { |
| 24 | 33 | // TODO 芋艿:V2 or V3 客户端 |
| 25 | 34 | /** |
| 26 | 35 | * API 版本 - V2 |
| 27 | - * <p> | |
| 28 | 36 | * https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=4_1 |
| 29 | 37 | */ |
| 30 | 38 | public static final String API_VERSION_V2 = "v2"; |
| 31 | 39 | /** |
| 32 | 40 | * API 版本 - V3 |
| 33 | - * <p> | |
| 34 | 41 | * https://pay.weixin.qq.com/wiki/doc/apiv3/wechatpay/wechatpay-1.shtml |
| 35 | 42 | */ |
| 36 | 43 | public static final String API_VERSION_V3 = "v3"; |
| ... | ... | @@ -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 | 67 | private String mchKey; |
| 61 | 68 | /** |
| 62 | 69 | * apiclient_cert.p12 证书文件的绝对路径或者以 classpath: 开头的类路径. |
| ... | ... | @@ -70,11 +77,9 @@ public class WXPayClientConfig implements PayClientConfig { |
| 70 | 77 | /** |
| 71 | 78 | * apiclient_key.pem 证书文件的绝对路径或者以 classpath: 开头的类路径. |
| 72 | 79 | * 对应的字符串 |
| 73 | - * <p> | |
| 74 | 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 | 83 | private String privateKeyContent; |
| 79 | 84 | /** |
| 80 | 85 | * apiclient_cert.pem 证书文件的绝对路径或者以 classpath: 开头的类路径. |
| ... | ... | @@ -82,21 +87,14 @@ public class WXPayClientConfig implements PayClientConfig { |
| 82 | 87 | * <p> |
| 83 | 88 | * 注意,可通过 {@link #main(String[])} 读取 |
| 84 | 89 | */ |
| 85 | - @NotBlank(message = "apiclient_cert 不能为空", groups = {V3.class}) | |
| 90 | + @NotBlank(message = "apiclient_cert 不能为空", groups = V3.class) | |
| 86 | 91 | private String privateCertContent; |
| 87 | 92 | /** |
| 88 | 93 | * apiV3 秘钥值 |
| 89 | 94 | */ |
| 90 | - @NotBlank(message = "apiV3 秘钥值 不能为空", groups = {V3.class}) | |
| 95 | + @NotBlank(message = "apiV3 秘钥值 不能为空", groups = V3.class) | |
| 91 | 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 | 100 | * 分组校验 v2版本 |
| ... | ... | @@ -110,4 +108,26 @@ public class WXPayClientConfig implements PayClientConfig { |
| 110 | 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 | 1 | package cn.iocoder.yudao.framework.pay.core.enums; |
| 2 | 2 | |
| 3 | 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 | 7 | import lombok.AllArgsConstructor; |
| 5 | 8 | import lombok.Getter; |
| 6 | 9 | |
| ... | ... | @@ -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 | 60 | switch (PayChannelEnum.getByCode(code)){ |
| 58 | 61 | case WX_PUB: |
| 59 | 62 | case WX_LITE: |
| 60 | 63 | case WX_APP: |
| 61 | - return WECHAT; | |
| 64 | + return WXPayClientConfig.class; | |
| 62 | 65 | case ALIPAY_PC: |
| 63 | 66 | case ALIPAY_WAP: |
| 64 | 67 | case ALIPAY_APP: |
| 65 | 68 | case ALIPAY_QR: |
| 66 | - return ALIPAY; | |
| 69 | + return AlipayPayClientConfig.class; | |
| 67 | 70 | } |
| 68 | 71 | return null; |
| 69 | 72 | } | ... | ... |