mirror of
				https://gitee.com/hhyykk/ipms-sjy.git
				synced 2025-10-31 02:08:43 +08:00 
			
		
		
		
	优化渠道 config 校验和逻辑转换问题
This commit is contained in:
		| @@ -80,7 +80,7 @@ public class PayMerchantController { | ||||
|     @ApiImplicitParam(name = "name", value = "商户名称", required = true, example = "芋道", dataTypeClass = Long.class) | ||||
|     @PreAuthorize("@ss.hasPermission('pay:merchant:query')") | ||||
|     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)); | ||||
|     } | ||||
|  | ||||
|   | ||||
| @@ -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.mybatis.core.mapper.BaseMapperX; | ||||
| 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 org.apache.ibatis.annotations.Mapper; | ||||
|  | ||||
| @@ -48,8 +49,6 @@ public interface PayMerchantMapper extends BaseMapperX<PayMerchantDO> { | ||||
|      * @return 商户集合 | ||||
|      */ | ||||
|     default List<PayMerchantDO> getMerchantListByName(String merchantName) { | ||||
|         // TODO @aquan:全模糊匹配,暂时不考虑索引的事;另外,可以直接 new Lambada 的 QueryWrapper 实现类呀 | ||||
|         return this.selectList(new QueryWrapper<PayMerchantDO>() | ||||
|                 .lambda().likeRight(PayMerchantDO::getName, merchantName)); | ||||
|         return this.selectList(new LambdaQueryWrapper<PayMerchantDO>().like(PayMerchantDO::getName, merchantName)); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -22,7 +22,7 @@ import org.springframework.validation.annotation.Validated; | ||||
| import javax.annotation.Resource; | ||||
| 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.util.collection.CollectionUtils.convertSet; | ||||
|  | ||||
| @@ -72,7 +72,7 @@ public class PayAppServiceImpl implements PayAppService { | ||||
|  | ||||
|     private void validateAppExists(Long id) { | ||||
|         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); | ||||
|         if (payApp == null) { | ||||
|             throw exception(APP_NOT_EXISTS); | ||||
|             throw exception(PAY_APP_NOT_FOUND); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -1,5 +1,6 @@ | ||||
| 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.PayChannelExportReqVO; | ||||
| 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.coreservice.modules.pay.dal.dataobject.merchant.PayChannelDO; | ||||
| 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.enums.PayChannelEnum; | ||||
| import com.alibaba.fastjson.JSON; | ||||
| 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.util.Assert; | ||||
| import org.springframework.validation.annotation.Validated; | ||||
|  | ||||
| import javax.annotation.Resource; | ||||
| import javax.validation.ConstraintViolation; | ||||
| import javax.validation.Validation; | ||||
| import javax.validation.Validator; | ||||
| import javax.validation.ValidatorFactory; | ||||
| import java.util.Collection; | ||||
| 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.framework.common.exception.util.ServiceExceptionUtil.exception; | ||||
| @@ -44,14 +41,15 @@ public class PayChannelServiceImpl implements PayChannelService { | ||||
|     @Resource | ||||
|     private PayChannelMapper channelMapper; | ||||
|  | ||||
|     @Resource | ||||
|     private Validator validator; | ||||
|  | ||||
|     @Override | ||||
|     public Long createChannel(PayChannelCreateReqVO reqVO) { | ||||
|         // TODO @aquan:感觉获得那一条比较合适。因为是有唯一性的。注释有错别字哈。 | ||||
|         // 判断是否有重复的有责无法新增 | ||||
|         Integer channelCount = this.getChannelCountByConditions(reqVO.getMerchantId(), reqVO.getAppId(), reqVO.getCode()); | ||||
|         if (channelCount > 0) { | ||||
|             throw exception(CHANNEL_EXIST_SAME_CHANNEL_ERROR); | ||||
|         } | ||||
|  | ||||
|         // 断言是否有重复的 | ||||
|         PayChannelDO channelDO = this.getChannelByConditions(reqVO.getMerchantId(), reqVO.getAppId(), reqVO.getCode()); | ||||
|         Assert.isNull(channelDO, CHANNEL_EXIST_SAME_CHANNEL_ERROR.getMsg()); | ||||
|  | ||||
|         // 新增渠道 | ||||
|         PayChannelDO channel = PayChannelConvert.INSTANCE.convert(reqVO); | ||||
| @@ -142,24 +140,6 @@ public class PayChannelServiceImpl implements PayChannelService { | ||||
|         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) { | ||||
|         // 得到这个渠道是微信的还是支付宝的 | ||||
|         String channelType = PayChannelEnum.verifyWechatOrAliPay(channel.getCode()); | ||||
|         Assert.notNull(channelType, CHANNEL_NOT_EXISTS.getMsg()); | ||||
|  | ||||
|         // 进行验证 | ||||
|         // TODO @阿全:Spring 可以注入 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(","))); | ||||
|  | ||||
|         Class<? extends PayClientConfig> payClass = PayChannelEnum.findByCodeGetClass(channel.getCode()); | ||||
|         Assert.notNull(payClass, CHANNEL_NOT_EXISTS.getMsg()); | ||||
|         PayClientConfig config = JSONUtil.toBean(configStr, payClass); | ||||
|         // 验证参数 | ||||
|         config.verifyParam(validator); | ||||
|         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); | ||||
|         } | ||||
|  | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -92,14 +92,6 @@ public interface PayMerchantService { | ||||
|      */ | ||||
|     List<PayMerchantDO> getMerchantListByName(String merchantName); | ||||
|  | ||||
|     // TODO aquan:暂时不用提供这样的检索。商户不多的。 | ||||
|     /** | ||||
|      * 根据商户名称模糊查询一定数量的商户集合 | ||||
|      * @param merchantName 商户名称 | ||||
|      * @return 商户集合 | ||||
|      */ | ||||
|     List<PayMerchantDO> getMerchantListByNameLimit(String merchantName); | ||||
|  | ||||
|     /** | ||||
|      * 获得指定编号的商户 Map | ||||
|      * | ||||
|   | ||||
| @@ -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.coreservice.modules.pay.dal.dataobject.merchant.PayMerchantDO; | ||||
| 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 org.springframework.stereotype.Service; | ||||
| import org.springframework.validation.annotation.Validated; | ||||
| @@ -21,7 +19,7 @@ import java.time.LocalDateTime; | ||||
| import java.util.Collection; | ||||
| 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; | ||||
| /** | ||||
|  * 支付商户信息 Service 实现类 | ||||
| @@ -64,7 +62,7 @@ public class PayMerchantServiceImpl implements PayMerchantService { | ||||
|  | ||||
|     private void validateMerchantExists(Long id) { | ||||
|         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); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 根据商户名称模糊查询一定数量的商户集合 | ||||
|      * | ||||
|      * @param merchantName 商户名称 | ||||
|      * @return 商户集合 | ||||
|      */ | ||||
|     @Override | ||||
|     public List<PayMerchantDO> getMerchantListByNameLimit(String merchantName) { | ||||
|         // TODO @aquan:mybatis 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); | ||||
|         if (merchant == null) { | ||||
|             throw exception(MERCHANT_NOT_EXISTS); | ||||
|             throw exception(PAY_MERCHANT_NOT_EXISTS); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|   | ||||
| @@ -92,7 +92,7 @@ public class PayAppServiceTest extends BaseDbUnitTest { | ||||
|         PayAppUpdateReqVO reqVO = randomPojo(PayAppUpdateReqVO.class, o -> | ||||
|                 o.setStatus((RandomUtil.randomEle(CommonStatusEnum.values()).getStatus()))); | ||||
|         // 调用, 并断言异常 | ||||
|         assertServiceException(() -> appService.updateApp(reqVO), APP_NOT_EXISTS); | ||||
|         assertServiceException(() -> appService.updateApp(reqVO), PAY_APP_NOT_FOUND); | ||||
|     } | ||||
|  | ||||
|     @Test | ||||
| @@ -116,7 +116,7 @@ public class PayAppServiceTest extends BaseDbUnitTest { | ||||
|         Long id = randomLongId(); | ||||
|  | ||||
|         // 调用, 并断言异常 | ||||
|         assertServiceException(() -> appService.deleteApp(id), APP_NOT_EXISTS); | ||||
|         assertServiceException(() -> appService.deleteApp(id), PAY_APP_NOT_FOUND); | ||||
|     } | ||||
|  | ||||
|     @Test | ||||
|   | ||||
| @@ -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(); | ||||
|     } | ||||
| } | ||||
| @@ -34,7 +34,10 @@ import static org.junit.jupiter.api.Assertions.*; | ||||
|  * | ||||
|  * @author 芋艿 | ||||
|  */ | ||||
| @Import(PayChannelServiceImpl.class) | ||||
| @Import({ | ||||
|         PayChannelServiceImpl.class, | ||||
|         PayChannelConfig.class | ||||
| }) | ||||
| public class PayChannelServiceTest extends BaseDbUnitTest { | ||||
|  | ||||
|     @Resource | ||||
| @@ -43,7 +46,6 @@ public class PayChannelServiceTest extends BaseDbUnitTest { | ||||
|     @Resource | ||||
|     private PayChannelMapper channelMapper; | ||||
|  | ||||
|  | ||||
|     @Test | ||||
|     public void testCreateWechatVersion2Channel_success() { | ||||
|         // 准备参数 | ||||
| @@ -69,8 +71,7 @@ public class PayChannelServiceTest extends BaseDbUnitTest { | ||||
|  | ||||
|     @Test | ||||
|     public void testCreateWechatVersion3Channel_success() { | ||||
|         // 准备参数 TODO @aquan:多余的空行去掉哈。例如说 74 行。 | ||||
|  | ||||
|         // 准备参数 | ||||
|         WXPayClientConfig v3Config = getV3Config(); | ||||
|         PayChannelCreateReqVO reqVO = randomPojo(PayChannelCreateReqVO.class, o -> { | ||||
|             o.setCode(PayChannelEnum.WX_PUB.getCode()); | ||||
|   | ||||
| @@ -18,7 +18,7 @@ import org.springframework.context.annotation.Import; | ||||
| import javax.annotation.Resource; | ||||
| 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.assertServiceException; | ||||
| 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); | ||||
|  | ||||
|         // 调用, 并断言异常 | ||||
|         assertServiceException(() -> merchantService.updateMerchant(reqVO), MERCHANT_NOT_EXISTS); | ||||
|         assertServiceException(() -> merchantService.updateMerchant(reqVO), PAY_MERCHANT_NOT_EXISTS); | ||||
|     } | ||||
|  | ||||
|     @Test | ||||
| @@ -103,7 +103,7 @@ public class PayMerchantServiceTest extends BaseDbUnitTest { | ||||
|         Long id = randomLongId(); | ||||
|  | ||||
|         // 调用, 并断言异常 | ||||
|         assertServiceException(() -> merchantService.deleteMerchant(id), MERCHANT_NOT_EXISTS); | ||||
|         assertServiceException(() -> merchantService.deleteMerchant(id), PAY_MERCHANT_NOT_EXISTS); | ||||
|     } | ||||
|  | ||||
|     @Test | ||||
|   | ||||
| @@ -22,7 +22,6 @@ public interface PayErrorCodeCoreConstants { | ||||
|     ErrorCode PAY_CHANNEL_IS_DISABLE = new ErrorCode(1007001001, "支付渠道已经禁用"); | ||||
|     ErrorCode PAY_CHANNEL_CLIENT_NOT_FOUND = new ErrorCode(1007001002, "支付渠道的客户端不存在"); | ||||
|     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_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不可为空"); | ||||
| @@ -49,18 +48,14 @@ public interface PayErrorCodeCoreConstants { | ||||
|     ErrorCode PAY_REFUND_CHN_ORDER_NO_IS_NULL = new ErrorCode(1007006002, "该订单的渠道订单为空"); | ||||
|     ErrorCode PAY_REFUND_POST_HANDLER_NOT_FOUND = new ErrorCode(1007006003, "未找到对应的退款后置处理类"); | ||||
|     ErrorCode PAY_REFUND_NOT_FOUND = new ErrorCode(1007006004, "支付退款单不存在"); | ||||
|     // TODO @aquan:下面还两个要合并上去哈。另外一般中英文之间要有空格。例如说, 新建一个 order 数据;这样可读性更好。 | ||||
|  | ||||
|     /** | ||||
|      * ========== 支付商户信息 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, "支付应用信息不存在"); | ||||
|  | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -1,7 +1,11 @@ | ||||
| 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 javax.validation.Validator; | ||||
|  | ||||
| /** | ||||
|  * 支付客户端的配置,本质是支付渠道的配置 | ||||
|  * 每个不同的渠道,需要不同的配置,通过子类来定义 | ||||
| @@ -13,4 +17,10 @@ import com.fasterxml.jackson.annotation.JsonTypeInfo; | ||||
| // 1. 序列化到时数据库时,增加 @class 属性。 | ||||
| // 2. 反序列化到内存对象时,通过 @class 属性,可以创建出正确的类型 | ||||
| public interface PayClientConfig { | ||||
|  | ||||
|     /** | ||||
|      * 验证配置参数是否正确 | ||||
|      * @param validator 校验对象 | ||||
|      */ | ||||
|     void verifyParam(Validator validator); | ||||
| } | ||||
|   | ||||
| @@ -2,9 +2,17 @@ package cn.iocoder.yudao.framework.pay.core.client.impl.alipay; | ||||
|  | ||||
| import cn.iocoder.yudao.framework.pay.core.client.PayClientConfig; | ||||
| 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.NotNull; | ||||
| import java.util.Set; | ||||
| import java.util.stream.Collectors; | ||||
|  | ||||
| // TODO 芋艿:参数校验 | ||||
|  | ||||
| @@ -106,4 +114,18 @@ public class AlipayPayClientConfig implements PayClientConfig { | ||||
|     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(","))); | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -1,17 +1,26 @@ | ||||
| package cn.iocoder.yudao.framework.pay.core.client.impl.wx; | ||||
|  | ||||
| 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 com.alibaba.fastjson.JSON; | ||||
| 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 java.io.FileInputStream; | ||||
| import java.io.FileNotFoundException; | ||||
| import java.util.Set; | ||||
| import java.util.stream.Collectors; | ||||
|  | ||||
| // TODO 芋艿:参数校验 | ||||
|  | ||||
| // TODO @aquan: 不要全文件格式化哈,去掉下 <p> 看着不太友好哈 | ||||
|  | ||||
| /** | ||||
|  * 微信支付的 PayClientConfig 实现类 | ||||
|  * 属性主要来自 {@link com.github.binarywang.wxpay.config.WxPayConfig} 的必要属性 | ||||
| @@ -24,13 +33,11 @@ public class WXPayClientConfig implements PayClientConfig { | ||||
|     // TODO 芋艿:V2 or V3 客户端 | ||||
|     /** | ||||
|      * API 版本 - V2 | ||||
|      * <p> | ||||
|      * https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=4_1 | ||||
|      */ | ||||
|     public static final String API_VERSION_V2 = "v2"; | ||||
|     /** | ||||
|      * API 版本 - V3 | ||||
|      * <p> | ||||
|      * https://pay.weixin.qq.com/wiki/doc/apiv3/wechatpay/wechatpay-1.shtml | ||||
|      */ | ||||
|     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; | ||||
|     /** | ||||
|      * apiclient_cert.p12 证书文件的绝对路径或者以 classpath: 开头的类路径. | ||||
| @@ -70,11 +77,9 @@ public class WXPayClientConfig implements PayClientConfig { | ||||
|     /** | ||||
|      * apiclient_key.pem 证书文件的绝对路径或者以 classpath: 开头的类路径. | ||||
|      * 对应的字符串 | ||||
|      * <p> | ||||
|      * 注意,可通过 {@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; | ||||
|     /** | ||||
|      * apiclient_cert.pem 证书文件的绝对路径或者以 classpath: 开头的类路径. | ||||
| @@ -82,21 +87,14 @@ public class WXPayClientConfig implements PayClientConfig { | ||||
|      * <p> | ||||
|      * 注意,可通过 {@link #main(String[])} 读取 | ||||
|      */ | ||||
|     @NotBlank(message = "apiclient_cert 不能为空", groups = {V3.class}) | ||||
|     @NotBlank(message = "apiclient_cert 不能为空", groups = V3.class) | ||||
|     private String privateCertContent; | ||||
|     /** | ||||
|      * apiV3 秘钥值 | ||||
|      */ | ||||
|     @NotBlank(message = "apiV3 秘钥值 不能为空", groups = {V3.class}) | ||||
|     @NotBlank(message = "apiV3 秘钥值 不能为空", groups = V3.class) | ||||
|     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版本 | ||||
| @@ -110,4 +108,26 @@ public class WXPayClientConfig implements PayClientConfig { | ||||
|     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))); | ||||
|     } | ||||
|  | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -1,6 +1,9 @@ | ||||
| package cn.iocoder.yudao.framework.pay.core.enums; | ||||
|  | ||||
| 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.Getter; | ||||
|  | ||||
| @@ -49,21 +52,21 @@ public enum PayChannelEnum { | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 判断当前渠道是那种支付方式 | ||||
|      * @param code | ||||
|      * @return | ||||
|      * 根据编码得到支付类 | ||||
|      * @param code 编码 | ||||
|      * @return 支付配置类 | ||||
|      */ | ||||
|     public static String verifyWechatOrAliPay(String code){ | ||||
|     public static Class<? extends PayClientConfig> findByCodeGetClass(String code){ | ||||
|         switch (PayChannelEnum.getByCode(code)){ | ||||
|             case WX_PUB: | ||||
|             case WX_LITE: | ||||
|             case WX_APP: | ||||
|                 return WECHAT; | ||||
|                 return WXPayClientConfig.class; | ||||
|             case ALIPAY_PC: | ||||
|             case ALIPAY_WAP: | ||||
|             case ALIPAY_APP: | ||||
|             case ALIPAY_QR: | ||||
|                 return ALIPAY; | ||||
|                 return AlipayPayClientConfig.class; | ||||
|         } | ||||
|         return null; | ||||
|     } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 aquan
					aquan