mirror of
				https://gitee.com/hhyykk/ipms-sjy.git
				synced 2025-11-01 02:38:43 +08:00 
			
		
		
		
	【功能优化】支付:支付应用,增加 appKey 标识,用于不同接入方的标识
This commit is contained in:
		| @@ -14,6 +14,10 @@ import jakarta.validation.constraints.*; | ||||
| @Data | ||||
| public class PayAppBaseVO { | ||||
|  | ||||
|     @Schema(description = "应用标识", requiredMode = Schema.RequiredMode.REQUIRED, example = "yudao") | ||||
|     @NotEmpty(message = "应用标识不能为空") | ||||
|     private String appKey; | ||||
|  | ||||
|     @Schema(description = "应用名", requiredMode = Schema.RequiredMode.REQUIRED, example = "小豆") | ||||
|     @NotNull(message = "应用名不能为空") | ||||
|     private String name; | ||||
|   | ||||
| @@ -1,7 +1,9 @@ | ||||
| package cn.iocoder.yudao.module.pay.controller.admin.app.vo; | ||||
|  | ||||
| import io.swagger.v3.oas.annotations.media.Schema; | ||||
| import jakarta.validation.constraints.NotNull; | ||||
| import lombok.*; | ||||
| import lombok.Data; | ||||
| import lombok.EqualsAndHashCode; | ||||
| import lombok.ToString; | ||||
|  | ||||
| @Schema(description = "管理后台 - 支付应用信息创建 Request VO") | ||||
| @Data | ||||
| @@ -9,8 +11,4 @@ import lombok.*; | ||||
| @ToString(callSuper = true) | ||||
| public class PayAppCreateReqVO extends PayAppBaseVO { | ||||
|  | ||||
|     @Schema(description = "应用标识", requiredMode = Schema.RequiredMode.REQUIRED, example = "yudao") | ||||
|     @NotNull(message = "应用标识不能为空") | ||||
|     private String appKey; | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -17,9 +17,6 @@ public class PayAppPageItemRespVO extends PayAppBaseVO { | ||||
|     @Schema(description = "应用编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") | ||||
|     private Long id; | ||||
|  | ||||
|     @Schema(description = "应用标识", requiredMode = Schema.RequiredMode.REQUIRED, example = "yudao") | ||||
|     private String appKey; | ||||
|  | ||||
|     @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) | ||||
|     private LocalDateTime createTime; | ||||
|  | ||||
|   | ||||
| @@ -20,7 +20,7 @@ public class PayAppPageReqVO extends PageParam { | ||||
|     @Schema(description = "应用名", example = "小豆") | ||||
|     private String name; | ||||
|  | ||||
|     @Schema(description = "应用标识", requiredMode = Schema.RequiredMode.REQUIRED, example = "yudao") | ||||
|     @Schema(description = "应用标识", example = "yudao") | ||||
|     private String appKey; | ||||
|  | ||||
|     @Schema(description = "开启状态", example = "0") | ||||
|   | ||||
| @@ -14,8 +14,4 @@ public class PayAppUpdateReqVO extends PayAppBaseVO { | ||||
|     @NotNull(message = "应用编号不能为空") | ||||
|     private Long id; | ||||
|  | ||||
|     @Schema(description = "应用标识", requiredMode = Schema.RequiredMode.REQUIRED, example = "yudao") | ||||
|     @NotNull(message = "应用标识不能为空") | ||||
|     private String appKey; | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -15,6 +15,8 @@ public class PayProperties { | ||||
|     private static final String ORDER_NO_PREFIX = "P"; | ||||
|     private static final String REFUND_NO_PREFIX = "R"; | ||||
|  | ||||
|     private static final String WALLET_PAY_APP_KEY_DEFAULT = "wallet"; | ||||
|  | ||||
|     /** | ||||
|      * 支付回调地址 | ||||
|      * | ||||
| @@ -49,4 +51,10 @@ public class PayProperties { | ||||
|     @NotEmpty(message = "退款订单 no 的前缀不能为空") | ||||
|     private String refundNoPrefix = REFUND_NO_PREFIX; | ||||
|  | ||||
|     /** | ||||
|      * 钱包支付应用 AppKey | ||||
|      */ | ||||
|     @NotEmpty(message = "钱包支付应用 AppKey 不能为空") | ||||
|     private String walletPayAppKey = WALLET_PAY_APP_KEY_DEFAULT; | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -1,9 +1,7 @@ | ||||
| package cn.iocoder.yudao.module.pay.service.app; | ||||
|  | ||||
| import cn.hutool.core.util.StrUtil; | ||||
| import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; | ||||
| import cn.iocoder.yudao.framework.common.pojo.PageResult; | ||||
| import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; | ||||
| import cn.iocoder.yudao.module.pay.controller.admin.app.vo.PayAppCreateReqVO; | ||||
| import cn.iocoder.yudao.module.pay.controller.admin.app.vo.PayAppPageReqVO; | ||||
| import cn.iocoder.yudao.module.pay.controller.admin.app.vo.PayAppUpdateReqVO; | ||||
| @@ -20,7 +18,6 @@ import org.springframework.validation.annotation.Validated; | ||||
|  | ||||
| import java.util.Collection; | ||||
| import java.util.List; | ||||
| import java.util.Objects; | ||||
|  | ||||
| import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; | ||||
| import static cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants.*; | ||||
| @@ -46,8 +43,9 @@ public class PayAppServiceImpl implements PayAppService { | ||||
|  | ||||
|     @Override | ||||
|     public Long createApp(PayAppCreateReqVO createReqVO) { | ||||
|         // 验证appKey是否重复 | ||||
|         validateAppKeyDuplicate(null, createReqVO.getAppKey()); | ||||
|         // 验证 appKey 是否重复 | ||||
|         validateEmailUnique(null, createReqVO.getAppKey()); | ||||
|  | ||||
|         // 插入 | ||||
|         PayAppDO app = PayAppConvert.INSTANCE.convert(createReqVO); | ||||
|         appMapper.insert(app); | ||||
| @@ -59,13 +57,28 @@ public class PayAppServiceImpl implements PayAppService { | ||||
|     public void updateApp(PayAppUpdateReqVO updateReqVO) { | ||||
|         // 校验存在 | ||||
|         validateAppExists(updateReqVO.getId()); | ||||
|         // 验证appKey是否重复 | ||||
|         validateAppKeyDuplicate(updateReqVO.getId(), updateReqVO.getAppKey()); | ||||
|         // 验证 appKey 是否重复 | ||||
|         validateEmailUnique(updateReqVO.getId(), updateReqVO.getAppKey()); | ||||
|  | ||||
|         // 更新 | ||||
|         PayAppDO updateObj = PayAppConvert.INSTANCE.convert(updateReqVO); | ||||
|         appMapper.updateById(updateObj); | ||||
|     } | ||||
|  | ||||
|     void validateEmailUnique(Long id, String appKey) { | ||||
|         PayAppDO app = appMapper.selectByAppKey(appKey); | ||||
|         if (app == null) { | ||||
|             return; | ||||
|         } | ||||
|         // 如果 id 为空,说明不用比较是否为相同 appKey 的应用 | ||||
|         if (id == null) { | ||||
|             throw exception(APP_KEY_EXISTS); | ||||
|         } | ||||
|         if (!app.getId().equals(id)) { | ||||
|             throw exception(APP_KEY_EXISTS); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public void updateAppStatus(Long id, Integer status) { | ||||
|         // 校验商户存在 | ||||
| @@ -119,63 +132,31 @@ public class PayAppServiceImpl implements PayAppService { | ||||
|     @Override | ||||
|     public PayAppDO validPayApp(Long appId) { | ||||
|         PayAppDO app = appMapper.selectById(appId); | ||||
|         // 校验支付应用数据是否存在以及可用 | ||||
|         return validatePayAppDO(app); | ||||
|         return validatePayApp(app); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public PayAppDO validPayApp(String appKey) { | ||||
|         PayAppDO app = appMapper.selectByAppKey(appKey); | ||||
|         // 校验支付应用数据是否存在以及可用 | ||||
|         return validatePayAppDO(app); | ||||
|         return validatePayApp(app); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * 校验支付应用实体的有效性 | ||||
|      * 主要包括存在性检查和禁用状态检查 | ||||
|      * 校验支付应用实体的有效性:存在 + 开启 | ||||
|      * | ||||
|      * @param app 待校验的支付应用实体 | ||||
|      * @return 校验通过的支付应用实体 | ||||
|      * @throws IllegalArgumentException 如果支付应用实体不存在或已被禁用 | ||||
|      */ | ||||
|     private PayAppDO validatePayAppDO(PayAppDO app) { | ||||
|     private PayAppDO validatePayApp(PayAppDO app) { | ||||
|         // 校验是否存在 | ||||
|         if (app == null) { | ||||
|             throw exception(ErrorCodeConstants.APP_NOT_FOUND); | ||||
|         } | ||||
|         // 校验是否禁用 | ||||
|         if (CommonStatusEnum.DISABLE.getStatus().equals(app.getStatus())) { | ||||
|         if (CommonStatusEnum.isDisable(app.getStatus())) { | ||||
|             throw exception(ErrorCodeConstants.APP_IS_DISABLE); | ||||
|         } | ||||
|         return app; | ||||
|     } | ||||
|  | ||||
|  | ||||
|     /** | ||||
|      * 校验应用密钥是否重复 | ||||
|      * 在新增或更新支付应用时,确保应用密钥(appKey)的唯一性 | ||||
|      * 如果是在新增情况下,检查数据库中是否已存在相同的appKey | ||||
|      * 如果是在更新情况下,检查数据库中是否存在除当前应用外的其他应用使用了相同的appKey | ||||
|      * | ||||
|      * @param payAppId  支付应用的ID,更新时使用,新增时可能为null | ||||
|      * @param payAppKey 支付应用的密钥,用于校验是否重复 | ||||
|      * @throws RuntimeException 如果发现appKey重复,抛出运行时异常 | ||||
|      */ | ||||
|     private void validateAppKeyDuplicate(Long payAppId, String payAppKey) { | ||||
|         // 新增时,校验appKey是否重复 | ||||
|         if (Objects.isNull(payAppId) && StrUtil.isNotBlank(payAppKey)) { | ||||
|             if (appMapper.selectCount(PayAppDO::getAppKey, payAppKey) > 0) { | ||||
|                 throw exception(APP_KEY_EXISTS); | ||||
|             } | ||||
|             // 更新时,校验appKey是否重复 | ||||
|         } else if (Objects.nonNull(payAppId) && StrUtil.isNotBlank(payAppKey)) { | ||||
|             LambdaQueryWrapperX<PayAppDO> queryWrapper = new LambdaQueryWrapperX<>(); | ||||
|             queryWrapper.eq(PayAppDO::getAppKey, payAppKey) | ||||
|                     .ne(PayAppDO::getId, payAppId); | ||||
|             if (appMapper.selectCount(queryWrapper) > 0) { | ||||
|                 throw exception(APP_KEY_EXISTS); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -43,7 +43,7 @@ import static cn.iocoder.yudao.module.pay.enums.ErrorCodeConstants.*; | ||||
| public class PayDemoOrderServiceImpl implements PayDemoOrderService { | ||||
|  | ||||
|     /** | ||||
|      * 接入的实力应用编号 | ||||
|      * 接入的支付应用标识 | ||||
|      * | ||||
|      * 从 [支付管理 -> 应用信息] 里添加 | ||||
|      */ | ||||
|   | ||||
| @@ -199,8 +199,8 @@ public class PayRefundServiceImpl implements PayRefundService { | ||||
|      * @param channel 支付渠道 | ||||
|      * @param notify  通知 | ||||
|      */ | ||||
|     @Transactional(rollbackFor = Exception.class) | ||||
|     // 注意,如果是方法内调用该方法,需要通过 getSelf().notifyRefund(channel, notify) 调用,否则事务不生效 | ||||
|     @Transactional(rollbackFor = Exception.class) | ||||
|     public void notifyRefund(PayChannelDO channel, PayRefundRespDTO notify) { | ||||
|         // 情况一:退款成功 | ||||
|         if (PayRefundStatusRespEnum.isSuccess(notify.getStatus())) { | ||||
|   | ||||
| @@ -18,6 +18,7 @@ import cn.iocoder.yudao.module.pay.dal.mysql.wallet.PayWalletRechargeMapper; | ||||
| import cn.iocoder.yudao.module.pay.enums.order.PayOrderStatusEnum; | ||||
| import cn.iocoder.yudao.module.pay.enums.refund.PayRefundStatusEnum; | ||||
| import cn.iocoder.yudao.module.pay.enums.wallet.PayWalletBizTypeEnum; | ||||
| import cn.iocoder.yudao.module.pay.framework.pay.config.PayProperties; | ||||
| import cn.iocoder.yudao.module.pay.service.order.PayOrderService; | ||||
| import cn.iocoder.yudao.module.pay.service.refund.PayRefundService; | ||||
| import cn.iocoder.yudao.module.system.api.social.SocialClientApi; | ||||
| @@ -51,11 +52,6 @@ import static cn.iocoder.yudao.module.pay.enums.refund.PayRefundStatusEnum.*; | ||||
| @Slf4j | ||||
| public class PayWalletRechargeServiceImpl implements PayWalletRechargeService { | ||||
|  | ||||
|     /** | ||||
|      * TODO 芋艿:放到 payconfig | ||||
|      */ | ||||
|     private static final String WALLET_PAY_APP_KEY = "wallet"; | ||||
|  | ||||
|     private static final String WALLET_RECHARGE_ORDER_SUBJECT = "钱包余额充值"; | ||||
|  | ||||
|     @Resource | ||||
| @@ -68,9 +64,13 @@ public class PayWalletRechargeServiceImpl implements PayWalletRechargeService { | ||||
|     private PayRefundService payRefundService; | ||||
|     @Resource | ||||
|     private PayWalletRechargePackageService payWalletRechargePackageService; | ||||
|  | ||||
|     @Resource | ||||
|     public SocialClientApi socialClientApi; | ||||
|  | ||||
|     @Resource | ||||
|     private PayProperties payProperties; | ||||
|  | ||||
|     @Override | ||||
|     @Transactional(rollbackFor = Exception.class) | ||||
|     public PayWalletRechargeDO createWalletRecharge(Long userId, Integer userType, String userIp, | ||||
| @@ -92,7 +92,7 @@ public class PayWalletRechargeServiceImpl implements PayWalletRechargeService { | ||||
|  | ||||
|         // 2.1 创建支付单 | ||||
|         Long payOrderId = payOrderService.createOrder(new PayOrderCreateReqDTO() | ||||
|                 .setAppKey(WALLET_PAY_APP_KEY).setUserIp(userIp) | ||||
|                 .setAppKey(payProperties.getWalletPayAppKey()).setUserIp(userIp) | ||||
|                 .setMerchantOrderId(recharge.getId().toString()) // 业务的订单编号 | ||||
|                 .setSubject(WALLET_RECHARGE_ORDER_SUBJECT).setBody("") | ||||
|                 .setPrice(recharge.getPayPrice()) | ||||
| @@ -174,7 +174,7 @@ public class PayWalletRechargeServiceImpl implements PayWalletRechargeService { | ||||
|         String walletRechargeId = String.valueOf(id); | ||||
|         String refundId = walletRechargeId + "-refund"; | ||||
|         Long payRefundId = payRefundService.createPayRefund(new PayRefundCreateReqDTO() | ||||
|                 .setAppKey(WALLET_PAY_APP_KEY).setUserIp(userIp) | ||||
|                 .setAppKey(payProperties.getWalletPayAppKey()).setUserIp(userIp) | ||||
|                 .setMerchantOrderId(walletRechargeId) | ||||
|                 .setMerchantRefundId(refundId) | ||||
|                 .setReason("想退钱").setPrice(walletRecharge.getPayPrice())); | ||||
|   | ||||
| @@ -98,9 +98,12 @@ public class AlipayPayClientConfig implements PayClientConfig { | ||||
|     private String rootCertContent; | ||||
|  | ||||
|     /** | ||||
|      * 接口内容加密方式,如果为空,将使用无加密方式 | ||||
|      * 如果要加密,目前支付宝只有 AES 一种加密方式 | ||||
|      * <a href="https://opendocs.alipay.com/common/02mse3">支付宝开放平台</a> | ||||
|      * 接口内容加密方式 | ||||
|      * | ||||
|      * 1. 如果为空,将使用无加密方式 | ||||
|      * 2. 如果要加密,目前支付宝只有 AES 一种加密方式 | ||||
|      * | ||||
|      * @see <a href="https://opendocs.alipay.com/common/02mse3">支付宝开放平台</a> | ||||
|      * @see AlipayPayClientConfig#ENC_TYPE_AES | ||||
|      */ | ||||
|     private String encryptType; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 YunaiV
					YunaiV