From d5b3dbfa62eb5b0a3ccf5f84383796d1f864a32f Mon Sep 17 00:00:00 2001 From: xxm1995 Date: Wed, 5 Jul 2023 17:06:07 +0800 Subject: [PATCH] =?UTF-8?q?ref=20=E4=BB=8E=E6=94=AF=E4=BB=98=E7=AD=96?= =?UTF-8?q?=E7=95=A5=E4=B8=AD=E6=8B=86=E5=88=86=E5=87=BA=E9=80=80=E6=AC=BE?= =?UTF-8?q?=E6=93=8D=E4=BD=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../daxpay/code/paymodel/VoucherCode.java | 2 +- .../daxpay/code/paymodel/WalletCode.java | 5 - .../daxpay/controller/PayController.java | 2 +- .../controller/RefundRecordController.java | 2 +- .../alipay/service/AliPayCancelService.java | 2 +- .../alipay/service/AlipayConfigService.java | 53 ++++++++ .../channel/voucher/dao/VoucherManager.java | 19 ++- .../voucher/service/VoucherPayService.java | 106 ++++++++-------- .../wallet/service/WalletPayService.java | 14 +-- .../service/WeChatPayCancelService.java | 2 +- .../core/pay/builder/PaymentBuilder.java | 2 +- .../core/pay/factory/PayStrategyFactory.java | 8 +- .../daxpay/core/pay/func/AbsPayStrategy.java | 5 - .../core/pay/strategy/AliPayStrategy.java | 75 +---------- .../core/pay/strategy/CashPayStrategy.java | 9 -- .../core/pay/strategy/UnionPayStrategy.java | 5 - ...rStrategy.java => VoucherPayStrategy.java} | 22 +--- .../core/pay/strategy/WalletPayStrategy.java | 18 +-- .../core/pay/strategy/WeChatPayStrategy.java | 29 +---- .../factory/PayRefundStrategyFactory.java | 119 ++++++++++++++++++ .../refund/func/AbsPayRefundStrategy.java | 61 +++++++++ .../func/PayRefundStrategyConsumer.java | 17 +++ .../local/AsyncRefundLocal.java | 2 +- .../{ => record}/convert/RefundConvert.java | 4 +- .../{ => record}/dao/RefundRecordManager.java | 4 +- .../{ => record}/dao/RefundRecordMapper.java | 4 +- .../{ => record}/entity/RefundRecord.java | 4 +- .../service/RefundRecordService.java | 6 +- .../service/PayRefundService.java | 60 ++++----- .../refund/strategy/AliPayRefundStrategy.java | 60 +++++++++ .../strategy/CashPayRefundStrategy.java | 44 +++++++ .../strategy/UnionPayRefundStrategy.java | 37 ++++++ .../strategy/VoucherPayRefundStrategy.java | 65 ++++++++++ .../strategy/WalletPayRefundStrategy.java | 45 +++++++ .../strategy/WeChatPayRefundStrategy.java | 77 ++++++++++++ .../voucher/VoucherGenerationParam.java | 4 +- .../daxpay/param/refund/RefundModeParam.java | 7 -- .../src/main/resources/application-dev.yml | 7 ++ 38 files changed, 719 insertions(+), 288 deletions(-) rename dax-pay/src/main/java/cn/bootx/platform/daxpay/core/pay/strategy/{VoucherStrategy.java => VoucherPayStrategy.java} (77%) create mode 100644 dax-pay/src/main/java/cn/bootx/platform/daxpay/core/refund/factory/PayRefundStrategyFactory.java create mode 100644 dax-pay/src/main/java/cn/bootx/platform/daxpay/core/refund/func/AbsPayRefundStrategy.java create mode 100644 dax-pay/src/main/java/cn/bootx/platform/daxpay/core/refund/func/PayRefundStrategyConsumer.java rename dax-pay/src/main/java/cn/bootx/platform/daxpay/core/{pay => refund}/local/AsyncRefundLocal.java (96%) rename dax-pay/src/main/java/cn/bootx/platform/daxpay/core/refund/{ => record}/convert/RefundConvert.java (71%) rename dax-pay/src/main/java/cn/bootx/platform/daxpay/core/refund/{ => record}/dao/RefundRecordManager.java (90%) rename dax-pay/src/main/java/cn/bootx/platform/daxpay/core/refund/{ => record}/dao/RefundRecordMapper.java (63%) rename dax-pay/src/main/java/cn/bootx/platform/daxpay/core/refund/{ => record}/entity/RefundRecord.java (93%) rename dax-pay/src/main/java/cn/bootx/platform/daxpay/core/refund/{ => record}/service/RefundRecordService.java (84%) rename dax-pay/src/main/java/cn/bootx/platform/daxpay/core/{pay => refund}/service/PayRefundService.java (80%) create mode 100644 dax-pay/src/main/java/cn/bootx/platform/daxpay/core/refund/strategy/AliPayRefundStrategy.java create mode 100644 dax-pay/src/main/java/cn/bootx/platform/daxpay/core/refund/strategy/CashPayRefundStrategy.java create mode 100644 dax-pay/src/main/java/cn/bootx/platform/daxpay/core/refund/strategy/UnionPayRefundStrategy.java create mode 100644 dax-pay/src/main/java/cn/bootx/platform/daxpay/core/refund/strategy/VoucherPayRefundStrategy.java create mode 100644 dax-pay/src/main/java/cn/bootx/platform/daxpay/core/refund/strategy/WalletPayRefundStrategy.java create mode 100644 dax-pay/src/main/java/cn/bootx/platform/daxpay/core/refund/strategy/WeChatPayRefundStrategy.java diff --git a/dax-pay/src/main/java/cn/bootx/platform/daxpay/code/paymodel/VoucherCode.java b/dax-pay/src/main/java/cn/bootx/platform/daxpay/code/paymodel/VoucherCode.java index fe92aa3e5..cc593fb76 100644 --- a/dax-pay/src/main/java/cn/bootx/platform/daxpay/code/paymodel/VoucherCode.java +++ b/dax-pay/src/main/java/cn/bootx/platform/daxpay/code/paymodel/VoucherCode.java @@ -34,7 +34,7 @@ public interface VoucherCode { String LOG_UNFREEZE_BALANCE = "unfreeze"; /** - * 钱包日志-解冻并扣减余额 + * 钱包日志-扣减并解冻余额 */ String LOG_REDUCE_AND_UNFREEZE_BALANCE = "reduceAndUnfreeze"; diff --git a/dax-pay/src/main/java/cn/bootx/platform/daxpay/code/paymodel/WalletCode.java b/dax-pay/src/main/java/cn/bootx/platform/daxpay/code/paymodel/WalletCode.java index aadd2ff6a..a64fa0ea5 100644 --- a/dax-pay/src/main/java/cn/bootx/platform/daxpay/code/paymodel/WalletCode.java +++ b/dax-pay/src/main/java/cn/bootx/platform/daxpay/code/paymodel/WalletCode.java @@ -41,11 +41,6 @@ public interface WalletCode { */ String LOG_FREEZE_BALANCE = "freeze"; - /** - * 钱包日志-解冻额度 - */ - String LOG_UNFREEZE_BALANCE = "unfreeze"; - /** * 钱包日志-解冻并扣减余额 */ diff --git a/dax-pay/src/main/java/cn/bootx/platform/daxpay/controller/PayController.java b/dax-pay/src/main/java/cn/bootx/platform/daxpay/controller/PayController.java index 950d31c75..2186b5df0 100644 --- a/dax-pay/src/main/java/cn/bootx/platform/daxpay/controller/PayController.java +++ b/dax-pay/src/main/java/cn/bootx/platform/daxpay/controller/PayController.java @@ -3,7 +3,7 @@ package cn.bootx.platform.daxpay.controller; import cn.bootx.platform.common.core.rest.Res; import cn.bootx.platform.common.core.rest.ResResult; import cn.bootx.platform.daxpay.core.pay.service.PayCancelService; -import cn.bootx.platform.daxpay.core.pay.service.PayRefundService; +import cn.bootx.platform.daxpay.core.refund.service.PayRefundService; import cn.bootx.platform.daxpay.core.pay.service.PayService; import cn.bootx.platform.daxpay.core.pay.service.PaySyncService; import cn.bootx.platform.daxpay.dto.pay.PayResult; diff --git a/dax-pay/src/main/java/cn/bootx/platform/daxpay/controller/RefundRecordController.java b/dax-pay/src/main/java/cn/bootx/platform/daxpay/controller/RefundRecordController.java index e79a7320e..8193f0791 100644 --- a/dax-pay/src/main/java/cn/bootx/platform/daxpay/controller/RefundRecordController.java +++ b/dax-pay/src/main/java/cn/bootx/platform/daxpay/controller/RefundRecordController.java @@ -4,7 +4,7 @@ import cn.bootx.platform.common.core.rest.PageResult; import cn.bootx.platform.common.core.rest.Res; import cn.bootx.platform.common.core.rest.ResResult; import cn.bootx.platform.common.core.rest.param.PageParam; -import cn.bootx.platform.daxpay.core.refund.service.RefundRecordService; +import cn.bootx.platform.daxpay.core.refund.record.service.RefundRecordService; import cn.bootx.platform.daxpay.dto.refund.RefundRecordDto; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; diff --git a/dax-pay/src/main/java/cn/bootx/platform/daxpay/core/channel/alipay/service/AliPayCancelService.java b/dax-pay/src/main/java/cn/bootx/platform/daxpay/core/channel/alipay/service/AliPayCancelService.java index 4a0a0570a..de11e63fe 100644 --- a/dax-pay/src/main/java/cn/bootx/platform/daxpay/core/channel/alipay/service/AliPayCancelService.java +++ b/dax-pay/src/main/java/cn/bootx/platform/daxpay/core/channel/alipay/service/AliPayCancelService.java @@ -2,7 +2,7 @@ package cn.bootx.platform.daxpay.core.channel.alipay.service; import cn.bootx.platform.common.spring.exception.RetryableException; import cn.bootx.platform.daxpay.code.paymodel.AliPayCode; -import cn.bootx.platform.daxpay.core.pay.local.AsyncRefundLocal; +import cn.bootx.platform.daxpay.core.refund.local.AsyncRefundLocal; import cn.bootx.platform.daxpay.core.payment.entity.Payment; import cn.bootx.platform.daxpay.exception.payment.PayFailureException; import cn.hutool.core.util.IdUtil; diff --git a/dax-pay/src/main/java/cn/bootx/platform/daxpay/core/channel/alipay/service/AlipayConfigService.java b/dax-pay/src/main/java/cn/bootx/platform/daxpay/core/channel/alipay/service/AlipayConfigService.java index f41f2de13..f19e62e43 100644 --- a/dax-pay/src/main/java/cn/bootx/platform/daxpay/core/channel/alipay/service/AlipayConfigService.java +++ b/dax-pay/src/main/java/cn/bootx/platform/daxpay/core/channel/alipay/service/AlipayConfigService.java @@ -8,6 +8,7 @@ import cn.bootx.platform.common.core.rest.param.PageParam; import cn.bootx.platform.common.mybatisplus.util.MpUtil; import cn.bootx.platform.daxpay.code.MchAndAppCode; import cn.bootx.platform.daxpay.code.pay.PayChannelEnum; +import cn.bootx.platform.daxpay.code.paymodel.AliPayCode; import cn.bootx.platform.daxpay.code.paymodel.AliPayWay; import cn.bootx.platform.daxpay.core.channel.alipay.dao.AlipayConfigManager; import cn.bootx.platform.daxpay.core.channel.alipay.entity.AlipayConfig; @@ -20,12 +21,18 @@ import cn.bootx.platform.daxpay.param.channel.alipay.AlipayConfigQuery; import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.bean.copier.CopyOptions; import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.CharsetUtil; +import com.ijpay.alipay.AliPayApiConfig; +import com.ijpay.alipay.AliPayApiConfigKit; import lombok.RequiredArgsConstructor; +import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j; +import lombok.val; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.util.List; +import java.util.Objects; import java.util.stream.Collectors; /** @@ -107,4 +114,50 @@ public class AlipayConfigService { .collect(Collectors.toList()); } + /** + * 初始化IJPay服务,通过商户应用AppCode获取支付配置 + */ + public void initApiConfigByMchAppCode(String mchAppCode){ + val alipayConfig = alipayConfigManager.findByMchAppCode(mchAppCode) + .orElseThrow(() -> new DataNotExistException("支付配置不存在")); + this.initApiConfig(alipayConfig); + } + + /** + * 初始化IJPay服务 + */ + @SneakyThrows + public void initApiConfig(AlipayConfig alipayConfig) { + + AliPayApiConfig aliPayApiConfig; + // 公钥 + if (Objects.equals(alipayConfig.getAuthType(), AliPayCode.AUTH_TYPE_KEY)) { + aliPayApiConfig = AliPayApiConfig.builder() + .setAppId(alipayConfig.getAppId()) + .setPrivateKey(alipayConfig.getPrivateKey()) + .setAliPayPublicKey(alipayConfig.getAlipayPublicKey()) + .setCharset(CharsetUtil.UTF_8) + .setServiceUrl(alipayConfig.getServerUrl()) + .setSignType(alipayConfig.getSignType()) + .build(); + } + // 证书 + else if (Objects.equals(alipayConfig.getAuthType(), AliPayCode.AUTH_TYPE_CART)) { + aliPayApiConfig = AliPayApiConfig.builder() + .setAppId(alipayConfig.getAppId()) + .setPrivateKey(alipayConfig.getPrivateKey()) + .setAppCertContent(alipayConfig.getAppCert()) + .setAliPayCertContent(alipayConfig.getAlipayCert()) + .setAliPayRootCertContent(alipayConfig.getAlipayRootCert()) + .setCharset(CharsetUtil.UTF_8) + .setServiceUrl(alipayConfig.getServerUrl()) + .setSignType(alipayConfig.getSignType()) + .buildByCertContent(); + } + else { + throw new BizException("支付宝认证方式不可为空"); + } + AliPayApiConfigKit.setThreadLocalAliPayApiConfig(aliPayApiConfig); + } + } diff --git a/dax-pay/src/main/java/cn/bootx/platform/daxpay/core/channel/voucher/dao/VoucherManager.java b/dax-pay/src/main/java/cn/bootx/platform/daxpay/core/channel/voucher/dao/VoucherManager.java index d2330fc99..824528392 100644 --- a/dax-pay/src/main/java/cn/bootx/platform/daxpay/core/channel/voucher/dao/VoucherManager.java +++ b/dax-pay/src/main/java/cn/bootx/platform/daxpay/core/channel/voucher/dao/VoucherManager.java @@ -1,17 +1,20 @@ package cn.bootx.platform.daxpay.core.channel.voucher.dao; import cn.bootx.platform.common.core.rest.param.PageParam; +import cn.bootx.platform.common.mybatisplus.base.MpDelEntity; import cn.bootx.platform.common.mybatisplus.base.MpIdEntity; import cn.bootx.platform.common.mybatisplus.impl.BaseManager; import cn.bootx.platform.common.mybatisplus.util.MpUtil; import cn.bootx.platform.daxpay.core.channel.voucher.entity.Voucher; import cn.bootx.platform.daxpay.param.channel.voucher.VoucherParam; +import cn.bootx.platform.starter.auth.util.SecurityUtil; import cn.hutool.core.util.StrUtil; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Repository; +import java.time.LocalDateTime; import java.util.List; import java.util.Objects; import java.util.Optional; @@ -57,16 +60,24 @@ public class VoucherManager extends BaseManager { /** * 更改状态 */ - public void changeStatus(Long id, int status) { - this.lambdaUpdate().eq(MpIdEntity::getId, id).set(Voucher::getStatus, status).update(); + public void changeStatus(Long id, String status) { + Long userIdOrDefaultId = SecurityUtil.getUserIdOrDefaultId(); + this.lambdaUpdate().eq(MpIdEntity::getId, id) + .set(MpDelEntity::getLastModifiedTime, LocalDateTime.now()) + .set(MpDelEntity::getLastModifier,userIdOrDefaultId) + .set(Voucher::getStatus, status).update(); } /** * 批量更改状态 */ - public void changeStatusBatch(List ids, int status) { - this.lambdaUpdate().in(MpIdEntity::getId, ids).set(Voucher::getStatus, status).update(); + public void changeStatusBatch(List ids, String status) { + Long userIdOrDefaultId = SecurityUtil.getUserIdOrDefaultId(); + this.lambdaUpdate().in(MpIdEntity::getId, ids) + .set(MpDelEntity::getLastModifiedTime, LocalDateTime.now()) + .set(MpDelEntity::getLastModifier,userIdOrDefaultId) + .set(Voucher::getStatus, status).update(); } } diff --git a/dax-pay/src/main/java/cn/bootx/platform/daxpay/core/channel/voucher/service/VoucherPayService.java b/dax-pay/src/main/java/cn/bootx/platform/daxpay/core/channel/voucher/service/VoucherPayService.java index deb2cd91f..3d8c346f3 100644 --- a/dax-pay/src/main/java/cn/bootx/platform/daxpay/core/channel/voucher/service/VoucherPayService.java +++ b/dax-pay/src/main/java/cn/bootx/platform/daxpay/core/channel/voucher/service/VoucherPayService.java @@ -1,6 +1,5 @@ package cn.bootx.platform.daxpay.core.channel.voucher.service; -import cn.bootx.platform.common.core.exception.DataNotExistException; import cn.bootx.platform.common.core.function.CollectorsFunction; import cn.bootx.platform.common.core.util.BigDecimalUtil; import cn.bootx.platform.common.core.util.LocalDateTimeUtil; @@ -31,7 +30,6 @@ import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.Objects; -import java.util.function.Function; import java.util.stream.Collectors; /** @@ -90,7 +88,7 @@ public class VoucherPayService { } /** - * 支付前冻结余额 + * 支付前冻结余额 (异步组合支付环境下) */ public List freezeBalance(BigDecimal amount, Payment payment, List vouchers){ List voucherLogs = new ArrayList<>(); @@ -106,19 +104,23 @@ public class VoucherPayService { .setPaymentId(payment.getId()) .setBusinessId(payment.getBusinessId()) .setType(VoucherCode.LOG_FREEZE_BALANCE) + .setRemark(String.format("钱包预冻结金额 %.2f ", amount)) .setVoucherId(voucher.getId()) .setVoucherNo(voucher.getCardNo()); - // 待支付额大于储值卡余额. 全冻结 + // 待支付额大于储值卡余额. 储值卡的金额全冻结 if (BigDecimalUtil.compareTo(amount, balance) == 1) { - amount = amount.subtract(balance); voucher.setFreezeBalance(balance); voucherLog.setAmount(balance); + // 剩余待支付的金额 + amount = amount.subtract(balance); } else { - amount = BigDecimal.ZERO; + // 待支付额小于或储值卡余额, 冻结待支付的金额 voucher.setFreezeBalance(amount); voucherLog.setAmount(amount); + // 待支付的金额扣减完毕, 值设置为零 + amount = BigDecimal.ZERO; } voucherRecords.add(new VoucherRecord().setCardNo(voucher.getCardNo()).setAmount(voucher.getFreezeBalance())); voucherLogs.add(voucherLog); @@ -129,35 +131,30 @@ public class VoucherPayService { } /** - * 支付成功, 对冻结的金额进行扣款 + * 支付成功, 对冻结的金额进行扣款 (异步组合支付环境下) */ public void paySuccess(Long paymentId){ voucherPaymentManager.findByPaymentId(paymentId).ifPresent(voucherPayment -> { + List voucherRecords = voucherPayment.getVoucherRecords(); + List cardNoList = voucherRecords.stream() + .map(VoucherRecord::getCardNo) + .collect(Collectors.toList()); + List vouchers = voucherManager.findByCardNoList(cardNoList); List voucherLogs = new ArrayList<>(); for (Voucher voucher : vouchers) { - // 待支付余额为零, 不在处理后面的储值卡 - if (BigDecimalUtil.compareTo(amount, BigDecimal.ZERO) < 1) { - break; - } - BigDecimal balance = voucher.getBalance(); + // 余额扣减 + voucher.setBalance(voucher.getBalance().subtract(voucher.getFreezeBalance())) + .setFreezeBalance(BigDecimal.ZERO); // 日志 VoucherLog voucherLog = new VoucherLog() - .setPaymentId(payment.getId()) - .setBusinessId(payment.getBusinessId()) - .setType(VoucherCode.LOG_FREEZE_BALANCE) + .setPaymentId(voucherPayment.getPaymentId()) + .setBusinessId(voucherPayment.getBusinessId()) + .setType(VoucherCode.LOG_REDUCE_AND_UNFREEZE_BALANCE) + .setRemark(String.format("钱包扣款金额 %.2f ", voucherPayment.getAmount())) .setVoucherId(voucher.getId()) + .setAmount(voucher.getFreezeBalance()) .setVoucherNo(voucher.getCardNo()); - - // 待支付额大于储值卡余额. 全冻结 - if (BigDecimalUtil.compareTo(amount, balance) == 1) { - amount = amount.subtract(balance); - voucher.setFreezeBalance(balance); - voucherLog.setAmount(balance); - } else { - voucher.setFreezeBalance(balance.subtract(amount)); - voucherLog.setAmount(amount); - } voucherLogs.add(voucherLog); } voucherManager.updateAllById(vouchers); @@ -183,23 +180,26 @@ public class VoucherPayService { .setPaymentId(payment.getId()) .setBusinessId(payment.getBusinessId()) .setType(VoucherCode.LOG_PAY) + .setRemark(String.format("钱包支付金额 %.2f ", amount)) .setVoucherId(voucher.getId()) .setVoucherNo(voucher.getCardNo()); // 记录当前卡扣了多少钱 BigDecimal amountRecord; - // 待支付额大于储值卡余额. 全扣光 + // 待支付额大于储值卡余额. 储值卡金额全扣光 if (BigDecimalUtil.compareTo(amount, balance) == 1) { amountRecord = voucher.getBalance(); - amount = amount.subtract(balance); voucher.setBalance(BigDecimal.ZERO); voucherLog.setAmount(balance); + amount = amount.subtract(balance); } else { + // 待支付额小于或储值卡余额, 储值卡余额-待支付额 amountRecord = balance.subtract(amount); - amount = BigDecimal.ZERO; voucher.setBalance(balance.subtract(amount)); voucherLog.setAmount(amount); + // 支付完毕, 待支付金额归零 + amount = BigDecimal.ZERO; } voucherLogs.add(voucherLog); voucherRecords.add(new VoucherRecord().setCardNo(voucher.getCardNo()).setAmount(amountRecord)); @@ -211,35 +211,29 @@ public class VoucherPayService { /** - * 取消支付, 可配置解除冻结金额 - * @param freeze 是否是冻结模式, 是的话对冻结金额进行解冻, 不是的话返还扣减的金额 + * 取消支付,解除冻结的额度, 只有在异步支付中才会发生取消操作 */ - public void close(Long paymentId, boolean freeze) { - - VoucherPayment voucherPayment = voucherPaymentManager.findByPaymentId(paymentId).orElseThrow(DataNotExistException::new); - - - // 查找支付记录日志 - List voucherLogs = voucherLogManager.findByPaymentIdAndType(paymentId, VoucherCode.LOG_PAY); - // 查出关联的储值卡 - Map voucherLogMap = voucherLogs.stream() - .collect(Collectors.toMap(VoucherLog::getVoucherId, Function.identity())); - List vouchers = voucherManager.findAllByIds(voucherLogMap.keySet()); - // 执行退款并记录日志 - List logs = new ArrayList<>(); - for (Voucher voucher : vouchers) { - VoucherLog voucherLog = voucherLogMap.get(voucher.getId()); - voucher.setBalance(voucher.getBalance().add(voucherLog.getAmount())); - VoucherLog log = new VoucherLog().setAmount(voucherLog.getAmount()) - .setPaymentId(paymentId) - .setBusinessId(voucherLog.getBusinessId()) - .setVoucherId(voucher.getId()) - .setVoucherNo(voucher.getCardNo()) - .setType(VoucherCode.LOG_CLOSE_PAY); - logs.add(log); - } - voucherManager.updateAllById(vouchers); - voucherLogManager.saveAll(logs); + public void close(Long paymentId) { + voucherPaymentManager.findByPaymentId(paymentId).ifPresent(voucherPayment -> { + List cardNoList = voucherPayment.getVoucherRecords().stream() + .map(VoucherRecord::getCardNo) + .collect(Collectors.toList()); + List vouchers = voucherManager.findByCardNoList(cardNoList); + // 解冻额度和记录日志 + List logs = new ArrayList<>(); + for (Voucher voucher : vouchers) { + VoucherLog log = new VoucherLog().setAmount(voucher.getFreezeBalance()) + .setPaymentId(paymentId) + .setBusinessId(voucherPayment.getBusinessId()) + .setVoucherId(voucher.getId()) + .setRemark(String.format("取消支付金额 %.2f ", voucher.getFreezeBalance())) + .setVoucherNo(voucher.getCardNo()) + .setType(VoucherCode.LOG_CLOSE_PAY); + logs.add(log); + } + voucherManager.updateAllById(vouchers); + voucherLogManager.saveAll(logs); + }); } /** diff --git a/dax-pay/src/main/java/cn/bootx/platform/daxpay/core/channel/wallet/service/WalletPayService.java b/dax-pay/src/main/java/cn/bootx/platform/daxpay/core/channel/wallet/service/WalletPayService.java index a2a68d3ae..abe933faa 100644 --- a/dax-pay/src/main/java/cn/bootx/platform/daxpay/core/channel/wallet/service/WalletPayService.java +++ b/dax-pay/src/main/java/cn/bootx/platform/daxpay/core/channel/wallet/service/WalletPayService.java @@ -119,10 +119,9 @@ public class WalletPayService { } /** - * 取消支付, 可配置解除冻结金额 - * @param freeze 是否是冻结模式, 是的话对冻结金额进行解冻, 不是的话返还扣减的金额 + * 取消支付,解除冻结的额度, 只有在异步支付中才会发生取消操作 */ - public void close(Long paymentId,boolean freeze) { + public void close(Long paymentId) { // 钱包支付记录 walletPaymentManager.findByPaymentId(paymentId).ifPresent(walletPayment -> { Optional walletOpt = walletManager.findById(walletPayment.getWalletId()); @@ -134,21 +133,14 @@ public class WalletPayService { walletPayment.setPayStatus(PayStatusCode.TRADE_CANCEL); walletPaymentManager.save(walletPayment); - // 是否在进行了额度冻结 - if (freeze){ - // 解冻金额 - walletManager.unfreezeBalance(wallet.getId(), walletPayment.getAmount()); - } else { // 金额返还 walletManager.increaseBalance(wallet.getId(), walletPayment.getAmount()); - } - // 记录日志 WalletLog walletLog = new WalletLog().setAmount(walletPayment.getAmount()) .setPaymentId(walletPayment.getPaymentId()) .setWalletId(wallet.getId()) .setUserId(wallet.getUserId()) - .setType(freeze?WalletCode.LOG_CLOSE_PAY:WalletCode.LOG_UNFREEZE_BALANCE) + .setType(WalletCode.LOG_CLOSE_PAY) .setRemark(String.format("取消支付金额 %.2f ", walletPayment.getAmount())) .setOperationSource(WalletCode.OPERATION_SOURCE_SYSTEM) .setBusinessId(walletPayment.getBusinessId()); diff --git a/dax-pay/src/main/java/cn/bootx/platform/daxpay/core/channel/wechat/service/WeChatPayCancelService.java b/dax-pay/src/main/java/cn/bootx/platform/daxpay/core/channel/wechat/service/WeChatPayCancelService.java index be1939b26..0c81fe12f 100644 --- a/dax-pay/src/main/java/cn/bootx/platform/daxpay/core/channel/wechat/service/WeChatPayCancelService.java +++ b/dax-pay/src/main/java/cn/bootx/platform/daxpay/core/channel/wechat/service/WeChatPayCancelService.java @@ -2,7 +2,7 @@ package cn.bootx.platform.daxpay.core.channel.wechat.service; import cn.bootx.platform.common.spring.exception.RetryableException; import cn.bootx.platform.daxpay.code.paymodel.WeChatPayCode; -import cn.bootx.platform.daxpay.core.pay.local.AsyncRefundLocal; +import cn.bootx.platform.daxpay.core.refund.local.AsyncRefundLocal; import cn.bootx.platform.daxpay.core.payment.entity.Payment; import cn.bootx.platform.daxpay.core.channel.wechat.entity.WeChatPayConfig; import cn.bootx.platform.daxpay.core.channel.wechat.entity.WeChatPayment; diff --git a/dax-pay/src/main/java/cn/bootx/platform/daxpay/core/pay/builder/PaymentBuilder.java b/dax-pay/src/main/java/cn/bootx/platform/daxpay/core/pay/builder/PaymentBuilder.java index 77e670b8b..707aac703 100644 --- a/dax-pay/src/main/java/cn/bootx/platform/daxpay/core/pay/builder/PaymentBuilder.java +++ b/dax-pay/src/main/java/cn/bootx/platform/daxpay/core/pay/builder/PaymentBuilder.java @@ -8,8 +8,8 @@ import cn.bootx.platform.daxpay.core.payment.entity.Payment; import cn.bootx.platform.daxpay.dto.pay.PayResult; import cn.bootx.platform.daxpay.dto.payment.PayChannelInfo; import cn.bootx.platform.daxpay.dto.payment.RefundableInfo; -import cn.bootx.platform.daxpay.param.pay.PayWayParam; import cn.bootx.platform.daxpay.param.pay.PayParam; +import cn.bootx.platform.daxpay.param.pay.PayWayParam; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.CollectionUtil; import cn.hutool.extra.servlet.ServletUtil; diff --git a/dax-pay/src/main/java/cn/bootx/platform/daxpay/core/pay/factory/PayStrategyFactory.java b/dax-pay/src/main/java/cn/bootx/platform/daxpay/core/pay/factory/PayStrategyFactory.java index c324af684..edcaf02d4 100644 --- a/dax-pay/src/main/java/cn/bootx/platform/daxpay/core/pay/factory/PayStrategyFactory.java +++ b/dax-pay/src/main/java/cn/bootx/platform/daxpay/core/pay/factory/PayStrategyFactory.java @@ -32,7 +32,7 @@ public class PayStrategyFactory { public static AbsPayStrategy create(PayWayParam payWayParam) { AbsPayStrategy strategy = null; - PayChannelEnum channelEnum = findByCode(payWayParam.getPayChannel()); + PayChannelEnum channelEnum = PayChannelEnum.findByCode(payWayParam.getPayChannel()); switch (channelEnum) { case ALI: strategy = SpringUtil.getBean(AliPayStrategy.class); @@ -50,7 +50,7 @@ public class PayStrategyFactory { strategy = SpringUtil.getBean(WalletPayStrategy.class); break; case VOUCHER: - strategy = SpringUtil.getBean(VoucherStrategy.class); + strategy = SpringUtil.getBean(VoucherPayStrategy.class); break; case CREDIT_CARD: break; @@ -92,13 +92,13 @@ public class PayStrategyFactory { // 同步支付 List syncPayWayParamList = payWayParamList.stream() .filter(Objects::nonNull) - .filter(payModeParam -> !ASYNC_TYPE.contains(payModeParam.getPayChannel())) + .filter(payModeParam -> !ASYNC_TYPE_CODE.contains(payModeParam.getPayChannel())) .collect(Collectors.toList()); // 异步支付 List asyncPayWayParamList = payWayParamList.stream() .filter(Objects::nonNull) - .filter(payModeParam -> ASYNC_TYPE.contains(payModeParam.getPayChannel())) + .filter(payModeParam -> ASYNC_TYPE_CODE.contains(payModeParam.getPayChannel())) .collect(Collectors.toList()); List sortList = new ArrayList<>(payWayParamList.size()); diff --git a/dax-pay/src/main/java/cn/bootx/platform/daxpay/core/pay/func/AbsPayStrategy.java b/dax-pay/src/main/java/cn/bootx/platform/daxpay/core/pay/func/AbsPayStrategy.java index ecee4d857..b9c26abe6 100644 --- a/dax-pay/src/main/java/cn/bootx/platform/daxpay/core/pay/func/AbsPayStrategy.java +++ b/dax-pay/src/main/java/cn/bootx/platform/daxpay/core/pay/func/AbsPayStrategy.java @@ -93,11 +93,6 @@ public abstract class AbsPayStrategy { */ public abstract void doCloseHandler(); - /** - * 退款 - */ - public abstract void doRefundHandler(); - /** * 异步支付单与支付网关进行状态比对 * @see PaySyncStatus diff --git a/dax-pay/src/main/java/cn/bootx/platform/daxpay/core/pay/strategy/AliPayStrategy.java b/dax-pay/src/main/java/cn/bootx/platform/daxpay/core/pay/strategy/AliPayStrategy.java index ec7fb22fa..5d50a5a3f 100644 --- a/dax-pay/src/main/java/cn/bootx/platform/daxpay/core/pay/strategy/AliPayStrategy.java +++ b/dax-pay/src/main/java/cn/bootx/platform/daxpay/core/pay/strategy/AliPayStrategy.java @@ -1,37 +1,26 @@ package cn.bootx.platform.daxpay.core.pay.strategy; -import cn.bootx.platform.common.core.exception.BizException; import cn.bootx.platform.common.core.util.BigDecimalUtil; import cn.bootx.platform.daxpay.code.pay.PayChannelEnum; import cn.bootx.platform.daxpay.code.paymodel.AliPayCode; +import cn.bootx.platform.daxpay.core.channel.alipay.entity.AlipayConfig; +import cn.bootx.platform.daxpay.core.channel.alipay.service.*; import cn.bootx.platform.daxpay.core.pay.exception.ExceptionInfo; import cn.bootx.platform.daxpay.core.pay.func.AbsPayStrategy; import cn.bootx.platform.daxpay.core.pay.result.PaySyncResult; -import cn.bootx.platform.daxpay.core.payment.service.PaymentService; -import cn.bootx.platform.daxpay.core.channel.alipay.dao.AlipayConfigManager; -import cn.bootx.platform.daxpay.core.channel.alipay.entity.AlipayConfig; -import cn.bootx.platform.daxpay.core.channel.alipay.service.AliPayCancelService; -import cn.bootx.platform.daxpay.core.channel.alipay.service.AliPayService; -import cn.bootx.platform.daxpay.core.channel.alipay.service.AliPaymentService; -import cn.bootx.platform.daxpay.core.channel.alipay.service.AlipaySyncService; import cn.bootx.platform.daxpay.exception.payment.PayAmountAbnormalException; import cn.bootx.platform.daxpay.exception.payment.PayFailureException; -import cn.bootx.platform.daxpay.param.pay.PayWayParam; import cn.bootx.platform.daxpay.param.channel.alipay.AliPayParam; -import cn.hutool.core.util.CharsetUtil; +import cn.bootx.platform.daxpay.param.pay.PayWayParam; import cn.hutool.core.util.StrUtil; import cn.hutool.json.JSONException; import cn.hutool.json.JSONUtil; -import com.ijpay.alipay.AliPayApiConfig; -import com.ijpay.alipay.AliPayApiConfigKit; import lombok.RequiredArgsConstructor; -import lombok.SneakyThrows; import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Component; import java.math.BigDecimal; import java.util.Map; -import java.util.Objects; import static org.springframework.beans.factory.config.BeanDefinition.SCOPE_PROTOTYPE; @@ -52,12 +41,10 @@ public class AliPayStrategy extends AbsPayStrategy { private final AliPayService aliPayService; + private final AlipayConfigService alipayConfigService; + private final AliPayCancelService aliPayCancelService; - private final AlipayConfigManager alipayConfigManager; - - private final PaymentService paymentService; - private AlipayConfig alipayConfig; private AliPayParam aliPayParam; @@ -163,17 +150,6 @@ public class AliPayStrategy extends AbsPayStrategy { aliPaymentService.updateClose(this.getPayment().getId()); } - /** - * 退款 - */ - @Override - public void doRefundHandler() { - this.initAlipayConfig(this.getPayParam().getMchAppCode()); - aliPayCancelService.refund(this.getPayment(), this.getPayWayParam().getAmount()); - aliPaymentService.updatePayRefund(this.getPayment().getId(), this.getPayWayParam().getAmount()); - paymentService.updateRefundSuccess(this.getPayment(), this.getPayWayParam().getAmount(), PayChannelEnum.ALI); - } - /** * 异步支付单与支付网关进行状态比对 */ @@ -188,46 +164,7 @@ public class AliPayStrategy extends AbsPayStrategy { */ private void initAlipayConfig(String mchAppCode) { // 检查并获取支付宝支付配置 - this.alipayConfig = alipayConfigManager.findByMchAppCode(mchAppCode) - .orElseThrow(() -> new PayFailureException("支付配置不存在")); - this.initApiConfig(this.alipayConfig); - } - - /** - * 初始化IJPay 服务 - */ - @SneakyThrows - private void initApiConfig(AlipayConfig alipayConfig) { - - AliPayApiConfig aliPayApiConfig; - // 公钥 - if (Objects.equals(alipayConfig.getAuthType(), AliPayCode.AUTH_TYPE_KEY)) { - aliPayApiConfig = AliPayApiConfig.builder() - .setAppId(alipayConfig.getAppId()) - .setPrivateKey(alipayConfig.getPrivateKey()) - .setAliPayPublicKey(alipayConfig.getAlipayPublicKey()) - .setCharset(CharsetUtil.UTF_8) - .setServiceUrl(alipayConfig.getServerUrl()) - .setSignType(alipayConfig.getSignType()) - .build(); - } - // 证书 - else if (Objects.equals(alipayConfig.getAuthType(), AliPayCode.AUTH_TYPE_CART)) { - aliPayApiConfig = AliPayApiConfig.builder() - .setAppId(alipayConfig.getAppId()) - .setPrivateKey(alipayConfig.getPrivateKey()) - .setAppCertContent(alipayConfig.getAppCert()) - .setAliPayCertContent(alipayConfig.getAlipayCert()) - .setAliPayRootCertContent(alipayConfig.getAlipayRootCert()) - .setCharset(CharsetUtil.UTF_8) - .setServiceUrl(alipayConfig.getServerUrl()) - .setSignType(alipayConfig.getSignType()) - .buildByCertContent(); - } - else { - throw new BizException("支付宝认证方式不可为空"); - } - AliPayApiConfigKit.setThreadLocalAliPayApiConfig(aliPayApiConfig); + alipayConfigService.initApiConfigByMchAppCode(mchAppCode); } } diff --git a/dax-pay/src/main/java/cn/bootx/platform/daxpay/core/pay/strategy/CashPayStrategy.java b/dax-pay/src/main/java/cn/bootx/platform/daxpay/core/pay/strategy/CashPayStrategy.java index 672f987df..b0c39a2b2 100644 --- a/dax-pay/src/main/java/cn/bootx/platform/daxpay/core/pay/strategy/CashPayStrategy.java +++ b/dax-pay/src/main/java/cn/bootx/platform/daxpay/core/pay/strategy/CashPayStrategy.java @@ -68,13 +68,4 @@ public class CashPayStrategy extends AbsPayStrategy { cashService.close(this.getPayment().getId()); } - /** - * 退款 - */ - @Override - public void doRefundHandler() { - cashService.refund(this.getPayment().getId(), this.getPayWayParam().getAmount()); - paymentService.updateRefundSuccess(this.getPayment(), this.getPayWayParam().getAmount(), PayChannelEnum.CASH); - } - } diff --git a/dax-pay/src/main/java/cn/bootx/platform/daxpay/core/pay/strategy/UnionPayStrategy.java b/dax-pay/src/main/java/cn/bootx/platform/daxpay/core/pay/strategy/UnionPayStrategy.java index 7f6775e1e..b53434a85 100644 --- a/dax-pay/src/main/java/cn/bootx/platform/daxpay/core/pay/strategy/UnionPayStrategy.java +++ b/dax-pay/src/main/java/cn/bootx/platform/daxpay/core/pay/strategy/UnionPayStrategy.java @@ -42,9 +42,4 @@ public class UnionPayStrategy extends AbsPayStrategy { } - @Override - public void doRefundHandler() { - - } - } diff --git a/dax-pay/src/main/java/cn/bootx/platform/daxpay/core/pay/strategy/VoucherStrategy.java b/dax-pay/src/main/java/cn/bootx/platform/daxpay/core/pay/strategy/VoucherPayStrategy.java similarity index 77% rename from dax-pay/src/main/java/cn/bootx/platform/daxpay/core/pay/strategy/VoucherStrategy.java rename to dax-pay/src/main/java/cn/bootx/platform/daxpay/core/pay/strategy/VoucherPayStrategy.java index ffed6ec2d..a20c35707 100644 --- a/dax-pay/src/main/java/cn/bootx/platform/daxpay/core/pay/strategy/VoucherStrategy.java +++ b/dax-pay/src/main/java/cn/bootx/platform/daxpay/core/pay/strategy/VoucherPayStrategy.java @@ -1,12 +1,11 @@ package cn.bootx.platform.daxpay.core.pay.strategy; import cn.bootx.platform.daxpay.code.pay.PayChannelEnum; -import cn.bootx.platform.daxpay.core.channel.voucher.entity.VoucherRecord; -import cn.bootx.platform.daxpay.core.pay.func.AbsPayStrategy; -import cn.bootx.platform.daxpay.core.payment.service.PaymentService; import cn.bootx.platform.daxpay.core.channel.voucher.entity.Voucher; +import cn.bootx.platform.daxpay.core.channel.voucher.entity.VoucherRecord; import cn.bootx.platform.daxpay.core.channel.voucher.service.VoucherPayService; import cn.bootx.platform.daxpay.core.channel.voucher.service.VoucherPaymentService; +import cn.bootx.platform.daxpay.core.pay.func.AbsPayStrategy; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.context.annotation.Scope; @@ -26,14 +25,12 @@ import static org.springframework.beans.factory.config.BeanDefinition.SCOPE_PROT @Scope(SCOPE_PROTOTYPE) @Service @RequiredArgsConstructor -public class VoucherStrategy extends AbsPayStrategy { +public class VoucherPayStrategy extends AbsPayStrategy { private final VoucherPayService voucherPayService; private final VoucherPaymentService voucherPaymentService; - private final PaymentService paymentService; - private List vouchers; @Override @@ -80,19 +77,8 @@ public class VoucherStrategy extends AbsPayStrategy { */ @Override public void doCloseHandler() { - voucherPayService.close(this.getPayment().getId(), this.getPayment().isAsyncPayMode()); + voucherPayService.close(this.getPayment().getId()); voucherPaymentService.updateClose(this.getPayment().getId()); } - /** - * 退款 - */ - @Override - public void doRefundHandler() { - voucherPayService.refund(this.getPayment().getId(), this.getPayWayParam().getAmount(),null); - voucherPaymentService.updateRefund(this.getPayment().getId(), this.getPayWayParam().getAmount()); - paymentService.updateRefundSuccess(this.getPayment(), this.getPayWayParam().getAmount(), - PayChannelEnum.VOUCHER); - } - } diff --git a/dax-pay/src/main/java/cn/bootx/platform/daxpay/core/pay/strategy/WalletPayStrategy.java b/dax-pay/src/main/java/cn/bootx/platform/daxpay/core/pay/strategy/WalletPayStrategy.java index da5385595..8333b6c91 100644 --- a/dax-pay/src/main/java/cn/bootx/platform/daxpay/core/pay/strategy/WalletPayStrategy.java +++ b/dax-pay/src/main/java/cn/bootx/platform/daxpay/core/pay/strategy/WalletPayStrategy.java @@ -8,7 +8,6 @@ import cn.bootx.platform.daxpay.core.channel.wallet.service.WalletPayService; import cn.bootx.platform.daxpay.core.channel.wallet.service.WalletPaymentService; import cn.bootx.platform.daxpay.core.channel.wallet.service.WalletQueryService; import cn.bootx.platform.daxpay.core.pay.func.AbsPayStrategy; -import cn.bootx.platform.daxpay.core.payment.service.PaymentService; import cn.bootx.platform.daxpay.exception.payment.PayFailureException; import cn.bootx.platform.daxpay.exception.waller.WalletBannedException; import cn.bootx.platform.daxpay.exception.waller.WalletLackOfBalanceException; @@ -41,8 +40,6 @@ public class WalletPayStrategy extends AbsPayStrategy { private final WalletQueryService walletQueryService; - private final PaymentService paymentService; - private Wallet wallet; @Override @@ -107,21 +104,8 @@ public class WalletPayStrategy extends AbsPayStrategy { */ @Override public void doCloseHandler() { - if (this.getPayment().isAsyncPayMode()){ - walletPayService.paySuccess(this.getPayment().getId()); - } - walletPayService.close(this.getPayment().getId(),this.getPayment().isAsyncPayMode()); + walletPayService.close(this.getPayment().getId()); walletPaymentService.updateClose(this.getPayment().getId()); } - /** - * 退款 - */ - @Override - public void doRefundHandler() { - walletPayService.refund(this.getPayment().getId(), this.getPayWayParam().getAmount()); - walletPaymentService.updateRefund(this.getPayment().getId(), this.getPayWayParam().getAmount()); - paymentService.updateRefundSuccess(this.getPayment(), this.getPayWayParam().getAmount(), PayChannelEnum.WALLET); - } - } diff --git a/dax-pay/src/main/java/cn/bootx/platform/daxpay/core/pay/strategy/WeChatPayStrategy.java b/dax-pay/src/main/java/cn/bootx/platform/daxpay/core/pay/strategy/WeChatPayStrategy.java index cccad2fb2..438546de7 100644 --- a/dax-pay/src/main/java/cn/bootx/platform/daxpay/core/pay/strategy/WeChatPayStrategy.java +++ b/dax-pay/src/main/java/cn/bootx/platform/daxpay/core/pay/strategy/WeChatPayStrategy.java @@ -3,22 +3,19 @@ package cn.bootx.platform.daxpay.core.pay.strategy; import cn.bootx.platform.common.core.util.BigDecimalUtil; import cn.bootx.platform.daxpay.code.pay.PayChannelEnum; import cn.bootx.platform.daxpay.code.paymodel.WeChatPayCode; -import cn.bootx.platform.daxpay.core.pay.exception.ExceptionInfo; -import cn.bootx.platform.daxpay.core.pay.func.AbsPayStrategy; -import cn.bootx.platform.daxpay.core.pay.result.PaySyncResult; -import cn.bootx.platform.daxpay.core.payment.service.PaymentService; import cn.bootx.platform.daxpay.core.channel.wechat.dao.WeChatPayConfigManager; -import cn.bootx.platform.daxpay.core.channel.wechat.dao.WeChatPaymentManager; import cn.bootx.platform.daxpay.core.channel.wechat.entity.WeChatPayConfig; -import cn.bootx.platform.daxpay.core.channel.wechat.entity.WeChatPayment; import cn.bootx.platform.daxpay.core.channel.wechat.service.WeChatPayCancelService; import cn.bootx.platform.daxpay.core.channel.wechat.service.WeChatPayService; import cn.bootx.platform.daxpay.core.channel.wechat.service.WeChatPaySyncService; import cn.bootx.platform.daxpay.core.channel.wechat.service.WeChatPaymentService; +import cn.bootx.platform.daxpay.core.pay.exception.ExceptionInfo; +import cn.bootx.platform.daxpay.core.pay.func.AbsPayStrategy; +import cn.bootx.platform.daxpay.core.pay.result.PaySyncResult; import cn.bootx.platform.daxpay.exception.payment.PayAmountAbnormalException; import cn.bootx.platform.daxpay.exception.payment.PayFailureException; -import cn.bootx.platform.daxpay.param.pay.PayWayParam; import cn.bootx.platform.daxpay.param.channel.wechat.WeChatPayParam; +import cn.bootx.platform.daxpay.param.pay.PayWayParam; import cn.hutool.core.util.StrUtil; import cn.hutool.json.JSONException; import cn.hutool.json.JSONUtil; @@ -49,14 +46,10 @@ public class WeChatPayStrategy extends AbsPayStrategy { private final WeChatPaymentService weChatPaymentService; - private final WeChatPaymentManager weChatPaymentManager; - private final WeChatPayCancelService weChatPayCancelService; private final WeChatPaySyncService weChatPaySyncService; - private final PaymentService paymentService; - private WeChatPayConfig weChatPayConfig; private WeChatPayParam weChatPayParam; @@ -162,20 +155,6 @@ public class WeChatPayStrategy extends AbsPayStrategy { weChatPaymentService.updateClose(this.getPayment().getId()); } - /** - * 退款 - */ - @Override - public void doRefundHandler() { - this.initWeChatPayConfig(this.getPayParam().getMchAppCode()); - WeChatPayment weChatPayment = weChatPaymentManager.findByPaymentId(this.getPayment().getId()) - .orElseThrow(() -> new PayFailureException("微信支付记录不存在")); - weChatPayCancelService.refund(this.getPayment(), weChatPayment, this.getPayWayParam().getAmount(), - this.weChatPayConfig); - weChatPaymentService.updatePayRefund(weChatPayment, this.getPayWayParam().getAmount()); - paymentService.updateRefundSuccess(this.getPayment(), this.getPayWayParam().getAmount(), PayChannelEnum.WECHAT); - } - /** * 异步支付单与支付网关进行状态比对 */ diff --git a/dax-pay/src/main/java/cn/bootx/platform/daxpay/core/refund/factory/PayRefundStrategyFactory.java b/dax-pay/src/main/java/cn/bootx/platform/daxpay/core/refund/factory/PayRefundStrategyFactory.java new file mode 100644 index 000000000..44270c884 --- /dev/null +++ b/dax-pay/src/main/java/cn/bootx/platform/daxpay/core/refund/factory/PayRefundStrategyFactory.java @@ -0,0 +1,119 @@ +package cn.bootx.platform.daxpay.core.refund.factory; + +import cn.bootx.platform.daxpay.code.pay.PayChannelEnum; +import cn.bootx.platform.daxpay.core.refund.func.AbsPayRefundStrategy; +import cn.bootx.platform.daxpay.core.refund.strategy.*; +import cn.bootx.platform.daxpay.exception.payment.PayUnsupportedMethodException; +import cn.bootx.platform.daxpay.param.refund.RefundModeParam; +import cn.hutool.core.collection.CollectionUtil; +import cn.hutool.extra.spring.SpringUtil; +import lombok.val; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; + +import static cn.bootx.platform.daxpay.code.pay.PayChannelEnum.ASYNC_TYPE_CODE; + +/** + * 退款策略工厂 + * @author xxm + * @since 2023/7/4 + */ +public class PayRefundStrategyFactory { + + /** + * 根据传入的支付通道创建策略 + * @return 支付策略 + */ + public static AbsPayRefundStrategy create(RefundModeParam refundModeParam) { + + AbsPayRefundStrategy strategy = null; + PayChannelEnum channelEnum = PayChannelEnum.findByCode(refundModeParam.getPayChannel()); + switch (channelEnum) { + case ALI: + strategy = SpringUtil.getBean(AliPayRefundStrategy.class); + break; + case WECHAT: + strategy = SpringUtil.getBean(WeChatPayRefundStrategy.class); + break; + case UNION_PAY: + strategy = SpringUtil.getBean(UnionPayRefundStrategy.class); + break; + case CASH: + strategy = SpringUtil.getBean(CashPayRefundStrategy.class); + break; + case WALLET: + strategy = SpringUtil.getBean(WalletPayRefundStrategy.class); + break; + case VOUCHER: + strategy = SpringUtil.getBean(VoucherPayRefundStrategy.class); + break; + case CREDIT_CARD: + break; + case APPLE_PAY: + break; + default: + throw new PayUnsupportedMethodException(); + } + // noinspection ConstantConditions + strategy.setRefundModeParam(refundModeParam); + return strategy; + } + + /** + * 根据传入的支付类型批量创建策略, 异步支付在后面 + */ + public static List createDesc(List refundModeParams) { + return create(refundModeParams, true); + } + + /** + * 根据传入的支付类型批量创建策略, 默认异步支付在前面 + */ + public static List create(List refundModeParams) { + return create(refundModeParams, false); + } + + /** + * 根据传入的支付类型批量创建策略 + * @param refundModeParams 支付类型 + * @return 支付策略 + */ + private static List create(List refundModeParams, boolean description) { + if (CollectionUtil.isEmpty(refundModeParams)) { + return Collections.emptyList(); + } + List list = new ArrayList<>(refundModeParams.size()); + + // 同步支付 + val syncRefundModeParams = refundModeParams.stream() + .filter(Objects::nonNull) + .filter(payModeParam -> !ASYNC_TYPE_CODE.contains(payModeParam.getPayChannel())) + .collect(Collectors.toList()); + + // 异步支付 + val asyncRefundModeParams = refundModeParams.stream() + .filter(Objects::nonNull) + .filter(payModeParam -> ASYNC_TYPE_CODE.contains(payModeParam.getPayChannel())) + .collect(Collectors.toList()); + + List sortList = new ArrayList<>(refundModeParams.size()); + + // 异步在后面 + if (description) { + sortList.addAll(syncRefundModeParams); + sortList.addAll(asyncRefundModeParams); + } + else { + sortList.addAll(asyncRefundModeParams); + sortList.addAll(syncRefundModeParams); + } + + // 此处有一个根据Type的反转排序, + sortList.stream().filter(Objects::nonNull).forEach(payMode -> list.add(create(payMode))); + return list; + } +} diff --git a/dax-pay/src/main/java/cn/bootx/platform/daxpay/core/refund/func/AbsPayRefundStrategy.java b/dax-pay/src/main/java/cn/bootx/platform/daxpay/core/refund/func/AbsPayRefundStrategy.java new file mode 100644 index 000000000..f359062e9 --- /dev/null +++ b/dax-pay/src/main/java/cn/bootx/platform/daxpay/core/refund/func/AbsPayRefundStrategy.java @@ -0,0 +1,61 @@ +package cn.bootx.platform.daxpay.core.refund.func; + +import cn.bootx.platform.daxpay.code.pay.PayChannelEnum; +import cn.bootx.platform.daxpay.core.pay.exception.ExceptionInfo; +import cn.bootx.platform.daxpay.core.payment.entity.Payment; +import cn.bootx.platform.daxpay.param.refund.RefundModeParam; +import cn.bootx.platform.daxpay.param.refund.RefundParam; +import lombok.Getter; +import lombok.Setter; + +/** + * 抽象支付退款策略基类 + * + * @author xxm + * @since 2020/12/11 + */ +@Getter +@Setter +public abstract class AbsPayRefundStrategy { + + /** 支付对象 */ + private Payment payment = null; + + /** 退款参数 */ + private RefundParam refundParam = null; + + /** 当前支付方式退款参数 退款参参数中的与这个不一致, 以这个为准 */ + private RefundModeParam refundModeParam = null; + + /** + * 策略标识 + * @see PayChannelEnum + */ + public abstract PayChannelEnum getType(); + + /** + * 初始化支付的参数 + */ + public void initPayParam(Payment payment, RefundParam refundParam) { + this.payment = payment; + this.refundParam = refundParam; + } + + /** + * 退款前对处理 包含必要的校验以及对Payment对象的创建和保存操作 + */ + public void doBeforeRefundHandler() { + } + + /** + * 退款操作 + */ + public abstract void doRefundHandler(); + + /** + * 退款失败的处理方式 + */ + public void doErrorHandler(ExceptionInfo exceptionInfo) { + } + +} diff --git a/dax-pay/src/main/java/cn/bootx/platform/daxpay/core/refund/func/PayRefundStrategyConsumer.java b/dax-pay/src/main/java/cn/bootx/platform/daxpay/core/refund/func/PayRefundStrategyConsumer.java new file mode 100644 index 000000000..6bba85739 --- /dev/null +++ b/dax-pay/src/main/java/cn/bootx/platform/daxpay/core/refund/func/PayRefundStrategyConsumer.java @@ -0,0 +1,17 @@ +package cn.bootx.platform.daxpay.core.refund.func; + +import cn.bootx.platform.daxpay.core.payment.entity.Payment; + +import java.util.List; + +/** + * 支付退款策略接口 + * @author xxm + * @since 2023/7/5 + */ +@FunctionalInterface +public interface PayRefundStrategyConsumer, S extends Payment> { + + void accept(T t, S s); + +} diff --git a/dax-pay/src/main/java/cn/bootx/platform/daxpay/core/pay/local/AsyncRefundLocal.java b/dax-pay/src/main/java/cn/bootx/platform/daxpay/core/refund/local/AsyncRefundLocal.java similarity index 96% rename from dax-pay/src/main/java/cn/bootx/platform/daxpay/core/pay/local/AsyncRefundLocal.java rename to dax-pay/src/main/java/cn/bootx/platform/daxpay/core/refund/local/AsyncRefundLocal.java index 82a11c373..ee74272b1 100644 --- a/dax-pay/src/main/java/cn/bootx/platform/daxpay/core/pay/local/AsyncRefundLocal.java +++ b/dax-pay/src/main/java/cn/bootx/platform/daxpay/core/refund/local/AsyncRefundLocal.java @@ -1,4 +1,4 @@ -package cn.bootx.platform.daxpay.core.pay.local; +package cn.bootx.platform.daxpay.core.refund.local; import com.alibaba.ttl.TransmittableThreadLocal; diff --git a/dax-pay/src/main/java/cn/bootx/platform/daxpay/core/refund/convert/RefundConvert.java b/dax-pay/src/main/java/cn/bootx/platform/daxpay/core/refund/record/convert/RefundConvert.java similarity index 71% rename from dax-pay/src/main/java/cn/bootx/platform/daxpay/core/refund/convert/RefundConvert.java rename to dax-pay/src/main/java/cn/bootx/platform/daxpay/core/refund/record/convert/RefundConvert.java index 40435992f..14d72fd71 100644 --- a/dax-pay/src/main/java/cn/bootx/platform/daxpay/core/refund/convert/RefundConvert.java +++ b/dax-pay/src/main/java/cn/bootx/platform/daxpay/core/refund/record/convert/RefundConvert.java @@ -1,6 +1,6 @@ -package cn.bootx.platform.daxpay.core.refund.convert; +package cn.bootx.platform.daxpay.core.refund.record.convert; -import cn.bootx.platform.daxpay.core.refund.entity.RefundRecord; +import cn.bootx.platform.daxpay.core.refund.record.entity.RefundRecord; import cn.bootx.platform.daxpay.dto.refund.RefundRecordDto; import org.mapstruct.Mapper; import org.mapstruct.factory.Mappers; diff --git a/dax-pay/src/main/java/cn/bootx/platform/daxpay/core/refund/dao/RefundRecordManager.java b/dax-pay/src/main/java/cn/bootx/platform/daxpay/core/refund/record/dao/RefundRecordManager.java similarity index 90% rename from dax-pay/src/main/java/cn/bootx/platform/daxpay/core/refund/dao/RefundRecordManager.java rename to dax-pay/src/main/java/cn/bootx/platform/daxpay/core/refund/record/dao/RefundRecordManager.java index b6b4d8611..7adaa8017 100644 --- a/dax-pay/src/main/java/cn/bootx/platform/daxpay/core/refund/dao/RefundRecordManager.java +++ b/dax-pay/src/main/java/cn/bootx/platform/daxpay/core/refund/record/dao/RefundRecordManager.java @@ -1,10 +1,10 @@ -package cn.bootx.platform.daxpay.core.refund.dao; +package cn.bootx.platform.daxpay.core.refund.record.dao; import cn.bootx.platform.common.core.rest.param.PageParam; import cn.bootx.platform.common.mybatisplus.base.MpIdEntity; import cn.bootx.platform.common.mybatisplus.impl.BaseManager; import cn.bootx.platform.common.mybatisplus.util.MpUtil; -import cn.bootx.platform.daxpay.core.refund.entity.RefundRecord; +import cn.bootx.platform.daxpay.core.refund.record.entity.RefundRecord; import cn.bootx.platform.daxpay.dto.refund.RefundRecordDto; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import lombok.RequiredArgsConstructor; diff --git a/dax-pay/src/main/java/cn/bootx/platform/daxpay/core/refund/dao/RefundRecordMapper.java b/dax-pay/src/main/java/cn/bootx/platform/daxpay/core/refund/record/dao/RefundRecordMapper.java similarity index 63% rename from dax-pay/src/main/java/cn/bootx/platform/daxpay/core/refund/dao/RefundRecordMapper.java rename to dax-pay/src/main/java/cn/bootx/platform/daxpay/core/refund/record/dao/RefundRecordMapper.java index 1afae7f79..55a4611e4 100644 --- a/dax-pay/src/main/java/cn/bootx/platform/daxpay/core/refund/dao/RefundRecordMapper.java +++ b/dax-pay/src/main/java/cn/bootx/platform/daxpay/core/refund/record/dao/RefundRecordMapper.java @@ -1,6 +1,6 @@ -package cn.bootx.platform.daxpay.core.refund.dao; +package cn.bootx.platform.daxpay.core.refund.record.dao; -import cn.bootx.platform.daxpay.core.refund.entity.RefundRecord; +import cn.bootx.platform.daxpay.core.refund.record.entity.RefundRecord; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import org.apache.ibatis.annotations.Mapper; diff --git a/dax-pay/src/main/java/cn/bootx/platform/daxpay/core/refund/entity/RefundRecord.java b/dax-pay/src/main/java/cn/bootx/platform/daxpay/core/refund/record/entity/RefundRecord.java similarity index 93% rename from dax-pay/src/main/java/cn/bootx/platform/daxpay/core/refund/entity/RefundRecord.java rename to dax-pay/src/main/java/cn/bootx/platform/daxpay/core/refund/record/entity/RefundRecord.java index 1b1b0d123..d47f4e8a4 100644 --- a/dax-pay/src/main/java/cn/bootx/platform/daxpay/core/refund/entity/RefundRecord.java +++ b/dax-pay/src/main/java/cn/bootx/platform/daxpay/core/refund/record/entity/RefundRecord.java @@ -1,10 +1,10 @@ -package cn.bootx.platform.daxpay.core.refund.entity; +package cn.bootx.platform.daxpay.core.refund.record.entity; import cn.bootx.platform.common.core.function.EntityBaseFunction; import cn.bootx.platform.common.mybatisplus.base.MpBaseEntity; import cn.bootx.platform.common.mybatisplus.handler.JacksonRawTypeHandler; import cn.bootx.platform.daxpay.code.pay.PayStatusCode; -import cn.bootx.platform.daxpay.core.refund.convert.RefundConvert; +import cn.bootx.platform.daxpay.core.refund.record.convert.RefundConvert; import cn.bootx.platform.daxpay.dto.payment.RefundableInfo; import cn.bootx.platform.daxpay.dto.refund.RefundRecordDto; import com.baomidou.mybatisplus.annotation.TableField; diff --git a/dax-pay/src/main/java/cn/bootx/platform/daxpay/core/refund/service/RefundRecordService.java b/dax-pay/src/main/java/cn/bootx/platform/daxpay/core/refund/record/service/RefundRecordService.java similarity index 84% rename from dax-pay/src/main/java/cn/bootx/platform/daxpay/core/refund/service/RefundRecordService.java rename to dax-pay/src/main/java/cn/bootx/platform/daxpay/core/refund/record/service/RefundRecordService.java index 30961d71d..46133c530 100644 --- a/dax-pay/src/main/java/cn/bootx/platform/daxpay/core/refund/service/RefundRecordService.java +++ b/dax-pay/src/main/java/cn/bootx/platform/daxpay/core/refund/record/service/RefundRecordService.java @@ -1,11 +1,11 @@ -package cn.bootx.platform.daxpay.core.refund.service; +package cn.bootx.platform.daxpay.core.refund.record.service; import cn.bootx.platform.common.core.exception.DataNotExistException; import cn.bootx.platform.common.core.rest.PageResult; import cn.bootx.platform.common.core.rest.param.PageParam; import cn.bootx.platform.common.mybatisplus.util.MpUtil; -import cn.bootx.platform.daxpay.core.refund.dao.RefundRecordManager; -import cn.bootx.platform.daxpay.core.refund.entity.RefundRecord; +import cn.bootx.platform.daxpay.core.refund.record.dao.RefundRecordManager; +import cn.bootx.platform.daxpay.core.refund.record.entity.RefundRecord; import cn.bootx.platform.daxpay.dto.refund.RefundRecordDto; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import lombok.RequiredArgsConstructor; diff --git a/dax-pay/src/main/java/cn/bootx/platform/daxpay/core/pay/service/PayRefundService.java b/dax-pay/src/main/java/cn/bootx/platform/daxpay/core/refund/service/PayRefundService.java similarity index 80% rename from dax-pay/src/main/java/cn/bootx/platform/daxpay/core/pay/service/PayRefundService.java rename to dax-pay/src/main/java/cn/bootx/platform/daxpay/core/refund/service/PayRefundService.java index 809edc9a6..8479f636a 100644 --- a/dax-pay/src/main/java/cn/bootx/platform/daxpay/core/pay/service/PayRefundService.java +++ b/dax-pay/src/main/java/cn/bootx/platform/daxpay/core/refund/service/PayRefundService.java @@ -1,24 +1,21 @@ -package cn.bootx.platform.daxpay.core.pay.service; +package cn.bootx.platform.daxpay.core.refund.service; import cn.bootx.platform.common.core.util.BigDecimalUtil; import cn.bootx.platform.common.spring.util.WebServletUtil; import cn.bootx.platform.daxpay.code.pay.PayStatusCode; -import cn.bootx.platform.daxpay.core.pay.builder.PaymentBuilder; -import cn.bootx.platform.daxpay.core.pay.factory.PayStrategyFactory; -import cn.bootx.platform.daxpay.core.pay.func.AbsPayStrategy; -import cn.bootx.platform.daxpay.core.pay.func.PayStrategyConsumer; -import cn.bootx.platform.daxpay.core.pay.local.AsyncRefundLocal; import cn.bootx.platform.daxpay.core.payment.dao.PaymentManager; import cn.bootx.platform.daxpay.core.payment.entity.Payment; import cn.bootx.platform.daxpay.core.payment.service.PaymentService; -import cn.bootx.platform.daxpay.core.refund.dao.RefundRecordManager; -import cn.bootx.platform.daxpay.core.refund.entity.RefundRecord; +import cn.bootx.platform.daxpay.core.refund.factory.PayRefundStrategyFactory; +import cn.bootx.platform.daxpay.core.refund.func.AbsPayRefundStrategy; +import cn.bootx.platform.daxpay.core.refund.func.PayRefundStrategyConsumer; +import cn.bootx.platform.daxpay.core.refund.local.AsyncRefundLocal; +import cn.bootx.platform.daxpay.core.refund.record.dao.RefundRecordManager; +import cn.bootx.platform.daxpay.core.refund.record.entity.RefundRecord; import cn.bootx.platform.daxpay.dto.payment.RefundableInfo; import cn.bootx.platform.daxpay.exception.payment.PayAmountAbnormalException; import cn.bootx.platform.daxpay.exception.payment.PayFailureException; import cn.bootx.platform.daxpay.exception.payment.PayUnsupportedMethodException; -import cn.bootx.platform.daxpay.param.pay.PayWayParam; -import cn.bootx.platform.daxpay.param.pay.PayParam; import cn.bootx.platform.daxpay.param.refund.RefundModeParam; import cn.bootx.platform.daxpay.param.refund.RefundParam; import cn.bootx.platform.starter.auth.util.SecurityUtil; @@ -67,13 +64,12 @@ public class PayRefundService { @Transactional(rollbackFor = Exception.class) public void refund(RefundParam refundParam) { Payment payment = paymentService.findByBusinessId(refundParam.getBusinessId()) - .orElseThrow(() -> new PayFailureException("未找到支付单")); - - this.refundPayment(payment, refundParam.getRefundModeParams()); + .orElseThrow(() -> new PayFailureException("未找到支付单")); + this.refundPayment(payment, refundParam); } /** - * 根据业务id取消支付记录 + * 根据业务ID全额退款 */ @Transactional(rollbackFor = Exception.class) public void refundByBusinessId(String businessId) { @@ -83,14 +79,19 @@ public class PayRefundService { .stream() .map(o -> new RefundModeParam().setPayChannel(o.getPayChannel()).setAmount(o.getAmount())) .collect(Collectors.toList()); - this.refundPayment(payment, refundModeParams); + RefundParam refundParam = new RefundParam() + .setBusinessId(businessId) + .setRefundModeParams(refundModeParams); + this.refundPayment(payment, refundParam); } /** * 退款 */ - private void refundPayment(Payment payment, List refundModeParams) { + private void refundPayment(Payment payment,RefundParam refundParam) { + + List refundModeParams = refundParam.getRefundModeParams(); // 状态判断, 支付中/失败/撤销不处理 List tradesStatus = Arrays.asList(TRADE_PROGRESS, TRADE_CANCEL, TRADE_FAIL); if (tradesStatus.contains(payment.getPayStatus())) { @@ -98,32 +99,26 @@ public class PayRefundService { } // 过滤退款金额为0的支付通道参数 - refundModeParams - .removeIf(refundModeParam -> BigDecimalUtil.compareTo(refundModeParam.getAmount(), BigDecimal.ZERO) == 0); - // 获取 paymentParam - PayParam payParam = PaymentBuilder.buildPayParamByPayment(payment); + refundModeParams.removeIf(refundModeParam -> BigDecimalUtil.compareTo(refundModeParam.getAmount(), BigDecimal.ZERO) == 0); // 退款参数检查 this.payModeCheck(refundModeParams, payment.getRefundableInfo()); // 1.获取退款参数方式,通过工厂生成对应的策略组 - List payWayParams = refundModeParams.stream() - .map(RefundModeParam::toPayModeParam) - .collect(Collectors.toList()); - List paymentStrategyList = PayStrategyFactory.create(payWayParams); - if (CollectionUtil.isEmpty(paymentStrategyList)) { + List payRefundStrategies = PayRefundStrategyFactory.create(refundModeParams); + if (CollectionUtil.isEmpty(payRefundStrategies)) { throw new PayUnsupportedMethodException(); } // 2.初始化支付的参数 - for (AbsPayStrategy paymentStrategy : paymentStrategyList) { - paymentStrategy.initPayParam(payment, payParam); + for (AbsPayRefundStrategy refundStrategy : payRefundStrategies) { + refundStrategy.initPayParam(payment, refundParam); } // 3.执行退款 - this.doHandler(payment, paymentStrategyList, (strategyList, paymentObj) -> { + this.doHandler(payment, payRefundStrategies, (strategyList, paymentObj) -> { // 发起支付成功进行的执行方法 try { - strategyList.forEach(AbsPayStrategy::doRefundHandler); + strategyList.forEach(AbsPayRefundStrategy::doRefundHandler); } catch (Exception e) { // 记录退款失败的记录 @@ -165,12 +160,11 @@ public class PayRefundService { /** * 处理方法 * @param payment 支付记录 - * @param strategyList 支付策略 + * @param strategyList 退款策略 * @param successCallback 成功操作 */ - private void doHandler(Payment payment, List strategyList, - PayStrategyConsumer, Payment> successCallback) { - + private void doHandler(Payment payment, List strategyList, + PayRefundStrategyConsumer, Payment> successCallback) { try { // 执行 successCallback.accept(strategyList, payment); diff --git a/dax-pay/src/main/java/cn/bootx/platform/daxpay/core/refund/strategy/AliPayRefundStrategy.java b/dax-pay/src/main/java/cn/bootx/platform/daxpay/core/refund/strategy/AliPayRefundStrategy.java new file mode 100644 index 000000000..00864ce86 --- /dev/null +++ b/dax-pay/src/main/java/cn/bootx/platform/daxpay/core/refund/strategy/AliPayRefundStrategy.java @@ -0,0 +1,60 @@ +package cn.bootx.platform.daxpay.core.refund.strategy; + +import cn.bootx.platform.daxpay.code.pay.PayChannelEnum; +import cn.bootx.platform.daxpay.core.channel.alipay.service.AliPayCancelService; +import cn.bootx.platform.daxpay.core.channel.alipay.service.AliPaymentService; +import cn.bootx.platform.daxpay.core.channel.alipay.service.AlipayConfigService; +import cn.bootx.platform.daxpay.core.payment.service.PaymentService; +import cn.bootx.platform.daxpay.core.refund.func.AbsPayRefundStrategy; +import lombok.RequiredArgsConstructor; +import org.springframework.context.annotation.Scope; +import org.springframework.stereotype.Component; + +import static org.springframework.beans.factory.config.BeanDefinition.SCOPE_PROTOTYPE; + +/** + * 支付宝退款 + * @author xxm + * @since 2023/7/4 + */ +@Scope(SCOPE_PROTOTYPE) +@Component +@RequiredArgsConstructor +public class AliPayRefundStrategy extends AbsPayRefundStrategy { + + private final AlipayConfigService alipayConfigService; + private final AliPaymentService aliPaymentService; + private final AliPayCancelService aliPayCancelService; + private final PaymentService paymentService; + + /** + * 策略标识 + * + * @see PayChannelEnum + */ + @Override + public PayChannelEnum getType() { + return PayChannelEnum.ALI; + } + + + /** + * 退款前前操作 + */ + @Override + public void doBeforeRefundHandler() { + alipayConfigService.initApiConfigByMchAppCode(this.getPayment().getMchAppCode()); + } + + /** + * 退款 + */ + @Override + public void doRefundHandler() { + aliPayCancelService.refund(this.getPayment(), this.getRefundModeParam().getAmount()); + aliPaymentService.updatePayRefund(this.getPayment().getId(), this.getRefundModeParam().getAmount()); + paymentService.updateRefundSuccess(this.getPayment(), this.getRefundModeParam().getAmount(), PayChannelEnum.ALI); + } + + +} diff --git a/dax-pay/src/main/java/cn/bootx/platform/daxpay/core/refund/strategy/CashPayRefundStrategy.java b/dax-pay/src/main/java/cn/bootx/platform/daxpay/core/refund/strategy/CashPayRefundStrategy.java new file mode 100644 index 000000000..7ff58e2e9 --- /dev/null +++ b/dax-pay/src/main/java/cn/bootx/platform/daxpay/core/refund/strategy/CashPayRefundStrategy.java @@ -0,0 +1,44 @@ +package cn.bootx.platform.daxpay.core.refund.strategy; + +import cn.bootx.platform.daxpay.code.pay.PayChannelEnum; +import cn.bootx.platform.daxpay.core.channel.cash.service.CashService; +import cn.bootx.platform.daxpay.core.payment.service.PaymentService; +import cn.bootx.platform.daxpay.core.refund.func.AbsPayRefundStrategy; +import lombok.RequiredArgsConstructor; +import org.springframework.context.annotation.Scope; +import org.springframework.stereotype.Component; + +import static org.springframework.beans.factory.config.BeanDefinition.SCOPE_PROTOTYPE; + +/** + * 现金支付退款 + * @author xxm + * @since 2023/7/5 + */ +@Scope(SCOPE_PROTOTYPE) +@Component +@RequiredArgsConstructor +public class CashPayRefundStrategy extends AbsPayRefundStrategy { + + private final CashService cashService; + private final PaymentService paymentService; + + /** + * 策略标识 + * + * @see PayChannelEnum + */ + @Override + public PayChannelEnum getType() { + return PayChannelEnum.CASH; + } + + /** + * 退款 + */ + @Override + public void doRefundHandler() { + cashService.refund(this.getPayment().getId(), this.getRefundModeParam().getAmount()); + paymentService.updateRefundSuccess(this.getPayment(), this.getRefundModeParam().getAmount(), PayChannelEnum.CASH); + } +} diff --git a/dax-pay/src/main/java/cn/bootx/platform/daxpay/core/refund/strategy/UnionPayRefundStrategy.java b/dax-pay/src/main/java/cn/bootx/platform/daxpay/core/refund/strategy/UnionPayRefundStrategy.java new file mode 100644 index 000000000..142ff8f77 --- /dev/null +++ b/dax-pay/src/main/java/cn/bootx/platform/daxpay/core/refund/strategy/UnionPayRefundStrategy.java @@ -0,0 +1,37 @@ +package cn.bootx.platform.daxpay.core.refund.strategy; + +import cn.bootx.platform.daxpay.code.pay.PayChannelEnum; +import cn.bootx.platform.daxpay.core.refund.func.AbsPayRefundStrategy; +import lombok.RequiredArgsConstructor; +import org.springframework.context.annotation.Scope; +import org.springframework.stereotype.Component; + +import static org.springframework.beans.factory.config.BeanDefinition.SCOPE_PROTOTYPE; + +/** + * 云闪付支付退款 + * @author xxm + * @since 2023/7/5 + */ +@Scope(SCOPE_PROTOTYPE) +@Component +@RequiredArgsConstructor +public class UnionPayRefundStrategy extends AbsPayRefundStrategy { + /** + * 策略标识 + * + * @see PayChannelEnum + */ + @Override + public PayChannelEnum getType() { + return PayChannelEnum.UNION_PAY; + } + + /** + * 退款 + */ + @Override + public void doRefundHandler() { + + } +} diff --git a/dax-pay/src/main/java/cn/bootx/platform/daxpay/core/refund/strategy/VoucherPayRefundStrategy.java b/dax-pay/src/main/java/cn/bootx/platform/daxpay/core/refund/strategy/VoucherPayRefundStrategy.java new file mode 100644 index 000000000..3da002e0e --- /dev/null +++ b/dax-pay/src/main/java/cn/bootx/platform/daxpay/core/refund/strategy/VoucherPayRefundStrategy.java @@ -0,0 +1,65 @@ +package cn.bootx.platform.daxpay.core.refund.strategy; + +import cn.bootx.platform.daxpay.code.pay.PayChannelEnum; +import cn.bootx.platform.daxpay.core.channel.voucher.service.VoucherPayService; +import cn.bootx.platform.daxpay.core.channel.voucher.service.VoucherPaymentService; +import cn.bootx.platform.daxpay.core.payment.service.PaymentService; +import cn.bootx.platform.daxpay.core.refund.func.AbsPayRefundStrategy; +import cn.bootx.platform.daxpay.param.channel.voucher.VoucherRefundParam; +import cn.bootx.platform.daxpay.param.refund.RefundModeParam; +import cn.hutool.core.util.StrUtil; +import cn.hutool.json.JSONUtil; +import lombok.RequiredArgsConstructor; +import org.springframework.context.annotation.Scope; +import org.springframework.stereotype.Component; + +import static org.springframework.beans.factory.config.BeanDefinition.SCOPE_PROTOTYPE; + +/** + * 储值卡支付退款 + * @author xxm + * @since 2023/7/5 + */ +@Scope(SCOPE_PROTOTYPE) +@Component +@RequiredArgsConstructor +public class VoucherPayRefundStrategy extends AbsPayRefundStrategy { + private final VoucherPayService voucherPayService; + private final VoucherPaymentService voucherPaymentService; + private final PaymentService paymentService; + + private VoucherRefundParam voucherRefundParam; + + /** + * 策略标识 + * + * @see PayChannelEnum + */ + @Override + public PayChannelEnum getType() { + return PayChannelEnum.VOUCHER; + } + + /** + * 退款前对处理 + */ + @Override + public void doBeforeRefundHandler() { + RefundModeParam refundModeParam = this.getRefundModeParam(); + this.voucherRefundParam = new VoucherRefundParam(); + if (StrUtil.isNotBlank(refundModeParam.getExtraParamsJson())){ + this.voucherRefundParam = JSONUtil.toBean(refundModeParam.getExtraParamsJson(), VoucherRefundParam.class); + } + } + + /** + * 退款 + */ + @Override + public void doRefundHandler() { + voucherPayService.refund(this.getPayment().getId(), this.getRefundModeParam().getAmount(),voucherRefundParam); + voucherPaymentService.updateRefund(this.getPayment().getId(), this.getRefundModeParam().getAmount()); + paymentService.updateRefundSuccess(this.getPayment(), this.getRefundModeParam().getAmount(), + PayChannelEnum.VOUCHER); + } +} diff --git a/dax-pay/src/main/java/cn/bootx/platform/daxpay/core/refund/strategy/WalletPayRefundStrategy.java b/dax-pay/src/main/java/cn/bootx/platform/daxpay/core/refund/strategy/WalletPayRefundStrategy.java new file mode 100644 index 000000000..8a87942d0 --- /dev/null +++ b/dax-pay/src/main/java/cn/bootx/platform/daxpay/core/refund/strategy/WalletPayRefundStrategy.java @@ -0,0 +1,45 @@ +package cn.bootx.platform.daxpay.core.refund.strategy; + +import cn.bootx.platform.daxpay.code.pay.PayChannelEnum; +import cn.bootx.platform.daxpay.core.channel.wallet.service.WalletPayService; +import cn.bootx.platform.daxpay.core.channel.wallet.service.WalletPaymentService; +import cn.bootx.platform.daxpay.core.payment.service.PaymentService; +import cn.bootx.platform.daxpay.core.refund.func.AbsPayRefundStrategy; +import lombok.RequiredArgsConstructor; +import org.springframework.context.annotation.Scope; +import org.springframework.stereotype.Component; + +import static org.springframework.beans.factory.config.BeanDefinition.SCOPE_PROTOTYPE; + +/** + * 钱包支付退款 + * @author xxm + * @since 2023/7/5 + */ +@Scope(SCOPE_PROTOTYPE) +@Component +@RequiredArgsConstructor +public class WalletPayRefundStrategy extends AbsPayRefundStrategy { + private final WalletPayService walletPayService; + private final WalletPaymentService walletPaymentService; + private final PaymentService paymentService; + /** + * 策略标识 + * + * @see PayChannelEnum + */ + @Override + public PayChannelEnum getType() { + return PayChannelEnum.WALLET; + } + + /** + * 退款 + */ + @Override + public void doRefundHandler() { + walletPayService.refund(this.getPayment().getId(), this.getRefundModeParam().getAmount()); + walletPaymentService.updateRefund(this.getPayment().getId(), this.getRefundModeParam().getAmount()); + paymentService.updateRefundSuccess(this.getPayment(), this.getRefundModeParam().getAmount(), PayChannelEnum.WALLET); + } +} diff --git a/dax-pay/src/main/java/cn/bootx/platform/daxpay/core/refund/strategy/WeChatPayRefundStrategy.java b/dax-pay/src/main/java/cn/bootx/platform/daxpay/core/refund/strategy/WeChatPayRefundStrategy.java new file mode 100644 index 000000000..5d7d1b9f4 --- /dev/null +++ b/dax-pay/src/main/java/cn/bootx/platform/daxpay/core/refund/strategy/WeChatPayRefundStrategy.java @@ -0,0 +1,77 @@ +package cn.bootx.platform.daxpay.core.refund.strategy; + +import cn.bootx.platform.daxpay.code.pay.PayChannelEnum; +import cn.bootx.platform.daxpay.core.channel.wechat.dao.WeChatPayConfigManager; +import cn.bootx.platform.daxpay.core.channel.wechat.dao.WeChatPaymentManager; +import cn.bootx.platform.daxpay.core.channel.wechat.entity.WeChatPayConfig; +import cn.bootx.platform.daxpay.core.channel.wechat.entity.WeChatPayment; +import cn.bootx.platform.daxpay.core.channel.wechat.service.WeChatPayCancelService; +import cn.bootx.platform.daxpay.core.channel.wechat.service.WeChatPaymentService; +import cn.bootx.platform.daxpay.core.payment.service.PaymentService; +import cn.bootx.platform.daxpay.core.refund.func.AbsPayRefundStrategy; +import cn.bootx.platform.daxpay.exception.payment.PayFailureException; +import lombok.RequiredArgsConstructor; +import org.springframework.context.annotation.Scope; +import org.springframework.stereotype.Component; + +import static org.springframework.beans.factory.config.BeanDefinition.SCOPE_PROTOTYPE; + +/** + * 微信支付退款 + * @author xxm + * @since 2023/7/5 + */ +@Scope(SCOPE_PROTOTYPE) +@Component +@RequiredArgsConstructor +public class WeChatPayRefundStrategy extends AbsPayRefundStrategy { + + private final WeChatPaymentManager weChatPaymentManager; + private final WeChatPayConfigManager weChatPayConfigManager; + + private final WeChatPayCancelService weChatPayCancelService; + private final WeChatPaymentService weChatPaymentService; + private final PaymentService paymentService; + + + private WeChatPayConfig weChatPayConfig; + + /** + * 策略标识 + * + * @see PayChannelEnum + */ + @Override + public PayChannelEnum getType() { + return PayChannelEnum.WECHAT; + } + + /** + * 退款前对处理 包含必要的校验以及对Payment对象的创建和保存操作 + */ + @Override + public void doBeforeRefundHandler() { + this.weChatPayConfig = weChatPayConfigManager.findByMchAppCode(this.getPayment().getMchAppCode()) + .orElseThrow(() -> new PayFailureException("支付配置不存在")); + } + + /** + * 退款 + */ + @Override + public void doRefundHandler() { + WeChatPayment weChatPayment = weChatPaymentManager.findByPaymentId(this.getPayment().getId()) + .orElseThrow(() -> new PayFailureException("微信支付记录不存在")); + weChatPayCancelService.refund(this.getPayment(), weChatPayment, this.getRefundModeParam().getAmount(), + this.weChatPayConfig); + weChatPaymentService.updatePayRefund(weChatPayment, this.getRefundModeParam().getAmount()); + paymentService.updateRefundSuccess(this.getPayment(), this.getRefundModeParam().getAmount(), PayChannelEnum.WECHAT); + } + /** + * 初始化微信支付 + */ + private void initWeChatPayConfig(String appCode) { + // 检查并获取微信支付配置 + } + +} diff --git a/dax-pay/src/main/java/cn/bootx/platform/daxpay/param/channel/voucher/VoucherGenerationParam.java b/dax-pay/src/main/java/cn/bootx/platform/daxpay/param/channel/voucher/VoucherGenerationParam.java index b710a987f..0e59618cc 100644 --- a/dax-pay/src/main/java/cn/bootx/platform/daxpay/param/channel/voucher/VoucherGenerationParam.java +++ b/dax-pay/src/main/java/cn/bootx/platform/daxpay/param/channel/voucher/VoucherGenerationParam.java @@ -37,9 +37,9 @@ public class VoucherGenerationParam { private LocalDateTime endTime; /** - * @see VoucherCode + * @see VoucherCode#STATUS_NORMAL */ @Schema(description = "默认状态") - private Integer status; + private String status; } diff --git a/dax-pay/src/main/java/cn/bootx/platform/daxpay/param/refund/RefundModeParam.java b/dax-pay/src/main/java/cn/bootx/platform/daxpay/param/refund/RefundModeParam.java index d5c488eb5..c62af7f03 100644 --- a/dax-pay/src/main/java/cn/bootx/platform/daxpay/param/refund/RefundModeParam.java +++ b/dax-pay/src/main/java/cn/bootx/platform/daxpay/param/refund/RefundModeParam.java @@ -4,7 +4,6 @@ import cn.bootx.platform.daxpay.code.pay.PayChannelEnum; import cn.bootx.platform.daxpay.dto.payment.RefundableInfo; import cn.bootx.platform.daxpay.param.channel.voucher.VoucherRefundParam; import cn.bootx.platform.daxpay.param.channel.wallet.WalletRefundParam; -import cn.bootx.platform.daxpay.param.pay.PayWayParam; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import lombok.experimental.Accessors; @@ -38,12 +37,6 @@ public class RefundModeParam { @Schema(description = "扩展参数的json字符串") private String extraParamsJson; - /** - * 转换成支付方式参数 - */ - public PayWayParam toPayModeParam() { - return new PayWayParam().setPayChannel(getPayChannel()).setAmount(getAmount()); - } /** * 转换成退款方式记录对象 diff --git a/dax-start/src/main/resources/application-dev.yml b/dax-start/src/main/resources/application-dev.yml index b19341849..8835b2600 100644 --- a/dax-start/src/main/resources/application-dev.yml +++ b/dax-start/src/main/resources/application-dev.yml @@ -20,6 +20,13 @@ spring: host: 127.0.0.1 port: 6379 database: 1 + lettuce: + cluster: + refresh: + # 自适应拓扑刷新 + adaptive: true + # 群集拓扑刷新周期 + period: 60s # 如果不使用MQ的话, 可以将项目中 @EnableRabbit 给注释掉, 就不会一直报错了 rabbitmq: # 虚拟主机