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

pull/2/head
aquan 2021-11-24 11:51:06 +08:00
parent dfde260ebb
commit 1c5544fc9d
15 changed files with 136 additions and 149 deletions

View File

@ -80,7 +80,7 @@ public class PayMerchantController {
@ApiImplicitParam(name = "name", value = "商户名称", required = true, example = "芋道", dataTypeClass = Long.class) @ApiImplicitParam(name = "name", value = "商户名称", required = true, example = "芋道", dataTypeClass = Long.class)
@PreAuthorize("@ss.hasPermission('pay:merchant:query')") @PreAuthorize("@ss.hasPermission('pay:merchant:query')")
public CommonResult<List<PayMerchantRespVO>> getMerchantListByName(@RequestParam("name") String name) { public CommonResult<List<PayMerchantRespVO>> getMerchantListByName(@RequestParam("name") String name) {
List<PayMerchantDO> merchantListDO = merchantService.getMerchantListByNameLimit(name); List<PayMerchantDO> merchantListDO = merchantService.getMerchantListByName(name);
return success(PayMerchantConvert.INSTANCE.convertList(merchantListDO)); return success(PayMerchantConvert.INSTANCE.convertList(merchantListDO));
} }

View File

@ -6,6 +6,7 @@ import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayMerch
import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
import cn.iocoder.yudao.framework.mybatis.core.query.QueryWrapperX; import cn.iocoder.yudao.framework.mybatis.core.query.QueryWrapperX;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Mapper;
@ -48,8 +49,6 @@ public interface PayMerchantMapper extends BaseMapperX<PayMerchantDO> {
* @return * @return
*/ */
default List<PayMerchantDO> getMerchantListByName(String merchantName) { default List<PayMerchantDO> getMerchantListByName(String merchantName) {
// TODO @aquan全模糊匹配暂时不考虑索引的事另外可以直接 new Lambada 的 QueryWrapper 实现类呀 return this.selectList(new LambdaQueryWrapper<PayMerchantDO>().like(PayMerchantDO::getName, merchantName));
return this.selectList(new QueryWrapper<PayMerchantDO>()
.lambda().likeRight(PayMerchantDO::getName, merchantName));
} }
} }

View File

@ -22,7 +22,7 @@ import org.springframework.validation.annotation.Validated;
import javax.annotation.Resource; import javax.annotation.Resource;
import java.util.*; import java.util.*;
import static cn.iocoder.yudao.coreservice.modules.pay.enums.PayErrorCodeCoreConstants.APP_NOT_EXISTS; import static cn.iocoder.yudao.coreservice.modules.pay.enums.PayErrorCodeCoreConstants.*;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
@ -72,7 +72,7 @@ public class PayAppServiceImpl implements PayAppService {
private void validateAppExists(Long id) { private void validateAppExists(Long id) {
if (appMapper.selectById(id) == null) { if (appMapper.selectById(id) == null) {
throw exception(APP_NOT_EXISTS); throw exception(PAY_APP_NOT_FOUND);
} }
} }
@ -148,7 +148,7 @@ public class PayAppServiceImpl implements PayAppService {
} }
PayAppDO payApp = appMapper.selectById(id); PayAppDO payApp = appMapper.selectById(id);
if (payApp == null) { if (payApp == null) {
throw exception(APP_NOT_EXISTS); throw exception(PAY_APP_NOT_FOUND);
} }
} }
} }

View File

@ -1,5 +1,6 @@
package cn.iocoder.yudao.adminserver.modules.pay.service.channel.impl; package cn.iocoder.yudao.adminserver.modules.pay.service.channel.impl;
import cn.hutool.json.JSONUtil;
import cn.iocoder.yudao.adminserver.modules.pay.controller.channel.vo.PayChannelCreateReqVO; import cn.iocoder.yudao.adminserver.modules.pay.controller.channel.vo.PayChannelCreateReqVO;
import cn.iocoder.yudao.adminserver.modules.pay.controller.channel.vo.PayChannelExportReqVO; import cn.iocoder.yudao.adminserver.modules.pay.controller.channel.vo.PayChannelExportReqVO;
import cn.iocoder.yudao.adminserver.modules.pay.controller.channel.vo.PayChannelPageReqVO; 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
import cn.iocoder.yudao.adminserver.modules.pay.service.channel.PayChannelService; import cn.iocoder.yudao.adminserver.modules.pay.service.channel.PayChannelService;
import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayChannelDO; import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayChannelDO;
import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.pay.core.client.impl.alipay.AlipayPayClientConfig; import cn.iocoder.yudao.framework.pay.core.client.PayClientConfig;
import cn.iocoder.yudao.framework.pay.core.client.impl.wx.WXPayClientConfig; import cn.iocoder.yudao.framework.pay.core.client.impl.wx.WXPayClientConfig;
import cn.iocoder.yudao.framework.pay.core.enums.PayChannelEnum; import cn.iocoder.yudao.framework.pay.core.enums.PayChannelEnum;
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.util.Assert; import org.springframework.util.Assert;
import org.springframework.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
import javax.annotation.Resource; import javax.annotation.Resource;
import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.Validator; import javax.validation.Validator;
import javax.validation.ValidatorFactory;
import java.util.Collection; import java.util.Collection;
import java.util.List; import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import static cn.iocoder.yudao.coreservice.modules.pay.enums.PayErrorCodeCoreConstants.*; import static cn.iocoder.yudao.coreservice.modules.pay.enums.PayErrorCodeCoreConstants.*;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
@ -44,14 +41,15 @@ public class PayChannelServiceImpl implements PayChannelService {
@Resource @Resource
private PayChannelMapper channelMapper; private PayChannelMapper channelMapper;
@Resource
private Validator validator;
@Override @Override
public Long createChannel(PayChannelCreateReqVO reqVO) { public Long createChannel(PayChannelCreateReqVO reqVO) {
// TODO @aquan感觉获得那一条比较合适。因为是有唯一性的。注释有错别字哈。
// 判断是否有重复的有责无法新增 // 断言是否有重复的
Integer channelCount = this.getChannelCountByConditions(reqVO.getMerchantId(), reqVO.getAppId(), reqVO.getCode()); PayChannelDO channelDO = this.getChannelByConditions(reqVO.getMerchantId(), reqVO.getAppId(), reqVO.getCode());
if (channelCount > 0) { Assert.isNull(channelDO, CHANNEL_EXIST_SAME_CHANNEL_ERROR.getMsg());
throw exception(CHANNEL_EXIST_SAME_CHANNEL_ERROR);
}
// 新增渠道 // 新增渠道
PayChannelDO channel = PayChannelConvert.INSTANCE.convert(reqVO); PayChannelDO channel = PayChannelConvert.INSTANCE.convert(reqVO);
@ -142,24 +140,6 @@ public class PayChannelServiceImpl implements PayChannelService {
return this.channelMapper.getChannelByConditions(merchantId, appid, code); return this.channelMapper.getChannelByConditions(merchantId, appid, code);
} }
/**
*
*
* @param config
*/
private void wechatParamCheck(WXPayClientConfig config) {
// 针对于 V2 或者 V3 版本的参数校验
if (WXPayClientConfig.API_VERSION_V2.equals(config.getApiVersion())) {
Assert.notNull(config.getMchKey(), CHANNEL_WECHAT_VERSION_2_MCH_KEY_IS_NULL.getMsg());
}
if (WXPayClientConfig.API_VERSION_V3.equals(config.getApiVersion())) {
Assert.notNull(config.getPrivateKeyContent(), CHANNEL_WECHAT_VERSION_3_PRIVATE_KEY_IS_NULL.getMsg());
Assert.notNull(config.getPrivateCertContent(), CHANNEL_WECHAT_VERSION_3_CERT_KEY_IS_NULL.getMsg());
}
}
/** /**
* *
* *
@ -168,48 +148,11 @@ public class PayChannelServiceImpl implements PayChannelService {
*/ */
private void settingConfigAndCheckParam(PayChannelDO channel, String configStr) { private void settingConfigAndCheckParam(PayChannelDO channel, String configStr) {
// 得到这个渠道是微信的还是支付宝的 // 得到这个渠道是微信的还是支付宝的
String channelType = PayChannelEnum.verifyWechatOrAliPay(channel.getCode()); Class<? extends PayClientConfig> payClass = PayChannelEnum.findByCodeGetClass(channel.getCode());
Assert.notNull(channelType, CHANNEL_NOT_EXISTS.getMsg()); Assert.notNull(payClass, CHANNEL_NOT_EXISTS.getMsg());
PayClientConfig config = JSONUtil.toBean(configStr, payClass);
// 进行验证 // 验证参数
// TODO @阿全Spring 可以注入 Validator 哈 config.verifyParam(validator);
ValidatorFactory validatorFactory = Validation.buildDefaultValidatorFactory();
Validator validator = validatorFactory.getValidator();
// 微信的验证
// TODO @aquan这么实现可扩性不好。@AssertTrue 注解。
if (PayChannelEnum.WECHAT.equals(channelType)) {
WXPayClientConfig config = JSON.parseObject(configStr, WXPayClientConfig.class);
// 判断是V2 版本还是 V3 版本
Class clazz = config.getApiVersion().equals(WXPayClientConfig.API_VERSION_V2)
? WXPayClientConfig.V2.class : WXPayClientConfig.V3.class;
// 手动调用validate进行验证
Set<ConstraintViolation<WXPayClientConfig>> validate = validator.validate(config,clazz);
// 断言没有异常
Assert.isTrue(validate.isEmpty(), validate.stream().map(ConstraintViolation::getMessage)
.collect(Collectors.joining(",")));
channel.setConfig(config); channel.setConfig(config);
} }
// 支付宝验证
if (PayChannelEnum.ALIPAY.equals(channelType)) {
AlipayPayClientConfig config = JSON.parseObject(configStr, AlipayPayClientConfig.class);
// 判断是V2 版本还是 V3 版本
Class clazz = config.getMode().equals(AlipayPayClientConfig.MODE_PUBLIC_KEY)
? AlipayPayClientConfig.ModePublicKey.class : AlipayPayClientConfig.ModeCertificate.class;
// 手动调用validate进行验证
Set<ConstraintViolation<AlipayPayClientConfig>> validate = validator.validate(config,clazz);
// 断言没有异常
Assert.isTrue(validate.isEmpty(), validate.stream().map(ConstraintViolation::getMessage)
.collect(Collectors.joining(",")));
channel.setConfig(config);
}
}
} }

View File

@ -92,14 +92,6 @@ public interface PayMerchantService {
*/ */
List<PayMerchantDO> getMerchantListByName(String merchantName); List<PayMerchantDO> getMerchantListByName(String merchantName);
// TODO aquan暂时不用提供这样的检索。商户不多的。
/**
*
* @param merchantName
* @return
*/
List<PayMerchantDO> getMerchantListByNameLimit(String merchantName);
/** /**
* Map * Map
* *

View File

@ -10,8 +10,6 @@ import cn.iocoder.yudao.adminserver.modules.pay.dal.mysql.merchant.PayMerchantMa
import cn.iocoder.yudao.adminserver.modules.pay.service.merchant.PayMerchantService; import cn.iocoder.yudao.adminserver.modules.pay.service.merchant.PayMerchantService;
import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayMerchantDO; import cn.iocoder.yudao.coreservice.modules.pay.dal.dataobject.merchant.PayMerchantDO;
import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.pojo.PageResult;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.google.common.annotations.VisibleForTesting; import com.google.common.annotations.VisibleForTesting;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
@ -21,7 +19,7 @@ import java.time.LocalDateTime;
import java.util.Collection; import java.util.Collection;
import java.util.List; import java.util.List;
import static cn.iocoder.yudao.coreservice.modules.pay.enums.PayErrorCodeCoreConstants.MERCHANT_NOT_EXISTS; import static cn.iocoder.yudao.coreservice.modules.pay.enums.PayErrorCodeCoreConstants.PAY_MERCHANT_NOT_EXISTS;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
/** /**
* Service * Service
@ -64,7 +62,7 @@ public class PayMerchantServiceImpl implements PayMerchantService {
private void validateMerchantExists(Long id) { private void validateMerchantExists(Long id) {
if (merchantMapper.selectById(id) == null) { if (merchantMapper.selectById(id) == null) {
throw exception(MERCHANT_NOT_EXISTS); throw exception(PAY_MERCHANT_NOT_EXISTS);
} }
} }
@ -116,22 +114,6 @@ public class PayMerchantServiceImpl implements PayMerchantService {
return this.merchantMapper.getMerchantListByName(merchantName); return this.merchantMapper.getMerchantListByName(merchantName);
} }
/**
*
*
* @param merchantName
* @return
*/
@Override
public List<PayMerchantDO> getMerchantListByNameLimit(String merchantName) {
// TODO @aquanmybatis plus 哈
LambdaQueryWrapper<PayMerchantDO> queryWrapper = new QueryWrapper<PayMerchantDO>().lambda()
.select(PayMerchantDO::getId, PayMerchantDO::getName)
.likeRight(PayMerchantDO::getName, merchantName)
.last("limit 200");
return this.merchantMapper.selectList(queryWrapper);
}
/** /**
* *
@ -144,7 +126,7 @@ public class PayMerchantServiceImpl implements PayMerchantService {
} }
PayMerchantDO merchant = merchantMapper.selectById(id); PayMerchantDO merchant = merchantMapper.selectById(id);
if (merchant == null) { if (merchant == null) {
throw exception(MERCHANT_NOT_EXISTS); throw exception(PAY_MERCHANT_NOT_EXISTS);
} }
} }

View File

@ -92,7 +92,7 @@ public class PayAppServiceTest extends BaseDbUnitTest {
PayAppUpdateReqVO reqVO = randomPojo(PayAppUpdateReqVO.class, o -> PayAppUpdateReqVO reqVO = randomPojo(PayAppUpdateReqVO.class, o ->
o.setStatus((RandomUtil.randomEle(CommonStatusEnum.values()).getStatus()))); o.setStatus((RandomUtil.randomEle(CommonStatusEnum.values()).getStatus())));
// 调用, 并断言异常 // 调用, 并断言异常
assertServiceException(() -> appService.updateApp(reqVO), APP_NOT_EXISTS); assertServiceException(() -> appService.updateApp(reqVO), PAY_APP_NOT_FOUND);
} }
@Test @Test
@ -116,7 +116,7 @@ public class PayAppServiceTest extends BaseDbUnitTest {
Long id = randomLongId(); Long id = randomLongId();
// 调用, 并断言异常 // 调用, 并断言异常
assertServiceException(() -> appService.deleteApp(id), APP_NOT_EXISTS); assertServiceException(() -> appService.deleteApp(id), PAY_APP_NOT_FOUND);
} }
@Test @Test

View File

@ -0,0 +1,20 @@
package cn.iocoder.yudao.adminserver.modules.pay.service.channel;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import javax.validation.Validation;
import javax.validation.Validator;
/**
* validator Bean
* @author aquan
*/
@Configuration
public class PayChannelConfig {
@Bean
public Validator validator(){
return Validation.buildDefaultValidatorFactory().getValidator();
}
}

View File

@ -34,7 +34,10 @@ import static org.junit.jupiter.api.Assertions.*;
* *
* @author * @author
*/ */
@Import(PayChannelServiceImpl.class) @Import({
PayChannelServiceImpl.class,
PayChannelConfig.class
})
public class PayChannelServiceTest extends BaseDbUnitTest { public class PayChannelServiceTest extends BaseDbUnitTest {
@Resource @Resource
@ -43,7 +46,6 @@ public class PayChannelServiceTest extends BaseDbUnitTest {
@Resource @Resource
private PayChannelMapper channelMapper; private PayChannelMapper channelMapper;
@Test @Test
public void testCreateWechatVersion2Channel_success() { public void testCreateWechatVersion2Channel_success() {
// 准备参数 // 准备参数
@ -69,8 +71,7 @@ public class PayChannelServiceTest extends BaseDbUnitTest {
@Test @Test
public void testCreateWechatVersion3Channel_success() { public void testCreateWechatVersion3Channel_success() {
// 准备参数 TODO @aquan多余的空行去掉哈。例如说 74 行。 // 准备参数
WXPayClientConfig v3Config = getV3Config(); WXPayClientConfig v3Config = getV3Config();
PayChannelCreateReqVO reqVO = randomPojo(PayChannelCreateReqVO.class, o -> { PayChannelCreateReqVO reqVO = randomPojo(PayChannelCreateReqVO.class, o -> {
o.setCode(PayChannelEnum.WX_PUB.getCode()); o.setCode(PayChannelEnum.WX_PUB.getCode());

View File

@ -18,7 +18,7 @@ import org.springframework.context.annotation.Import;
import javax.annotation.Resource; import javax.annotation.Resource;
import java.util.List; import java.util.List;
import static cn.iocoder.yudao.coreservice.modules.pay.enums.PayErrorCodeCoreConstants.MERCHANT_NOT_EXISTS; import static cn.iocoder.yudao.coreservice.modules.pay.enums.PayErrorCodeCoreConstants.PAY_MERCHANT_NOT_EXISTS;
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals;
import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException; import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException;
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.buildTime; import static cn.iocoder.yudao.framework.common.util.date.DateUtils.buildTime;
@ -79,7 +79,7 @@ public class PayMerchantServiceTest extends BaseDbUnitTest {
PayMerchantUpdateReqVO reqVO = randomPojo(PayMerchantUpdateReqVO.class); PayMerchantUpdateReqVO reqVO = randomPojo(PayMerchantUpdateReqVO.class);
// 调用, 并断言异常 // 调用, 并断言异常
assertServiceException(() -> merchantService.updateMerchant(reqVO), MERCHANT_NOT_EXISTS); assertServiceException(() -> merchantService.updateMerchant(reqVO), PAY_MERCHANT_NOT_EXISTS);
} }
@Test @Test
@ -103,7 +103,7 @@ public class PayMerchantServiceTest extends BaseDbUnitTest {
Long id = randomLongId(); Long id = randomLongId();
// 调用, 并断言异常 // 调用, 并断言异常
assertServiceException(() -> merchantService.deleteMerchant(id), MERCHANT_NOT_EXISTS); assertServiceException(() -> merchantService.deleteMerchant(id), PAY_MERCHANT_NOT_EXISTS);
} }
@Test @Test

View File

@ -22,7 +22,6 @@ public interface PayErrorCodeCoreConstants {
ErrorCode PAY_CHANNEL_IS_DISABLE = new ErrorCode(1007001001, "支付渠道已经禁用"); ErrorCode PAY_CHANNEL_IS_DISABLE = new ErrorCode(1007001001, "支付渠道已经禁用");
ErrorCode PAY_CHANNEL_CLIENT_NOT_FOUND = new ErrorCode(1007001002, "支付渠道的客户端不存在"); ErrorCode PAY_CHANNEL_CLIENT_NOT_FOUND = new ErrorCode(1007001002, "支付渠道的客户端不存在");
ErrorCode CHANNEL_NOT_EXISTS = new ErrorCode(1007001003, "支付渠道不存在"); ErrorCode CHANNEL_NOT_EXISTS = new ErrorCode(1007001003, "支付渠道不存在");
ErrorCode CHANNEL_KEY_READ_ERROR = new ErrorCode(1007001004, "支付渠道秘钥文件读取失败");
ErrorCode CHANNEL_EXIST_SAME_CHANNEL_ERROR = new ErrorCode(1007001005, "已存在相同的渠道"); ErrorCode CHANNEL_EXIST_SAME_CHANNEL_ERROR = new ErrorCode(1007001005, "已存在相同的渠道");
ErrorCode CHANNEL_WECHAT_VERSION_2_MCH_KEY_IS_NULL = new ErrorCode(1007001006,"微信渠道v2版本中商户密钥不可为空"); ErrorCode CHANNEL_WECHAT_VERSION_2_MCH_KEY_IS_NULL = new ErrorCode(1007001006,"微信渠道v2版本中商户密钥不可为空");
ErrorCode CHANNEL_WECHAT_VERSION_3_PRIVATE_KEY_IS_NULL = new ErrorCode(1007001006,"微信渠道v3版本apiclient_key.pem不可为空"); ErrorCode CHANNEL_WECHAT_VERSION_3_PRIVATE_KEY_IS_NULL = new ErrorCode(1007001006,"微信渠道v3版本apiclient_key.pem不可为空");
@ -49,18 +48,14 @@ public interface PayErrorCodeCoreConstants {
ErrorCode PAY_REFUND_CHN_ORDER_NO_IS_NULL = new ErrorCode(1007006002, "该订单的渠道订单为空"); ErrorCode PAY_REFUND_CHN_ORDER_NO_IS_NULL = new ErrorCode(1007006002, "该订单的渠道订单为空");
ErrorCode PAY_REFUND_POST_HANDLER_NOT_FOUND = new ErrorCode(1007006003, "未找到对应的退款后置处理类"); ErrorCode PAY_REFUND_POST_HANDLER_NOT_FOUND = new ErrorCode(1007006003, "未找到对应的退款后置处理类");
ErrorCode PAY_REFUND_NOT_FOUND = new ErrorCode(1007006004, "支付退款单不存在"); ErrorCode PAY_REFUND_NOT_FOUND = new ErrorCode(1007006004, "支付退款单不存在");
// TODO @aquan下面还两个要合并上去哈。另外一般中英文之间要有空格。例如说 新建一个 order 数据;这样可读性更好。
/** /**
* ========== 1-007-004-000 ========== * ========== 1-007-004-000 ==========
*/ */
ErrorCode MERCHANT_NOT_EXISTS = new ErrorCode(1007004000, "支付商户信息不存在"); ErrorCode PAY_MERCHANT_NOT_EXISTS = new ErrorCode(1007004000, "支付商户信息不存在");
/**
* ========== 1-007-005-000 ==========
*/
ErrorCode APP_NOT_EXISTS = new ErrorCode(1007005000, "支付应用信息不存在");
} }

View File

@ -1,7 +1,11 @@
package cn.iocoder.yudao.framework.pay.core.client; package cn.iocoder.yudao.framework.pay.core.client;
import cn.hutool.json.JSONUtil;
import cn.iocoder.yudao.framework.pay.core.enums.PayChannelEnum;
import com.fasterxml.jackson.annotation.JsonTypeInfo; import com.fasterxml.jackson.annotation.JsonTypeInfo;
import javax.validation.Validator;
/** /**
* *
* *
@ -13,4 +17,10 @@ import com.fasterxml.jackson.annotation.JsonTypeInfo;
// 1. 序列化到时数据库时,增加 @class 属性。 // 1. 序列化到时数据库时,增加 @class 属性。
// 2. 反序列化到内存对象时,通过 @class 属性,可以创建出正确的类型 // 2. 反序列化到内存对象时,通过 @class 属性,可以创建出正确的类型
public interface PayClientConfig { public interface PayClientConfig {
/**
*
* @param validator
*/
void verifyParam(Validator validator);
} }

View File

@ -2,9 +2,17 @@ package cn.iocoder.yudao.framework.pay.core.client.impl.alipay;
import cn.iocoder.yudao.framework.pay.core.client.PayClientConfig; import cn.iocoder.yudao.framework.pay.core.client.PayClientConfig;
import lombok.Data; import lombok.Data;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.Assert;
import javax.annotation.Resource;
import javax.validation.ConstraintViolation;
import javax.validation.Validator;
import javax.validation.constraints.AssertTrue;
import javax.validation.constraints.NotBlank; import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull; import javax.validation.constraints.NotNull;
import java.util.Set;
import java.util.stream.Collectors;
// TODO 芋艿:参数校验 // TODO 芋艿:参数校验
@ -106,4 +114,18 @@ public class AlipayPayClientConfig implements PayClientConfig {
public interface ModeCertificate { public interface ModeCertificate {
} }
/**
*
* @param validator
*/
@Override
public void verifyParam(Validator validator) {
// 手动调用validate进行验证
Set<ConstraintViolation<AlipayPayClientConfig>> validate = validator.validate(this,
MODE_PUBLIC_KEY.equals(this.getMode()) ? ModePublicKey.class : ModeCertificate.class);
// 断言没有异常
Assert.isTrue(validate.isEmpty(), validate.stream().map(ConstraintViolation::getMessage)
.collect(Collectors.joining(",")));
}
} }

View File

@ -1,17 +1,26 @@
package cn.iocoder.yudao.framework.pay.core.client.impl.wx; package cn.iocoder.yudao.framework.pay.core.client.impl.wx;
import cn.hutool.core.io.IoUtil; import cn.hutool.core.io.IoUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import cn.iocoder.yudao.framework.pay.core.client.PayClientConfig; import cn.iocoder.yudao.framework.pay.core.client.PayClientConfig;
import com.alibaba.fastjson.JSON;
import lombok.Data; import lombok.Data;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.Assert;
import javax.annotation.Resource;
import javax.validation.ConstraintViolation;
import javax.validation.Validator;
import javax.validation.constraints.AssertTrue;
import javax.validation.constraints.NotBlank; import javax.validation.constraints.NotBlank;
import java.io.FileInputStream; import java.io.FileInputStream;
import java.io.FileNotFoundException; import java.io.FileNotFoundException;
import java.util.Set;
import java.util.stream.Collectors;
// TODO 芋艿:参数校验 // TODO 芋艿:参数校验
// TODO @aquan: 不要全文件格式化哈,去掉下 <p> 看着不太友好哈
/** /**
* PayClientConfig * PayClientConfig
* {@link com.github.binarywang.wxpay.config.WxPayConfig} * {@link com.github.binarywang.wxpay.config.WxPayConfig}
@ -24,13 +33,11 @@ public class WXPayClientConfig implements PayClientConfig {
// TODO 芋艿V2 or V3 客户端 // TODO 芋艿V2 or V3 客户端
/** /**
* API - V2 * API - V2
* <p>
* https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=4_1 * https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=4_1
*/ */
public static final String API_VERSION_V2 = "v2"; public static final String API_VERSION_V2 = "v2";
/** /**
* API - V3 * API - V3
* <p>
* https://pay.weixin.qq.com/wiki/doc/apiv3/wechatpay/wechatpay-1.shtml * https://pay.weixin.qq.com/wiki/doc/apiv3/wechatpay/wechatpay-1.shtml
*/ */
public static final String API_VERSION_V3 = "v3"; public static final String API_VERSION_V3 = "v3";
@ -56,7 +63,7 @@ public class WXPayClientConfig implements PayClientConfig {
/** /**
* *
*/ */
@NotBlank(message = "商户密钥 不能为空", groups = {V2.class}) @NotBlank(message = "商户密钥 不能为空", groups = V2.class)
private String mchKey; private String mchKey;
/** /**
* apiclient_cert.p12 classpath: . * apiclient_cert.p12 classpath: .
@ -70,11 +77,9 @@ public class WXPayClientConfig implements PayClientConfig {
/** /**
* apiclient_key.pem classpath: . * apiclient_key.pem classpath: .
* *
* <p>
* {@link #main(String[])} * {@link #main(String[])}
*/ */
// TODO @aquan对于只有一个值的时候直接 groups = V3.class 即可,简洁。例如说,我们在 Spring MVC 注解url 可以多个,也只写单个,一个道理哈 @NotBlank(message = "apiclient_key 不能为空", groups = V3.class)
@NotBlank(message = "apiclient_key 不能为空", groups = {V3.class})
private String privateKeyContent; private String privateKeyContent;
/** /**
* apiclient_cert.pem classpath: . * apiclient_cert.pem classpath: .
@ -82,21 +87,14 @@ public class WXPayClientConfig implements PayClientConfig {
* <p> * <p>
* {@link #main(String[])} * {@link #main(String[])}
*/ */
@NotBlank(message = "apiclient_cert 不能为空", groups = {V3.class}) @NotBlank(message = "apiclient_cert 不能为空", groups = V3.class)
private String privateCertContent; private String privateCertContent;
/** /**
* apiV3 * apiV3
*/ */
@NotBlank(message = "apiV3 秘钥值 不能为空", groups = {V3.class}) @NotBlank(message = "apiV3 秘钥值 不能为空", groups = V3.class)
private String apiV3Key; private String apiV3Key;
public static void main(String[] args) throws FileNotFoundException {
String path = "/Users/yunai/Downloads/wx_pay/apiclient_cert.p12";
// String path = "/Users/yunai/Downloads/wx_pay/apiclient_key.pem";
// String path = "/Users/yunai/Downloads/wx_pay/apiclient_cert.pem";
System.out.println(IoUtil.readUtf8(new FileInputStream(path)));
}
/** /**
* v2 * v2
@ -110,4 +108,26 @@ public class WXPayClientConfig implements PayClientConfig {
public interface V3 { public interface V3 {
} }
/**
*
* @param validator
*/
@Override
public void verifyParam(Validator validator) {
// 手动调用validate进行验证
Set<ConstraintViolation<PayClientConfig>> validate = validator.validate(this,
this.getApiVersion().equals(API_VERSION_V2) ? V2.class : V3.class);
// 断言没有异常
Assert.isTrue(validate.isEmpty(), validate.stream().map(ConstraintViolation::getMessage)
.collect(Collectors.joining(",")));
}
public static void main(String[] args) throws FileNotFoundException {
String path = "/Users/yunai/Downloads/wx_pay/apiclient_cert.p12";
/// String path = "/Users/yunai/Downloads/wx_pay/apiclient_key.pem";
/// String path = "/Users/yunai/Downloads/wx_pay/apiclient_cert.pem";
System.out.println(IoUtil.readUtf8(new FileInputStream(path)));
}
} }

View File

@ -1,6 +1,9 @@
package cn.iocoder.yudao.framework.pay.core.enums; package cn.iocoder.yudao.framework.pay.core.enums;
import cn.hutool.core.util.ArrayUtil; import cn.hutool.core.util.ArrayUtil;
import cn.iocoder.yudao.framework.pay.core.client.PayClientConfig;
import cn.iocoder.yudao.framework.pay.core.client.impl.alipay.AlipayPayClientConfig;
import cn.iocoder.yudao.framework.pay.core.client.impl.wx.WXPayClientConfig;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.Getter; import lombok.Getter;
@ -49,21 +52,21 @@ public enum PayChannelEnum {
} }
/** /**
* *
* @param code * @param code
* @return * @return
*/ */
public static String verifyWechatOrAliPay(String code){ public static Class<? extends PayClientConfig> findByCodeGetClass(String code){
switch (PayChannelEnum.getByCode(code)){ switch (PayChannelEnum.getByCode(code)){
case WX_PUB: case WX_PUB:
case WX_LITE: case WX_LITE:
case WX_APP: case WX_APP:
return WECHAT; return WXPayClientConfig.class;
case ALIPAY_PC: case ALIPAY_PC:
case ALIPAY_WAP: case ALIPAY_WAP:
case ALIPAY_APP: case ALIPAY_APP:
case ALIPAY_QR: case ALIPAY_QR:
return ALIPAY; return AlipayPayClientConfig.class;
} }
return null; return null;
} }