mirror of
https://gitee.com/dromara/dax-pay
synced 2026-08-04 20:36:24 +08:00
ref 从支付策略中拆分出退款操作
This commit is contained in:
@@ -34,7 +34,7 @@ public interface VoucherCode {
|
||||
String LOG_UNFREEZE_BALANCE = "unfreeze";
|
||||
|
||||
/**
|
||||
* 钱包日志-解冻并扣减余额
|
||||
* 钱包日志-扣减并解冻余额
|
||||
*/
|
||||
String LOG_REDUCE_AND_UNFREEZE_BALANCE = "reduceAndUnfreeze";
|
||||
|
||||
|
||||
@@ -41,11 +41,6 @@ public interface WalletCode {
|
||||
*/
|
||||
String LOG_FREEZE_BALANCE = "freeze";
|
||||
|
||||
/**
|
||||
* 钱包日志-解冻额度
|
||||
*/
|
||||
String LOG_UNFREEZE_BALANCE = "unfreeze";
|
||||
|
||||
/**
|
||||
* 钱包日志-解冻并扣减余额
|
||||
*/
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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<VoucherMapper, Voucher> {
|
||||
/**
|
||||
* 更改状态
|
||||
*/
|
||||
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<Long> ids, int status) {
|
||||
this.lambdaUpdate().in(MpIdEntity::getId, ids).set(Voucher::getStatus, status).update();
|
||||
public void changeStatusBatch(List<Long> 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();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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<VoucherRecord> freezeBalance(BigDecimal amount, Payment payment, List<Voucher> vouchers){
|
||||
List<VoucherLog> 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<VoucherRecord> voucherRecords = voucherPayment.getVoucherRecords();
|
||||
|
||||
List<String> cardNoList = voucherRecords.stream()
|
||||
.map(VoucherRecord::getCardNo)
|
||||
.collect(Collectors.toList());
|
||||
List<Voucher> vouchers = voucherManager.findByCardNoList(cardNoList);
|
||||
List<VoucherLog> 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<VoucherLog> voucherLogs = voucherLogManager.findByPaymentIdAndType(paymentId, VoucherCode.LOG_PAY);
|
||||
// 查出关联的储值卡
|
||||
Map<Long, VoucherLog> voucherLogMap = voucherLogs.stream()
|
||||
.collect(Collectors.toMap(VoucherLog::getVoucherId, Function.identity()));
|
||||
List<Voucher> vouchers = voucherManager.findAllByIds(voucherLogMap.keySet());
|
||||
// 执行退款并记录日志
|
||||
List<VoucherLog> 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<String> cardNoList = voucherPayment.getVoucherRecords().stream()
|
||||
.map(VoucherRecord::getCardNo)
|
||||
.collect(Collectors.toList());
|
||||
List<Voucher> vouchers = voucherManager.findByCardNoList(cardNoList);
|
||||
// 解冻额度和记录日志
|
||||
List<VoucherLog> 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);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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<Wallet> 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());
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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<PayWayParam> 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<PayWayParam> 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<PayWayParam> sortList = new ArrayList<>(payWayParamList.size());
|
||||
|
||||
@@ -93,11 +93,6 @@ public abstract class AbsPayStrategy {
|
||||
*/
|
||||
public abstract void doCloseHandler();
|
||||
|
||||
/**
|
||||
* 退款
|
||||
*/
|
||||
public abstract void doRefundHandler();
|
||||
|
||||
/**
|
||||
* 异步支付单与支付网关进行状态比对
|
||||
* @see PaySyncStatus
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -42,9 +42,4 @@ public class UnionPayStrategy extends AbsPayStrategy {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doRefundHandler() {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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<Voucher> 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);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
* 异步支付单与支付网关进行状态比对
|
||||
*/
|
||||
|
||||
@@ -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<AbsPayRefundStrategy> createDesc(List<RefundModeParam> refundModeParams) {
|
||||
return create(refundModeParams, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据传入的支付类型批量创建策略, 默认异步支付在前面
|
||||
*/
|
||||
public static List<AbsPayRefundStrategy> create(List<RefundModeParam> refundModeParams) {
|
||||
return create(refundModeParams, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据传入的支付类型批量创建策略
|
||||
* @param refundModeParams 支付类型
|
||||
* @return 支付策略
|
||||
*/
|
||||
private static List<AbsPayRefundStrategy> create(List<RefundModeParam> refundModeParams, boolean description) {
|
||||
if (CollectionUtil.isEmpty(refundModeParams)) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
List<AbsPayRefundStrategy> 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<RefundModeParam> 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;
|
||||
}
|
||||
}
|
||||
@@ -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) {
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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<T extends List<AbsPayRefundStrategy>, S extends Payment> {
|
||||
|
||||
void accept(T t, S s);
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
@@ -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<RefundModeParam> refundModeParams) {
|
||||
private void refundPayment(Payment payment,RefundParam refundParam) {
|
||||
|
||||
List<RefundModeParam> refundModeParams = refundParam.getRefundModeParams();
|
||||
// 状态判断, 支付中/失败/撤销不处理
|
||||
List<String> 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<PayWayParam> payWayParams = refundModeParams.stream()
|
||||
.map(RefundModeParam::toPayModeParam)
|
||||
.collect(Collectors.toList());
|
||||
List<AbsPayStrategy> paymentStrategyList = PayStrategyFactory.create(payWayParams);
|
||||
if (CollectionUtil.isEmpty(paymentStrategyList)) {
|
||||
List<AbsPayRefundStrategy> 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<AbsPayStrategy> strategyList,
|
||||
PayStrategyConsumer<List<AbsPayStrategy>, Payment> successCallback) {
|
||||
|
||||
private void doHandler(Payment payment, List<AbsPayRefundStrategy> strategyList,
|
||||
PayRefundStrategyConsumer<List<AbsPayRefundStrategy>, Payment> successCallback) {
|
||||
try {
|
||||
// 执行
|
||||
successCallback.accept(strategyList, payment);
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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() {
|
||||
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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) {
|
||||
// 检查并获取微信支付配置
|
||||
}
|
||||
|
||||
}
|
||||
@@ -37,9 +37,9 @@ public class VoucherGenerationParam {
|
||||
private LocalDateTime endTime;
|
||||
|
||||
/**
|
||||
* @see VoucherCode
|
||||
* @see VoucherCode#STATUS_NORMAL
|
||||
*/
|
||||
@Schema(description = "默认状态")
|
||||
private Integer status;
|
||||
private String status;
|
||||
|
||||
}
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
/**
|
||||
* 转换成退款方式记录对象
|
||||
|
||||
@@ -20,6 +20,13 @@ spring:
|
||||
host: 127.0.0.1
|
||||
port: 6379
|
||||
database: 1
|
||||
lettuce:
|
||||
cluster:
|
||||
refresh:
|
||||
# 自适应拓扑刷新
|
||||
adaptive: true
|
||||
# 群集拓扑刷新周期
|
||||
period: 60s
|
||||
# 如果不使用MQ的话, 可以将项目中 @EnableRabbit 给注释掉, 就不会一直报错了
|
||||
rabbitmq:
|
||||
# 虚拟主机
|
||||
|
||||
Reference in New Issue
Block a user