mirror of
https://gitee.com/dromara/dax-pay.git
synced 2025-09-06 12:39:38 +00:00
ref 统一交易调整模式更改为分开处理
This commit is contained in:
@@ -58,10 +58,6 @@ public class CallbackLocal {
|
||||
*/
|
||||
private PayCallbackStatusEnum callbackStatus = PayCallbackStatusEnum.SUCCESS;
|
||||
|
||||
|
||||
/** 调整号 */
|
||||
private String adjustNo;
|
||||
|
||||
/** 提示信息 */
|
||||
private String errorMsg;
|
||||
}
|
||||
|
@@ -1,17 +1,17 @@
|
||||
package cn.daxpay.single.service.core.channel.alipay.service;
|
||||
|
||||
import cn.bootx.platform.common.core.util.LocalDateTimeUtil;
|
||||
import cn.bootx.platform.common.core.function.CollectorsFunction;
|
||||
import cn.bootx.platform.common.mybatisplus.base.MpIdEntity;
|
||||
import cn.daxpay.single.core.code.AllocDetailResultEnum;
|
||||
import cn.daxpay.single.core.exception.TradeFailException;
|
||||
import cn.daxpay.single.core.util.PayUtil;
|
||||
import cn.daxpay.single.service.code.AliPayCode;
|
||||
import cn.daxpay.single.service.common.local.PaymentContextLocal;
|
||||
import cn.daxpay.single.service.core.channel.alipay.entity.AliPayConfig;
|
||||
import cn.daxpay.single.service.core.order.allocation.entity.AllocOrder;
|
||||
import cn.daxpay.single.service.core.order.allocation.entity.AllocOrderDetail;
|
||||
import cn.daxpay.single.service.core.payment.adjust.dto.AllocResultItem;
|
||||
import cn.daxpay.single.service.core.payment.sync.result.AllocRemoteSyncResult;
|
||||
import cn.daxpay.single.core.util.PayUtil;
|
||||
import cn.hutool.core.date.LocalDateTimeUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import com.alipay.api.AlipayClient;
|
||||
@@ -26,11 +26,12 @@ import lombok.SneakyThrows;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
@@ -112,7 +113,7 @@ public class AliPayAllocService {
|
||||
* 分账状态同步
|
||||
*/
|
||||
@SneakyThrows
|
||||
public AllocRemoteSyncResult sync(AllocOrder allocOrder, AliPayConfig config){
|
||||
public AllocRemoteSyncResult sync(AllocOrder allocOrder, List<AllocOrderDetail> allocOrderDetails, AliPayConfig config){
|
||||
AlipayClient alipayClient = aliPayConfigService.getAlipayClient(config);
|
||||
AlipayTradeOrderSettleQueryModel model = new AlipayTradeOrderSettleQueryModel();
|
||||
model.setTradeNo(allocOrder.getOutOrderNo());
|
||||
@@ -122,32 +123,25 @@ public class AliPayAllocService {
|
||||
AlipayTradeOrderSettleQueryResponse response = alipayClient.execute(request);
|
||||
// 验证
|
||||
this.verifyErrorMsg(response);
|
||||
// 接收到的结果
|
||||
Map<String, AllocOrderDetail> detailMap = allocOrderDetails.stream()
|
||||
.collect(Collectors.toMap(AllocOrderDetail::getReceiverAccount, Function.identity(), CollectorsFunction::retainLatest));
|
||||
List<RoyaltyDetail> royaltyDetailList = response.getRoyaltyDetailList();
|
||||
// 转换成通用的明细详情
|
||||
List<AllocResultItem> resultItems = royaltyDetailList.stream()
|
||||
.map(receiver -> {
|
||||
// 金额
|
||||
int amount = PayUtil.convertCentAmount(new BigDecimal(receiver.getAmount()));
|
||||
AllocResultItem detail = new AllocResultItem()
|
||||
.setResult(this.getDetailResultEnum(receiver.getState()).getCode())
|
||||
.setAccount(receiver.getTransIn())
|
||||
.setAmount(amount)
|
||||
.setErrorCode(receiver.getErrorCode())
|
||||
.setErrorMsg(receiver.getErrorDesc());
|
||||
// 如果是完成, 更新时间
|
||||
if (AllocDetailResultEnum.SUCCESS.getCode()
|
||||
.equals(detail.getResult())) {
|
||||
LocalDateTime finishTime = LocalDateTimeUtil.of(receiver.getExecuteDt());
|
||||
detail.setFinishTime(finishTime)
|
||||
.setErrorMsg(null)
|
||||
.setErrorCode(null);
|
||||
}
|
||||
return detail;
|
||||
})
|
||||
.collect(Collectors.toList());
|
||||
|
||||
return new AllocRemoteSyncResult().setSyncInfo(JSONUtil.toJsonStr(response)).setResultItems(resultItems);
|
||||
for (RoyaltyDetail receiver : royaltyDetailList) {
|
||||
AllocOrderDetail detail = detailMap.get(receiver.getTransIn());
|
||||
if (Objects.nonNull(detail)) {
|
||||
detail.setResult(this.getDetailResultEnum(receiver.getState()).getCode());
|
||||
detail.setErrorCode(receiver.getErrorCode());
|
||||
detail.setErrorMsg(receiver.getErrorDesc());
|
||||
// 如果是完成, 更新时间
|
||||
if (AllocDetailResultEnum.SUCCESS.getCode().equals(detail.getResult())){
|
||||
LocalDateTime finishTime = LocalDateTimeUtil.of(receiver.getExecuteDt());
|
||||
detail.setFinishTime(finishTime)
|
||||
.setErrorMsg(null)
|
||||
.setErrorCode(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
return new AllocRemoteSyncResult().setSyncInfo(JSONUtil.toJsonStr(response));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -1,6 +1,6 @@
|
||||
package cn.daxpay.single.service.core.channel.wechat.service;
|
||||
|
||||
import cn.bootx.platform.common.core.util.LocalDateTimeUtil;
|
||||
import cn.bootx.platform.common.core.function.CollectorsFunction;
|
||||
import cn.bootx.platform.common.mybatisplus.base.MpIdEntity;
|
||||
import cn.daxpay.single.core.code.AllocDetailResultEnum;
|
||||
import cn.daxpay.single.core.code.AllocReceiverTypeEnum;
|
||||
@@ -9,11 +9,11 @@ import cn.daxpay.single.service.code.WeChatPayCode;
|
||||
import cn.daxpay.single.service.core.channel.wechat.entity.WeChatPayConfig;
|
||||
import cn.daxpay.single.service.core.order.allocation.entity.AllocOrder;
|
||||
import cn.daxpay.single.service.core.order.allocation.entity.AllocOrderDetail;
|
||||
import cn.daxpay.single.service.core.payment.adjust.dto.AllocResultItem;
|
||||
import cn.daxpay.single.service.core.payment.sync.result.AllocRemoteSyncResult;
|
||||
import cn.daxpay.single.service.dto.channel.wechat.WeChatPayAllocReceiver;
|
||||
import cn.hutool.core.codec.Base64;
|
||||
import cn.hutool.core.date.DatePattern;
|
||||
import cn.hutool.core.date.LocalDateTimeUtil;
|
||||
import cn.hutool.core.lang.TypeReference;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
@@ -34,6 +34,7 @@ import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
@@ -111,7 +112,7 @@ public class WeChatPayAllocService {
|
||||
/**
|
||||
* 同步分账状态
|
||||
*/
|
||||
public AllocRemoteSyncResult sync(AllocOrder allocOrder, WeChatPayConfig config){
|
||||
public AllocRemoteSyncResult sync(AllocOrder allocOrder, List<AllocOrderDetail> allocOrderDetails, WeChatPayConfig config){
|
||||
// 不要传输AppId参数, 否则会失败
|
||||
Map<String, String> params = ProfitSharingModel.builder()
|
||||
.mch_id(config.getWxMchId())
|
||||
@@ -124,26 +125,23 @@ public class WeChatPayAllocService {
|
||||
Map<String, String> result = WxPayKit.xmlToMap(xmlResult);
|
||||
this.verifyErrorMsg(result);
|
||||
String json = result.get(WeChatPayCode.ALLOC_RECEIVERS);
|
||||
// 接收到的分账内容
|
||||
List<WeChatPayAllocReceiver> receivers = JSONUtil.toBean(json, new TypeReference<List<WeChatPayAllocReceiver>>() {}, false);
|
||||
|
||||
// 转换成通用的明细详情
|
||||
List<AllocResultItem> resultItems = receivers.stream()
|
||||
.map(receiver -> {
|
||||
AllocResultItem detail = new AllocResultItem()
|
||||
.setResult(this.getDetailResultEnum(receiver.getResult()).getCode())
|
||||
.setAccount(receiver.getAccount())
|
||||
.setErrorMsg(receiver.getFailReason());
|
||||
// 如果是完成, 更新时间
|
||||
if (AllocDetailResultEnum.SUCCESS.getCode().equals(detail.getResult())){
|
||||
LocalDateTime finishTime = LocalDateTimeUtil.parse(receiver.getFinishTime(), DatePattern.PURE_DATETIME_PATTERN);
|
||||
detail.setFinishTime(finishTime);
|
||||
}
|
||||
return detail;
|
||||
})
|
||||
.collect(Collectors.toList());
|
||||
|
||||
return new AllocRemoteSyncResult().setSyncInfo(json).setResultItems(resultItems);
|
||||
Map<String, AllocOrderDetail> detailMap = allocOrderDetails.stream()
|
||||
.collect(Collectors.toMap(AllocOrderDetail::getReceiverAccount, Function.identity(), CollectorsFunction::retainLatest));
|
||||
// 根据明细更新订单明细内容
|
||||
for (WeChatPayAllocReceiver receiver : receivers) {
|
||||
AllocOrderDetail detail = detailMap.get(receiver.getAccount());
|
||||
if (Objects.nonNull(detail)){
|
||||
detail.setResult(this.getDetailResultEnum(receiver.getResult()).getCode());
|
||||
detail.setErrorMsg(receiver.getFailReason());
|
||||
// 如果是完成, 更新时间
|
||||
if (AllocDetailResultEnum.SUCCESS.getCode().equals(detail.getResult())){
|
||||
LocalDateTime finishTime = LocalDateTimeUtil.parse(receiver.getFinishTime(), DatePattern.PURE_DATETIME_PATTERN);
|
||||
detail.setFinishTime(finishTime);
|
||||
}
|
||||
}
|
||||
}
|
||||
return new AllocRemoteSyncResult().setSyncInfo(JSONUtil.toJsonStr(receivers));
|
||||
}
|
||||
|
||||
|
||||
|
@@ -4,8 +4,8 @@ import cn.bootx.platform.common.core.rest.param.PageParam;
|
||||
import cn.bootx.platform.common.mybatisplus.impl.BaseManager;
|
||||
import cn.bootx.platform.common.mybatisplus.util.MpUtil;
|
||||
import cn.bootx.platform.common.query.generator.QueryGenerator;
|
||||
import cn.daxpay.single.core.code.PayStatusEnum;
|
||||
import cn.daxpay.single.service.core.order.refund.entity.RefundOrder;
|
||||
import cn.daxpay.single.core.code.TransferStatusEnum;
|
||||
import cn.daxpay.single.core.result.order.TransferOrderResult;
|
||||
import cn.daxpay.single.service.core.order.transfer.entity.TransferOrder;
|
||||
import cn.daxpay.single.service.param.order.TransferOrderQuery;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
@@ -55,7 +55,7 @@ public class TransferOrderManager extends BaseManager<TransferOrderMapper, Trans
|
||||
*/
|
||||
public Integer getTalAmount(TransferOrderQuery query){
|
||||
QueryWrapper<TransferOrderQuery> generator = QueryGenerator.generator(query);
|
||||
generator.eq(MpUtil.getColumnName(RefundOrder::getStatus), PayStatusEnum.SUCCESS.getCode());
|
||||
generator.eq(MpUtil.getColumnName(TransferOrderResult::getStatus), TransferStatusEnum.SUCCESS.getCode());
|
||||
return baseMapper.getTalAmount(generator);
|
||||
}
|
||||
}
|
||||
|
@@ -1,35 +0,0 @@
|
||||
package cn.daxpay.single.service.core.payment.adjust.dto;
|
||||
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* 分账结果明细
|
||||
* @author xxm
|
||||
* @since 2024/7/16
|
||||
*/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class AllocResultItem {
|
||||
|
||||
/** 账号 */
|
||||
private String account;
|
||||
|
||||
/** 金额 */
|
||||
private Integer amount;
|
||||
|
||||
/** 状态 */
|
||||
private String result;
|
||||
|
||||
/** 完成时间 */
|
||||
private LocalDateTime finishTime;
|
||||
|
||||
/** 错误码 */
|
||||
private String errorCode;
|
||||
|
||||
/** 错误信息 */
|
||||
private String errorMsg;
|
||||
|
||||
}
|
@@ -1,36 +0,0 @@
|
||||
package cn.daxpay.single.service.core.payment.adjust.param;
|
||||
|
||||
import cn.daxpay.single.service.code.TradeAdjustSourceEnum;
|
||||
import cn.daxpay.single.service.core.order.allocation.entity.AllocOrder;
|
||||
import cn.daxpay.single.service.core.order.allocation.entity.AllocOrderDetail;
|
||||
import cn.daxpay.single.service.core.payment.adjust.dto.AllocResultItem;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 分账调整参数
|
||||
* @author xxm
|
||||
* @since 2024/7/16
|
||||
*/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
@Schema(title = "分账调整参数")
|
||||
public class AllocAdjustParam {
|
||||
|
||||
|
||||
/** 触发来源 */
|
||||
@Schema(description = "触发来源")
|
||||
private TradeAdjustSourceEnum source;
|
||||
|
||||
/** 分账订单 */
|
||||
private AllocOrder order;
|
||||
|
||||
/** 分账明细订单 */
|
||||
private List<AllocOrderDetail> details;
|
||||
|
||||
/** 分账结果明细列表 */
|
||||
private List<AllocResultItem> resultItems;
|
||||
}
|
@@ -1,35 +0,0 @@
|
||||
package cn.daxpay.single.service.core.payment.adjust.param;
|
||||
|
||||
import cn.daxpay.single.service.code.PayAdjustWayEnum;
|
||||
import cn.daxpay.single.service.code.TradeAdjustSourceEnum;
|
||||
import cn.daxpay.single.service.core.order.pay.entity.PayOrder;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* 支付订单调整参数
|
||||
* @author xxm
|
||||
* @since 2023/12/27
|
||||
*/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class PayAdjustParam {
|
||||
|
||||
@Schema(description = "支付订单")
|
||||
private PayOrder order;
|
||||
|
||||
@Schema(description = "通道交易号")
|
||||
private String outTradeNo;
|
||||
|
||||
@Schema(description = "完成时间")
|
||||
private LocalDateTime finishTime;
|
||||
|
||||
@Schema(description = "触发来源")
|
||||
private TradeAdjustSourceEnum source;
|
||||
|
||||
@Schema(description = "调整方式")
|
||||
private PayAdjustWayEnum adjustWay;
|
||||
}
|
@@ -1,35 +0,0 @@
|
||||
package cn.daxpay.single.service.core.payment.adjust.param;
|
||||
|
||||
import cn.daxpay.single.service.code.RefundAdjustWayEnum;
|
||||
import cn.daxpay.single.service.code.TradeAdjustSourceEnum;
|
||||
import cn.daxpay.single.service.core.order.refund.entity.RefundOrder;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
/**
|
||||
* 退款订单调整参数
|
||||
* @author xxm
|
||||
* @since 2023/12/27
|
||||
*/
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
public class RefundAdjustParam {
|
||||
|
||||
@Schema(description = "退款订单")
|
||||
private RefundOrder order;
|
||||
|
||||
@Schema(description = "通道交易号")
|
||||
private String outTradeNo;
|
||||
|
||||
@Schema(description = "完成时间")
|
||||
private LocalDateTime finishTime;
|
||||
|
||||
@Schema(description = "触发来源")
|
||||
private TradeAdjustSourceEnum source;
|
||||
|
||||
@Schema(description = "调整方式")
|
||||
private RefundAdjustWayEnum adjustWay;
|
||||
}
|
@@ -1,132 +0,0 @@
|
||||
package cn.daxpay.single.service.core.payment.adjust.service;
|
||||
|
||||
import cn.bootx.platform.common.core.exception.RepetitiveOperationException;
|
||||
import cn.daxpay.single.core.code.AllocDetailResultEnum;
|
||||
import cn.daxpay.single.core.code.AllocOrderResultEnum;
|
||||
import cn.daxpay.single.core.code.AllocOrderStatusEnum;
|
||||
import cn.daxpay.single.core.util.TradeNoGenerateUtil;
|
||||
import cn.daxpay.single.service.code.TradeTypeEnum;
|
||||
import cn.daxpay.single.service.core.order.allocation.dao.AllocOrderDetailManager;
|
||||
import cn.daxpay.single.service.core.order.allocation.dao.AllocOrderManager;
|
||||
import cn.daxpay.single.service.core.order.allocation.entity.AllocOrder;
|
||||
import cn.daxpay.single.service.core.order.allocation.entity.AllocOrderDetail;
|
||||
import cn.daxpay.single.service.core.payment.adjust.dto.AllocResultItem;
|
||||
import cn.daxpay.single.service.core.payment.adjust.param.AllocAdjustParam;
|
||||
import cn.daxpay.single.service.core.payment.notice.service.ClientNoticeService;
|
||||
import cn.daxpay.single.service.core.record.adjust.entity.TradeAdjustRecord;
|
||||
import cn.daxpay.single.service.core.record.adjust.service.TradeAdjustRecordService;
|
||||
import com.baomidou.lock.LockInfo;
|
||||
import com.baomidou.lock.LockTemplate;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 分账调整
|
||||
* @author xxm
|
||||
* @since 2024/7/16
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class AllocAdjustService {
|
||||
|
||||
private final LockTemplate lockTemplate;
|
||||
private final AllocOrderDetailManager allocOrderDetailManager;
|
||||
private final AllocOrderManager allocOrderManager;
|
||||
private final ClientNoticeService clientNoticeService;
|
||||
private final TradeAdjustRecordService tradeAdjustRecordService;
|
||||
|
||||
/**
|
||||
* 分账订单处理
|
||||
*/
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public String adjust(AllocAdjustParam allocAdjustParam){
|
||||
AllocOrder allocOrder = allocAdjustParam.getOrder();
|
||||
List<AllocResultItem> resultItems = allocAdjustParam.getResultItems();
|
||||
List<AllocOrderDetail> details = allocAdjustParam.getDetails();
|
||||
LockInfo lock = lockTemplate.lock("adjust:alloc:" + allocOrder.getOrderId(),10000,200);
|
||||
if (Objects.isNull(lock)){
|
||||
throw new RepetitiveOperationException("分账调整中,请勿重复操作");
|
||||
}
|
||||
// 如果是分账结束或失败, 不更新状态
|
||||
String status = allocOrder.getStatus();
|
||||
// 如果是分账结束或失败, 不进行对订单进行处理
|
||||
List<String> list = Arrays.asList(AllocOrderStatusEnum.FINISH.getCode(), AllocOrderStatusEnum.FINISH_FAILED.getCode());
|
||||
if (!list.contains(status)){
|
||||
Map<Long, AllocOrderDetail> detailMap = allocAdjustParam.getDetails()
|
||||
.stream()
|
||||
.collect(Collectors.toMap(AllocOrderDetail::getId, Function.identity()));
|
||||
// 更新状态
|
||||
for (AllocResultItem resultItem : resultItems) {
|
||||
|
||||
}
|
||||
|
||||
// 判断明细状态. 获取成功和失败的
|
||||
long successCount = details.stream()
|
||||
.map(AllocOrderDetail::getResult)
|
||||
.filter(AllocDetailResultEnum.SUCCESS.getCode()::equals)
|
||||
.count();
|
||||
long failCount = details.stream()
|
||||
.map(AllocOrderDetail::getResult)
|
||||
.filter(AllocDetailResultEnum.FAIL.getCode()::equals)
|
||||
.count();
|
||||
|
||||
// 成功和失败都为0 表示进行中
|
||||
if (successCount == 0 && failCount == 0){
|
||||
allocOrder.setStatus(AllocOrderStatusEnum.ALLOCATION_PROCESSING.getCode())
|
||||
.setResult(AllocOrderResultEnum.ALL_PENDING.getCode());
|
||||
} else {
|
||||
if (failCount == details.size()){
|
||||
// 全部失败
|
||||
allocOrder.setStatus(AllocOrderStatusEnum.ALLOCATION_END.getCode())
|
||||
.setResult(AllocOrderResultEnum.ALL_FAILED.getCode());
|
||||
} else if (successCount == details.size()){
|
||||
// 全部成功
|
||||
allocOrder.setStatus(AllocOrderStatusEnum.ALLOCATION_END.getCode())
|
||||
.setResult(AllocOrderResultEnum.ALL_SUCCESS.getCode());
|
||||
} else {
|
||||
// 部分成功
|
||||
allocOrder.setStatus(AllocOrderStatusEnum.ALLOCATION_END.getCode())
|
||||
.setResult(AllocOrderResultEnum.PART_SUCCESS.getCode());
|
||||
}
|
||||
}
|
||||
// 更新
|
||||
allocOrderDetailManager.updateAllById(details);
|
||||
allocOrderManager.updateById(allocOrder);
|
||||
|
||||
// 如果状态为完成, 发送通知
|
||||
if (Objects.equals(AllocOrderStatusEnum.ALLOCATION_END.getCode(), allocOrder.getStatus())){
|
||||
// 发送通知
|
||||
clientNoticeService.registerAllocNotice(allocOrder, details);
|
||||
}
|
||||
return this.saveRecord(allocAdjustParam).getAdjustNo();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存记录
|
||||
*/
|
||||
private TradeAdjustRecord saveRecord(AllocAdjustParam param){
|
||||
AllocOrder order = param.getOrder();
|
||||
TradeAdjustRecord record = new TradeAdjustRecord()
|
||||
.setAdjustNo(TradeNoGenerateUtil.adjust())
|
||||
.setTradeId(order.getId())
|
||||
.setChannel(order.getChannel())
|
||||
.setSource(param.getSource().getCode())
|
||||
.setTradeNo(order.getOrderNo())
|
||||
.setType(TradeTypeEnum.ALLOCATION.getCode());
|
||||
tradeAdjustRecordService.saveRecord(record);
|
||||
return record;
|
||||
}
|
||||
}
|
@@ -1,146 +0,0 @@
|
||||
package cn.daxpay.single.service.core.payment.adjust.service;
|
||||
|
||||
import cn.daxpay.single.core.code.PayStatusEnum;
|
||||
import cn.daxpay.single.core.exception.OperationProcessingException;
|
||||
import cn.daxpay.single.core.exception.SystemUnknownErrorException;
|
||||
import cn.daxpay.single.core.exception.TradeStatusErrorException;
|
||||
import cn.daxpay.single.core.util.TradeNoGenerateUtil;
|
||||
import cn.daxpay.single.service.code.TradeTypeEnum;
|
||||
import cn.daxpay.single.service.core.order.pay.entity.PayOrder;
|
||||
import cn.daxpay.single.service.core.order.pay.service.PayOrderService;
|
||||
import cn.daxpay.single.service.core.payment.notice.service.ClientNoticeService;
|
||||
import cn.daxpay.single.service.core.payment.adjust.param.PayAdjustParam;
|
||||
import cn.daxpay.single.service.core.record.flow.service.TradeFlowRecordService;
|
||||
import cn.daxpay.single.service.core.record.adjust.entity.TradeAdjustRecord;
|
||||
import cn.daxpay.single.service.core.record.adjust.service.TradeAdjustRecordService;
|
||||
import cn.daxpay.single.service.func.AbsPayAdjustStrategy;
|
||||
import cn.daxpay.single.service.util.PayStrategyFactory;
|
||||
import com.baomidou.lock.LockInfo;
|
||||
import com.baomidou.lock.LockTemplate;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* 支付订单调整服务
|
||||
* @author xxm
|
||||
* @since 2024/7/15
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class PayAdjustService {
|
||||
|
||||
private final ClientNoticeService clientNoticeService;
|
||||
|
||||
private final LockTemplate lockTemplate;
|
||||
private final TradeAdjustRecordService tradeAdjustRecordService;
|
||||
private final PayOrderService payOrderService;
|
||||
private final TradeFlowRecordService tradeFlowRecordService;
|
||||
|
||||
/**
|
||||
* 调整服务
|
||||
*/
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public String adjust(PayAdjustParam param){
|
||||
PayOrder order = param.getOrder();
|
||||
// 添加分布式锁
|
||||
LockInfo lock = lockTemplate.lock("adjust:pay:" + order.getId(), 10000, 200);
|
||||
if (Objects.isNull(lock)){
|
||||
log.warn("当前支付订单正在调整中: {}", order.getId());
|
||||
throw new OperationProcessingException("当前支付订单正在调整中");
|
||||
}
|
||||
// 如果到达终态不能向前回滚
|
||||
if (Objects.equals(order.getStatus(), PayStatusEnum.SUCCESS.getCode())){
|
||||
throw new TradeStatusErrorException("当前支付订单已支付成功");
|
||||
}
|
||||
|
||||
// 初始化调整参数
|
||||
AbsPayAdjustStrategy adjustStrategy = PayStrategyFactory.create(order.getChannel(), AbsPayAdjustStrategy.class);
|
||||
adjustStrategy.setOrder(order);
|
||||
|
||||
// 执行前置处理
|
||||
adjustStrategy.doBeforeHandler();
|
||||
String beforeStatus = order.getStatus();
|
||||
// 根据不同的调整方式执行对应的调整逻辑
|
||||
switch (param.getAdjustWay()) {
|
||||
case SUCCESS:
|
||||
this.success(order, param);
|
||||
break;
|
||||
case CLOSE_LOCAL:
|
||||
this.closeLocal(order);
|
||||
break;
|
||||
case CLOSE_GATEWAY:
|
||||
this.closeRemote(order, adjustStrategy);
|
||||
break;
|
||||
default:
|
||||
log.error("走到了理论上讲不会走到的分支");
|
||||
throw new SystemUnknownErrorException("走到了理论上讲不会走到的分支");
|
||||
}
|
||||
|
||||
// 发送通知
|
||||
clientNoticeService.registerPayNotice(order);
|
||||
TradeAdjustRecord record = this.saveRecord(order, param, beforeStatus);
|
||||
return record.getAdjustNo();
|
||||
}
|
||||
|
||||
/**
|
||||
* 变更为已支付
|
||||
* 同步: 将异步支付状态修改为成功
|
||||
* 回调: 将异步支付状态修改为成功
|
||||
*/
|
||||
private void success(PayOrder order, PayAdjustParam param) {
|
||||
// 修改订单支付状态为成功
|
||||
order.setStatus(PayStatusEnum.SUCCESS.getCode())
|
||||
.setPayTime(param.getFinishTime())
|
||||
.setOutOrderNo(param.getOutTradeNo())
|
||||
.setCloseTime(null);
|
||||
tradeFlowRecordService.savePay(order);
|
||||
payOrderService.updateById(order);
|
||||
}
|
||||
|
||||
/**
|
||||
* 关闭支付
|
||||
* 同步/对账: 执行支付单所有的支付通道关闭支付逻辑, 不需要调用网关关闭,
|
||||
*/
|
||||
private void closeLocal(PayOrder order) {
|
||||
// 执行策略的关闭方法
|
||||
order.setStatus(PayStatusEnum.CLOSE.getCode())
|
||||
.setCloseTime(LocalDateTime.now());
|
||||
payOrderService.updateById(order);
|
||||
}
|
||||
/**
|
||||
* 关闭网关交易, 同时也会关闭本地支付
|
||||
* 回调: 执行所有的支付通道关闭支付逻辑
|
||||
*/
|
||||
private void closeRemote(PayOrder payOrder, AbsPayAdjustStrategy strategy) {
|
||||
// 执行策略的关闭方法
|
||||
strategy.doCloseRemoteHandler();
|
||||
payOrder.setStatus(PayStatusEnum.CLOSE.getCode())
|
||||
.setCloseTime(LocalDateTime.now());
|
||||
payOrderService.updateById(payOrder);
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存记录
|
||||
*/
|
||||
private TradeAdjustRecord saveRecord(PayOrder order, PayAdjustParam param, String beforeStatus){
|
||||
TradeAdjustRecord record = new TradeAdjustRecord()
|
||||
.setAdjustNo(TradeNoGenerateUtil.adjust())
|
||||
.setTradeId(order.getId())
|
||||
.setChannel(order.getChannel())
|
||||
.setSource(param.getSource().getCode())
|
||||
.setTradeNo(order.getOrderNo())
|
||||
.setBeforeStatus(beforeStatus)
|
||||
.setAfterStatus(order.getStatus())
|
||||
.setType(TradeTypeEnum.PAY.getCode())
|
||||
.setWay(param.getAdjustWay().getCode());
|
||||
tradeAdjustRecordService.saveRecord(record);
|
||||
return record;
|
||||
}
|
||||
|
||||
}
|
@@ -1,179 +0,0 @@
|
||||
package cn.daxpay.single.service.core.payment.adjust.service;
|
||||
|
||||
import cn.daxpay.single.core.code.PayOrderRefundStatusEnum;
|
||||
import cn.daxpay.single.core.code.PayStatusEnum;
|
||||
import cn.daxpay.single.core.code.RefundStatusEnum;
|
||||
import cn.daxpay.single.core.exception.OperationProcessingException;
|
||||
import cn.daxpay.single.core.exception.TradeStatusErrorException;
|
||||
import cn.daxpay.single.core.util.TradeNoGenerateUtil;
|
||||
import cn.daxpay.single.service.code.RefundAdjustWayEnum;
|
||||
import cn.daxpay.single.service.code.TradeTypeEnum;
|
||||
import cn.daxpay.single.service.core.order.pay.entity.PayOrder;
|
||||
import cn.daxpay.single.service.core.order.pay.service.PayOrderQueryService;
|
||||
import cn.daxpay.single.service.core.order.pay.service.PayOrderService;
|
||||
import cn.daxpay.single.service.core.order.refund.dao.RefundOrderManager;
|
||||
import cn.daxpay.single.service.core.order.refund.entity.RefundOrder;
|
||||
import cn.daxpay.single.service.core.payment.adjust.param.RefundAdjustParam;
|
||||
import cn.daxpay.single.service.core.payment.notice.service.ClientNoticeService;
|
||||
import cn.daxpay.single.service.core.record.flow.service.TradeFlowRecordService;
|
||||
import cn.daxpay.single.service.core.record.adjust.entity.TradeAdjustRecord;
|
||||
import cn.daxpay.single.service.core.record.adjust.service.TradeAdjustRecordService;
|
||||
import com.baomidou.lock.LockInfo;
|
||||
import com.baomidou.lock.LockTemplate;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* 退款订单调整
|
||||
* @author xxm
|
||||
* @since 2024/1/26
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class RefundAdjustService {
|
||||
|
||||
private final PayOrderService payOrderService;
|
||||
|
||||
private final PayOrderQueryService payOrderQueryService;
|
||||
|
||||
private final ClientNoticeService clientNoticeService;
|
||||
|
||||
private final RefundOrderManager refundOrderManager;
|
||||
|
||||
private final TradeFlowRecordService tradeFlowRecordService;
|
||||
|
||||
private final TradeAdjustRecordService tradeAdjustRecordService;
|
||||
|
||||
private final LockTemplate lockTemplate;
|
||||
|
||||
/**
|
||||
* 退款订单调整
|
||||
*/
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public String adjust(RefundAdjustParam param){
|
||||
RefundOrder refundOrder = param.getOrder();
|
||||
RefundAdjustWayEnum adjustType = param.getAdjustWay();
|
||||
// 添加分布式锁
|
||||
LockInfo lock = lockTemplate.lock("adjust:refund:" + refundOrder.getId(), 10000, 200);
|
||||
if (Objects.isNull(lock)){
|
||||
log.warn("当前退款订单正在调整中: {}", refundOrder.getId());
|
||||
throw new OperationProcessingException("当前退款订单正在调整中");
|
||||
}
|
||||
// 如果到达终态不能向前回滚
|
||||
if (Arrays.asList(RefundStatusEnum.SUCCESS.getCode(), RefundStatusEnum.CLOSE.getCode()).contains(refundOrder.getStatus())){
|
||||
throw new TradeStatusErrorException("当前退款订单已处理完成");
|
||||
}
|
||||
try {
|
||||
// 获取关联支付单
|
||||
PayOrder payOrder = payOrderQueryService.findById(refundOrder.getOrderId()).orElseThrow(() -> new RuntimeException("支付单不存在"));
|
||||
String adjustNo = null;
|
||||
// 根据不同的类型执行对应的调整逻辑
|
||||
if (adjustType == RefundAdjustWayEnum.SUCCESS) {
|
||||
adjustNo = this.success(param, payOrder);
|
||||
} else if (adjustType == RefundAdjustWayEnum.FAIL) {
|
||||
adjustNo = this.close(param, payOrder);
|
||||
} else {
|
||||
log.error("走到了理论上讲不会走到的分支");
|
||||
}
|
||||
|
||||
// 发送通知
|
||||
clientNoticeService.registerRefundNotice(refundOrder);
|
||||
return adjustNo;
|
||||
} finally {
|
||||
lockTemplate.releaseLock(lock);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 退款成功, 更新退款单和支付单
|
||||
*/
|
||||
private String success(RefundAdjustParam param, PayOrder payOrder) {
|
||||
RefundOrder refundOrder = param.getOrder();
|
||||
String beforeRefundStatus = refundOrder.getStatus();
|
||||
|
||||
// 订单相关状态
|
||||
PayOrderRefundStatusEnum afterPayRefundStatus;
|
||||
|
||||
// 判断订单全部退款还是部分退款
|
||||
if (Objects.equals(payOrder.getRefundableBalance(),0)){
|
||||
afterPayRefundStatus = PayOrderRefundStatusEnum.REFUNDED;
|
||||
} else {
|
||||
afterPayRefundStatus = PayOrderRefundStatusEnum.PARTIAL_REFUND;
|
||||
}
|
||||
// 设置退款为完成状态和完成时间
|
||||
refundOrder.setStatus(RefundStatusEnum.SUCCESS.getCode())
|
||||
.setFinishTime(param.getFinishTime());
|
||||
payOrder.setRefundStatus(afterPayRefundStatus.getCode());
|
||||
|
||||
// 更新订单和退款相关订单
|
||||
payOrderService.updateById(payOrder);
|
||||
refundOrderManager.updateById(refundOrder);
|
||||
|
||||
// 记录流水
|
||||
tradeFlowRecordService.saveRefund(refundOrder);
|
||||
|
||||
// 发送通知
|
||||
List<String> list = Arrays.asList(RefundStatusEnum.SUCCESS.getCode(), RefundStatusEnum.CLOSE.getCode(), RefundStatusEnum.FAIL.getCode());
|
||||
if (list.contains(refundOrder.getStatus())){
|
||||
clientNoticeService.registerRefundNotice(refundOrder);
|
||||
}
|
||||
// 保存调整记录
|
||||
TradeAdjustRecord adjustRecord = this.saveRecord(param, beforeRefundStatus);
|
||||
return adjustRecord.getAdjustNo();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 退款失败, 关闭退款单并将失败的退款金额归还回订单
|
||||
*/
|
||||
private String close(RefundAdjustParam param, PayOrder payOrder) {
|
||||
RefundOrder refundOrder = param.getOrder();
|
||||
String beforeRefundStatus = refundOrder.getStatus();
|
||||
|
||||
// 退款失败返还后的余额
|
||||
int payOrderAmount = refundOrder.getAmount() + payOrder.getRefundableBalance();
|
||||
// 退款失败返还后的余额+可退余额 == 订单金额 支付订单回退为为支付成功状态
|
||||
if (payOrderAmount == payOrder.getAmount()){
|
||||
payOrder.setStatus(PayStatusEnum.SUCCESS.getCode());
|
||||
} else {
|
||||
// 回归部分退款状态
|
||||
payOrder.setRefundStatus(PayOrderRefundStatusEnum.PARTIAL_REFUND.getCode());
|
||||
}
|
||||
|
||||
// 更新支付订单相关的可退款金额
|
||||
payOrder.setRefundableBalance(payOrderAmount);
|
||||
refundOrder.setStatus(RefundStatusEnum.CLOSE.getCode());
|
||||
|
||||
// 更新订单和退款相关订单
|
||||
payOrderService.updateById(payOrder);
|
||||
refundOrderManager.updateById(refundOrder);
|
||||
TradeAdjustRecord adjustRecord = this.saveRecord(param, beforeRefundStatus);
|
||||
return adjustRecord.getAdjustNo();
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存退款订单的调整记录
|
||||
*/
|
||||
private TradeAdjustRecord saveRecord(RefundAdjustParam param, String beforeRefundStatus){
|
||||
RefundOrder refundOrder = param.getOrder();
|
||||
TradeAdjustRecord record = new TradeAdjustRecord()
|
||||
.setTradeId(refundOrder.getId())
|
||||
.setAdjustNo(TradeNoGenerateUtil.adjust())
|
||||
.setTradeNo(refundOrder.getRefundNo())
|
||||
.setChannel(refundOrder.getChannel())
|
||||
.setType(TradeTypeEnum.REFUND.getCode())
|
||||
.setBeforeStatus(beforeRefundStatus)
|
||||
.setAfterStatus(refundOrder.getStatus())
|
||||
.setSource(param.getSource().getCode())
|
||||
.setWay(param.getAdjustWay().getCode());
|
||||
tradeAdjustRecordService.saveRecord(record);
|
||||
return record;
|
||||
}
|
||||
}
|
@@ -1,16 +0,0 @@
|
||||
package cn.daxpay.single.service.core.payment.adjust.service;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* 转账订单调整服务
|
||||
* @author xxm
|
||||
* @since 2024/7/16
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class TransferAdjustService {
|
||||
}
|
@@ -1,55 +0,0 @@
|
||||
package cn.daxpay.single.service.core.payment.adjust.strategy.pay;
|
||||
|
||||
import cn.daxpay.single.core.code.PayChannelEnum;
|
||||
import cn.daxpay.single.service.core.channel.alipay.entity.AliPayConfig;
|
||||
import cn.daxpay.single.service.core.channel.alipay.service.AliPayCloseService;
|
||||
import cn.daxpay.single.service.core.channel.alipay.service.AliPayConfigService;
|
||||
import cn.daxpay.single.service.func.AbsPayAdjustStrategy;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.context.annotation.Scope;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import static org.springframework.beans.factory.config.BeanDefinition.SCOPE_PROTOTYPE;
|
||||
|
||||
/**
|
||||
* 支付宝订单调整策略
|
||||
* @author xxm
|
||||
* @since 2023/12/27
|
||||
*/
|
||||
@Slf4j
|
||||
@Scope(SCOPE_PROTOTYPE)
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class AliPayAdjustStrategy extends AbsPayAdjustStrategy {
|
||||
private final AliPayCloseService closeService;
|
||||
|
||||
private final AliPayConfigService aliPayConfigService;
|
||||
|
||||
private AliPayConfig config;
|
||||
|
||||
/**
|
||||
* 策略标识
|
||||
*/
|
||||
@Override
|
||||
public String getChannel() {
|
||||
return PayChannelEnum.ALI.getCode();
|
||||
}
|
||||
|
||||
/**
|
||||
* 调整前处理
|
||||
*/
|
||||
@Override
|
||||
public void doBeforeHandler() {
|
||||
this.config = aliPayConfigService.getConfig();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 关闭本地支付和网关支付
|
||||
*/
|
||||
@Override
|
||||
public void doCloseRemoteHandler() {
|
||||
closeService.close(this.getOrder(), this.config);
|
||||
}
|
||||
}
|
@@ -1,38 +0,0 @@
|
||||
package cn.daxpay.single.service.core.payment.adjust.strategy.pay;
|
||||
|
||||
import cn.daxpay.single.core.code.PayChannelEnum;
|
||||
import cn.daxpay.single.service.func.AbsPayAdjustStrategy;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.context.annotation.Scope;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import static org.springframework.beans.factory.config.BeanDefinition.SCOPE_PROTOTYPE;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author xxm
|
||||
* @since 2023/12/29
|
||||
*/
|
||||
@Slf4j
|
||||
@Scope(SCOPE_PROTOTYPE)
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class UnionPayAdjustStrategy extends AbsPayAdjustStrategy {
|
||||
|
||||
/**
|
||||
* 策略标识
|
||||
*/
|
||||
@Override
|
||||
public String getChannel() {
|
||||
return PayChannelEnum.UNION_PAY.getCode();
|
||||
}
|
||||
|
||||
/**
|
||||
* 关闭三方系统的支付
|
||||
*/
|
||||
@Override
|
||||
public void doCloseRemoteHandler() {
|
||||
log.warn("云闪付未提供支付订单关闭接口");
|
||||
}
|
||||
}
|
@@ -1,56 +0,0 @@
|
||||
package cn.daxpay.single.service.core.payment.adjust.strategy.pay;
|
||||
|
||||
import cn.daxpay.single.core.code.PayChannelEnum;
|
||||
import cn.daxpay.single.service.core.channel.wechat.entity.WeChatPayConfig;
|
||||
import cn.daxpay.single.service.core.channel.wechat.service.WeChatPayCloseService;
|
||||
import cn.daxpay.single.service.core.channel.wechat.service.WeChatPayConfigService;
|
||||
import cn.daxpay.single.service.func.AbsPayAdjustStrategy;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.context.annotation.Scope;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import static org.springframework.beans.factory.config.BeanDefinition.SCOPE_PROTOTYPE;
|
||||
|
||||
/**
|
||||
* 微信支付订单调整策略类
|
||||
* @author xxm
|
||||
* @since 2023/12/29
|
||||
*/
|
||||
@Slf4j
|
||||
@Scope(SCOPE_PROTOTYPE)
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class WeChatPayAdjustStrategy extends AbsPayAdjustStrategy {
|
||||
private final WeChatPayCloseService closeService;
|
||||
|
||||
private final WeChatPayConfigService weChatPayConfigService;
|
||||
|
||||
private WeChatPayConfig weChatPayConfig;
|
||||
|
||||
/**
|
||||
* 策略标识
|
||||
*/
|
||||
@Override
|
||||
public String getChannel() {
|
||||
return PayChannelEnum.WECHAT.getCode();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 调整前处理
|
||||
*/
|
||||
@Override
|
||||
public void doBeforeHandler() {
|
||||
this.weChatPayConfig = weChatPayConfigService.getConfig();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 关闭本地支付和网关支付
|
||||
*/
|
||||
@Override
|
||||
public void doCloseRemoteHandler() {
|
||||
closeService.close(this.getOrder(),this.weChatPayConfig);
|
||||
}
|
||||
}
|
@@ -5,6 +5,7 @@ import cn.daxpay.single.core.exception.ConfigNotEnableException;
|
||||
import cn.daxpay.single.service.core.channel.alipay.entity.AliPayConfig;
|
||||
import cn.daxpay.single.service.core.channel.alipay.service.AliPayAllocService;
|
||||
import cn.daxpay.single.service.core.channel.alipay.service.AliPayConfigService;
|
||||
import cn.daxpay.single.service.core.payment.sync.result.AllocRemoteSyncResult;
|
||||
import cn.daxpay.single.service.func.AbsAllocStrategy;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
@@ -30,7 +31,7 @@ public class AliPayAllocStrategy extends AbsAllocStrategy {
|
||||
|
||||
private final AliPayConfigService aliPayConfigService;
|
||||
|
||||
private AliPayConfig aliPayConfig;
|
||||
private AliPayConfig aliPayConfig;;
|
||||
|
||||
|
||||
/**
|
||||
@@ -69,4 +70,12 @@ public class AliPayAllocStrategy extends AbsAllocStrategy {
|
||||
aliPayAllocService.finish(this.getAllocOrder(), this.getAllocOrderDetails(), this.aliPayConfig);
|
||||
}
|
||||
|
||||
/**
|
||||
* 同步状态
|
||||
*/
|
||||
@Override
|
||||
public AllocRemoteSyncResult doSync() {
|
||||
return aliPayAllocService.sync(this.getAllocOrder(), this.getAllocOrderDetails(), this.aliPayConfig);
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -6,6 +6,7 @@ import cn.daxpay.single.core.exception.OperationFailException;
|
||||
import cn.daxpay.single.service.core.channel.wechat.entity.WeChatPayConfig;
|
||||
import cn.daxpay.single.service.core.channel.wechat.service.WeChatPayAllocService;
|
||||
import cn.daxpay.single.service.core.channel.wechat.service.WeChatPayConfigService;
|
||||
import cn.daxpay.single.service.core.payment.sync.result.AllocRemoteSyncResult;
|
||||
import cn.daxpay.single.service.func.AbsAllocStrategy;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
@@ -73,5 +74,12 @@ public class WeChatPayAllocStrategy extends AbsAllocStrategy {
|
||||
weChatPayAllocService.finish(getAllocOrder(), weChatPayConfig);
|
||||
}
|
||||
|
||||
/**
|
||||
* 同步状态
|
||||
*/
|
||||
@Override
|
||||
public AllocRemoteSyncResult doSync() {
|
||||
return weChatPayAllocService.sync(this.getAllocOrder(),this.getAllocOrderDetails(),weChatPayConfig);
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -2,15 +2,14 @@ package cn.daxpay.single.service.core.payment.callback.service;
|
||||
|
||||
import cn.bootx.platform.common.core.util.LocalDateTimeUtil;
|
||||
import cn.daxpay.single.core.code.PayStatusEnum;
|
||||
import cn.daxpay.single.service.code.PayAdjustWayEnum;
|
||||
import cn.daxpay.single.service.code.PayCallbackStatusEnum;
|
||||
import cn.daxpay.single.service.code.TradeAdjustSourceEnum;
|
||||
import cn.daxpay.single.service.common.context.CallbackLocal;
|
||||
import cn.daxpay.single.service.common.local.PaymentContextLocal;
|
||||
import cn.daxpay.single.service.core.order.pay.entity.PayOrder;
|
||||
import cn.daxpay.single.service.core.order.pay.service.PayOrderQueryService;
|
||||
import cn.daxpay.single.service.core.payment.adjust.param.PayAdjustParam;
|
||||
import cn.daxpay.single.service.core.payment.adjust.service.PayAdjustService;
|
||||
import cn.daxpay.single.service.core.order.pay.service.PayOrderService;
|
||||
import cn.daxpay.single.service.core.payment.notice.service.ClientNoticeService;
|
||||
import cn.daxpay.single.service.core.record.flow.service.TradeFlowRecordService;
|
||||
import com.baomidou.lock.LockInfo;
|
||||
import com.baomidou.lock.LockTemplate;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
@@ -33,10 +32,12 @@ public class PayCallbackService {
|
||||
|
||||
private final PayOrderQueryService payOrderQueryService;
|
||||
|
||||
private final PayAdjustService payAdjustService;
|
||||
|
||||
private final LockTemplate lockTemplate;
|
||||
|
||||
private final PayOrderService payOrderService;
|
||||
private final TradeFlowRecordService tradeFlowRecordService;
|
||||
private final ClientNoticeService clientNoticeService;
|
||||
|
||||
/**
|
||||
* 支付统一回调处理
|
||||
*/
|
||||
@@ -74,7 +75,7 @@ public class PayCallbackService {
|
||||
}
|
||||
|
||||
/**
|
||||
* 成功处理 使用调整策略将支付订单调整为支付成功状态
|
||||
* 成功处理 将支付订单调整为支付成功状态
|
||||
*/
|
||||
private void success(PayOrder payOrder) {
|
||||
CallbackLocal callbackInfo = PaymentContextLocal.get().getCallbackInfo();
|
||||
@@ -94,15 +95,14 @@ public class PayCallbackService {
|
||||
callbackInfo.setCallbackStatus(PayCallbackStatusEnum.EXCEPTION).setErrorMsg("支付单不是待支付状态,记录回调记录");
|
||||
return;
|
||||
}
|
||||
// 执行支付成功的调整逻辑
|
||||
PayAdjustParam param = new PayAdjustParam()
|
||||
.setOrder(payOrder)
|
||||
.setOutTradeNo(callbackInfo.getOutTradeNo())
|
||||
.setAdjustWay(PayAdjustWayEnum.SUCCESS)
|
||||
.setSource(TradeAdjustSourceEnum.CALLBACK)
|
||||
.setFinishTime(callbackInfo.getFinishTime());
|
||||
String adjustNo = payAdjustService.adjust(param);
|
||||
callbackInfo.setAdjustNo(adjustNo);
|
||||
// 修改订单支付状态为成功
|
||||
payOrder.setStatus(PayStatusEnum.SUCCESS.getCode())
|
||||
.setPayTime(callbackInfo.getFinishTime())
|
||||
.setOutOrderNo(callbackInfo.getOutTradeNo())
|
||||
.setCloseTime(null);
|
||||
payOrderService.updateById(payOrder);
|
||||
tradeFlowRecordService.savePay(payOrder);
|
||||
clientNoticeService.registerPayNotice(payOrder);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -121,14 +121,11 @@ public class PayCallbackService {
|
||||
return;
|
||||
}
|
||||
// 执行支付关闭的调整逻辑
|
||||
PayAdjustParam param = new PayAdjustParam()
|
||||
.setOrder(payOrder)
|
||||
.setOutTradeNo(callbackInfo.getOutTradeNo())
|
||||
.setAdjustWay(PayAdjustWayEnum.CLOSE_LOCAL)
|
||||
.setSource(TradeAdjustSourceEnum.CALLBACK)
|
||||
.setFinishTime(callbackInfo.getFinishTime());
|
||||
String adjustNo = payAdjustService.adjust(param);
|
||||
callbackInfo.setAdjustNo(adjustNo);
|
||||
// 执行策略的关闭方法
|
||||
payOrder.setStatus(PayStatusEnum.CLOSE.getCode())
|
||||
.setCloseTime(LocalDateTime.now());
|
||||
payOrderService.updateById(payOrder);
|
||||
clientNoticeService.registerPayNotice(payOrder);
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -1,15 +1,18 @@
|
||||
package cn.daxpay.single.service.core.payment.callback.service;
|
||||
|
||||
import cn.bootx.platform.common.core.exception.DataNotExistException;
|
||||
import cn.daxpay.single.core.code.PayOrderRefundStatusEnum;
|
||||
import cn.daxpay.single.core.code.PayStatusEnum;
|
||||
import cn.daxpay.single.core.code.RefundStatusEnum;
|
||||
import cn.daxpay.single.service.code.PayCallbackStatusEnum;
|
||||
import cn.daxpay.single.service.code.RefundAdjustWayEnum;
|
||||
import cn.daxpay.single.service.code.TradeAdjustSourceEnum;
|
||||
import cn.daxpay.single.service.common.context.CallbackLocal;
|
||||
import cn.daxpay.single.service.common.local.PaymentContextLocal;
|
||||
import cn.daxpay.single.service.core.order.pay.entity.PayOrder;
|
||||
import cn.daxpay.single.service.core.order.pay.service.PayOrderService;
|
||||
import cn.daxpay.single.service.core.order.refund.dao.RefundOrderManager;
|
||||
import cn.daxpay.single.service.core.order.refund.entity.RefundOrder;
|
||||
import cn.daxpay.single.service.core.payment.adjust.param.RefundAdjustParam;
|
||||
import cn.daxpay.single.service.core.payment.adjust.service.RefundAdjustService;
|
||||
import cn.daxpay.single.service.core.payment.notice.service.ClientNoticeService;
|
||||
import cn.daxpay.single.service.core.record.flow.service.TradeFlowRecordService;
|
||||
import com.baomidou.lock.LockInfo;
|
||||
import com.baomidou.lock.LockTemplate;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
@@ -29,9 +32,10 @@ import java.util.Objects;
|
||||
public class RefundCallbackService {
|
||||
private final RefundOrderManager refundOrderManager;
|
||||
|
||||
private final RefundAdjustService reflectionService;
|
||||
|
||||
private final LockTemplate lockTemplate;
|
||||
private final TradeFlowRecordService tradeFlowRecordService;
|
||||
private final PayOrderService payOrderService;
|
||||
private final ClientNoticeService clientNoticeService;
|
||||
|
||||
/**
|
||||
* 退款回调统一处理
|
||||
@@ -61,23 +65,74 @@ public class RefundCallbackService {
|
||||
}
|
||||
|
||||
// 退款成功还是失败
|
||||
RefundAdjustParam param = new RefundAdjustParam()
|
||||
.setOrder(refundOrder)
|
||||
.setOutTradeNo(callbackInfo.getOutTradeNo())
|
||||
.setSource(TradeAdjustSourceEnum.CALLBACK)
|
||||
.setFinishTime(callbackInfo.getFinishTime());
|
||||
if (Objects.equals(RefundStatusEnum.SUCCESS.getCode(), callbackInfo.getOutStatus())) {
|
||||
param.setAdjustWay(RefundAdjustWayEnum.SUCCESS);
|
||||
String adjustNo = reflectionService.adjust(param);
|
||||
callbackInfo.setAdjustNo(adjustNo);
|
||||
this.success(refundOrder);
|
||||
} else {
|
||||
param.setAdjustWay(RefundAdjustWayEnum.FAIL);
|
||||
String adjustNo = reflectionService.adjust(param);
|
||||
callbackInfo.setAdjustNo(adjustNo);
|
||||
this.close(refundOrder);
|
||||
}
|
||||
|
||||
} finally {
|
||||
lockTemplate.releaseLock(lock);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 退款成功, 更新退款单和支付单
|
||||
*/
|
||||
private void success(RefundOrder refundOrder) {
|
||||
CallbackLocal callbackInfo = PaymentContextLocal.get().getCallbackInfo();
|
||||
PayOrder payOrder = payOrderService.findById(refundOrder.getOrderId())
|
||||
.orElseThrow(() -> new DataNotExistException("退款订单关联支付订单不存在"));
|
||||
|
||||
// 订单相关状态
|
||||
PayOrderRefundStatusEnum afterPayRefundStatus;
|
||||
|
||||
// 判断订单全部退款还是部分退款
|
||||
if (Objects.equals(payOrder.getRefundableBalance(), 0)) {
|
||||
afterPayRefundStatus = PayOrderRefundStatusEnum.REFUNDED;
|
||||
} else {
|
||||
afterPayRefundStatus = PayOrderRefundStatusEnum.PARTIAL_REFUND;
|
||||
}
|
||||
// 设置退款为完成状态和完成时间
|
||||
refundOrder.setStatus(RefundStatusEnum.SUCCESS.getCode())
|
||||
.setFinishTime(callbackInfo.getFinishTime());
|
||||
payOrder.setRefundStatus(afterPayRefundStatus.getCode());
|
||||
|
||||
// 更新订单和退款相关订单
|
||||
payOrderService.updateById(payOrder);
|
||||
refundOrderManager.updateById(refundOrder);
|
||||
|
||||
// 记录流水
|
||||
tradeFlowRecordService.saveRefund(refundOrder);
|
||||
// 发送通知
|
||||
clientNoticeService.registerRefundNotice(refundOrder);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 退款失败, 关闭退款单并将失败的退款金额归还回订单
|
||||
*/
|
||||
private void close(RefundOrder refundOrder) {
|
||||
PayOrder payOrder = payOrderService.findById(refundOrder.getOrderId())
|
||||
.orElseThrow(() -> new DataNotExistException("退款订单关联支付订单不存在"));
|
||||
// 退款失败返还后的余额
|
||||
int payOrderAmount = refundOrder.getAmount() + payOrder.getRefundableBalance();
|
||||
// 退款失败返还后的余额+可退余额 == 订单金额 支付订单回退为为支付成功状态
|
||||
if (payOrderAmount == payOrder.getAmount()) {
|
||||
payOrder.setStatus(PayStatusEnum.SUCCESS.getCode());
|
||||
} else {
|
||||
// 回归部分退款状态
|
||||
payOrder.setRefundStatus(PayOrderRefundStatusEnum.PARTIAL_REFUND.getCode());
|
||||
}
|
||||
|
||||
// 更新支付订单相关的可退款金额
|
||||
payOrder.setRefundableBalance(payOrderAmount);
|
||||
refundOrder.setStatus(RefundStatusEnum.CLOSE.getCode());
|
||||
|
||||
// 更新订单和退款相关订单
|
||||
payOrderService.updateById(payOrder);
|
||||
refundOrderManager.updateById(refundOrder);
|
||||
// 发送通知
|
||||
clientNoticeService.registerRefundNotice(refundOrder);
|
||||
}
|
||||
}
|
||||
|
@@ -1,11 +1,8 @@
|
||||
package cn.daxpay.single.service.core.payment.sync.result;
|
||||
|
||||
import cn.daxpay.single.service.core.payment.adjust.dto.AllocResultItem;
|
||||
import lombok.Data;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 分账同步结果
|
||||
* @author xxm
|
||||
@@ -16,14 +13,4 @@ import java.util.List;
|
||||
public class AllocRemoteSyncResult {
|
||||
/** 同步时网关返回的对象, 序列化为json字符串 */
|
||||
private String syncInfo;
|
||||
|
||||
/** 通用分账结果明细 */
|
||||
private List<AllocResultItem> resultItems;
|
||||
|
||||
/** 错误提示码 */
|
||||
private String errorCode;
|
||||
|
||||
/** 错误提示 */
|
||||
private String errorMsg;
|
||||
|
||||
}
|
||||
|
@@ -2,25 +2,23 @@ package cn.daxpay.single.service.core.payment.sync.service;
|
||||
|
||||
import cn.bootx.platform.common.core.exception.DataNotExistException;
|
||||
import cn.bootx.platform.common.core.exception.RepetitiveOperationException;
|
||||
import cn.daxpay.single.core.code.AllocDetailResultEnum;
|
||||
import cn.daxpay.single.core.code.AllocOrderResultEnum;
|
||||
import cn.daxpay.single.core.code.AllocOrderStatusEnum;
|
||||
import cn.daxpay.single.core.param.payment.allocation.AllocSyncParam;
|
||||
import cn.daxpay.single.core.result.sync.AllocSyncResult;
|
||||
import cn.daxpay.single.service.code.TradeAdjustSourceEnum;
|
||||
import cn.daxpay.single.service.code.TradeTypeEnum;
|
||||
import cn.daxpay.single.service.common.local.PaymentContextLocal;
|
||||
import cn.daxpay.single.service.core.order.allocation.dao.AllocOrderDetailManager;
|
||||
import cn.daxpay.single.service.core.order.allocation.dao.AllocOrderManager;
|
||||
import cn.daxpay.single.service.core.order.allocation.entity.AllocOrder;
|
||||
import cn.daxpay.single.service.core.order.allocation.entity.AllocOrderDetail;
|
||||
import cn.daxpay.single.service.core.payment.adjust.param.AllocAdjustParam;
|
||||
import cn.daxpay.single.service.core.payment.adjust.service.AllocAdjustService;
|
||||
import cn.daxpay.single.service.core.payment.notice.service.ClientNoticeService;
|
||||
import cn.daxpay.single.service.core.payment.sync.result.AllocRemoteSyncResult;
|
||||
import cn.daxpay.single.service.core.record.sync.entity.TradeSyncRecord;
|
||||
import cn.daxpay.single.service.core.record.sync.service.TradeSyncRecordService;
|
||||
import cn.daxpay.single.service.func.AbsAllocSyncStrategy;
|
||||
import cn.daxpay.single.service.func.AbsAllocStrategy;
|
||||
import cn.daxpay.single.service.util.PayStrategyFactory;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.baomidou.lock.LockInfo;
|
||||
import com.baomidou.lock.LockTemplate;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
@@ -29,6 +27,7 @@ import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Propagation;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
@@ -50,8 +49,6 @@ public class AllocSyncService {
|
||||
|
||||
private final TradeSyncRecordService tradeSyncRecordService;
|
||||
|
||||
private final AllocAdjustService allocAdjustService;
|
||||
|
||||
private final LockTemplate lockTemplate;
|
||||
|
||||
/**
|
||||
@@ -90,40 +87,86 @@ public class AllocSyncService {
|
||||
try {
|
||||
List<AllocOrderDetail> detailList = allocOrderDetailManager.findAllByOrderId(allocOrder.getId());
|
||||
// 获取分账策略
|
||||
AbsAllocSyncStrategy allocSyncStrategy = PayStrategyFactory.create(allocOrder.getChannel(), AbsAllocSyncStrategy.class);
|
||||
allocSyncStrategy.initParam(allocOrder);
|
||||
// 执行同步操作, 返账通用对账比对结果列表
|
||||
AllocRemoteSyncResult allocRemoteSyncResult = allocSyncStrategy.doSync();
|
||||
// 分账调整处理
|
||||
AllocAdjustParam allocAdjustParam = new AllocAdjustParam()
|
||||
.setSource(TradeAdjustSourceEnum.SYNC)
|
||||
.setOrder(allocOrder)
|
||||
.setDetails(detailList)
|
||||
.setResultItems(allocRemoteSyncResult.getResultItems());
|
||||
String adjustNo = allocAdjustService.adjust(allocAdjustParam);
|
||||
AbsAllocStrategy allocStrategy = PayStrategyFactory.create(allocOrder.getChannel(),AbsAllocStrategy.class);
|
||||
allocStrategy.initParam(allocOrder, detailList);
|
||||
// 分账完结预处理
|
||||
allocStrategy.doBeforeHandler();
|
||||
// 执行同步操作, 分账明细的状态变更会在这个里面
|
||||
AllocRemoteSyncResult allocRemoteSyncResult = allocStrategy.doSync();
|
||||
// 保存分账同步记录
|
||||
this.saveRecord(allocOrder, allocRemoteSyncResult, adjustNo);
|
||||
this.saveRecord(allocOrder, allocRemoteSyncResult,null,null);
|
||||
// 根据订单明细更新订单的状态和处理结果
|
||||
this.updateOrderStatus(allocOrder, detailList);
|
||||
} finally {
|
||||
lockTemplate.releaseLock(lock);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据订单明细更新订单的状态和处理结果, 如果订单是分账结束或失败, 不更新状态
|
||||
* TODO 是否多次同步会产生多次变动, 注意处理多次推送通知的问题, 目前是
|
||||
*/
|
||||
private void updateOrderStatus(AllocOrder allocOrder, List<AllocOrderDetail> details){
|
||||
// 如果是分账结束或失败, 不更新状态
|
||||
String status = allocOrder.getStatus();
|
||||
|
||||
// 如果是分账结束或失败, 不进行对订单进行处理
|
||||
List<String> list = Arrays.asList(AllocOrderStatusEnum.FINISH.getCode(), AllocOrderStatusEnum.FINISH_FAILED.getCode());
|
||||
if (!list.contains(status)){
|
||||
// 判断明细状态. 获取成功和失败的
|
||||
long successCount = details.stream()
|
||||
.map(AllocOrderDetail::getResult)
|
||||
.filter(AllocDetailResultEnum.SUCCESS.getCode()::equals)
|
||||
.count();
|
||||
long failCount = details.stream()
|
||||
.map(AllocOrderDetail::getResult)
|
||||
.filter(AllocDetailResultEnum.FAIL.getCode()::equals)
|
||||
.count();
|
||||
|
||||
// 成功和失败都为0 表示进行中
|
||||
if (successCount == 0 && failCount == 0){
|
||||
allocOrder.setStatus(AllocOrderStatusEnum.ALLOCATION_PROCESSING.getCode())
|
||||
.setResult(AllocOrderResultEnum.ALL_PENDING.getCode());
|
||||
} else {
|
||||
if (failCount == details.size()){
|
||||
// 全部失败
|
||||
allocOrder.setStatus(AllocOrderStatusEnum.ALLOCATION_END.getCode())
|
||||
.setResult(AllocOrderResultEnum.ALL_FAILED.getCode());
|
||||
} else if (successCount == details.size()){
|
||||
// 全部成功
|
||||
allocOrder.setStatus(AllocOrderStatusEnum.ALLOCATION_END.getCode())
|
||||
.setResult(AllocOrderResultEnum.ALL_SUCCESS.getCode());
|
||||
} else {
|
||||
// 部分成功
|
||||
allocOrder.setStatus(AllocOrderStatusEnum.ALLOCATION_END.getCode())
|
||||
.setResult(AllocOrderResultEnum.PART_SUCCESS.getCode());
|
||||
}
|
||||
}
|
||||
}
|
||||
allocOrderDetailManager.updateAllById(details);
|
||||
allocOrderManager.updateById(allocOrder);
|
||||
|
||||
// 如果状态为完成, 发送通知
|
||||
if (Objects.equals(AllocOrderStatusEnum.ALLOCATION_END.getCode(), allocOrder.getStatus())){
|
||||
// 发送通知
|
||||
clientNoticeService.registerAllocNotice(allocOrder, details);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 保存同步记录
|
||||
*/
|
||||
private void saveRecord(AllocOrder order, AllocRemoteSyncResult syncResult, String adjustNo){
|
||||
private void saveRecord(AllocOrder order, AllocRemoteSyncResult syncResult, String errorCode, String errorMsg){
|
||||
TradeSyncRecord tradeSyncRecord = new TradeSyncRecord()
|
||||
.setBizTradeNo(order.getBizAllocNo())
|
||||
.setTradeNo(order.getAllocNo())
|
||||
.setOutTradeNo(order.getOutAllocNo())
|
||||
.setType(TradeTypeEnum.ALLOCATION.getCode())
|
||||
.setAdjust(StrUtil.isNotBlank(adjustNo))
|
||||
.setAdjustNo(adjustNo)
|
||||
.setChannel(order.getChannel())
|
||||
.setSyncInfo(syncResult.getSyncInfo())
|
||||
.setErrorCode(syncResult.getErrorCode())
|
||||
.setErrorMsg(syncResult.getErrorMsg())
|
||||
.setErrorCode(errorCode)
|
||||
.setErrorMsg(errorMsg)
|
||||
.setClientIp(PaymentContextLocal.get().getClientInfo().getClientIp());
|
||||
tradeSyncRecordService.saveRecord(tradeSyncRecord);
|
||||
}
|
||||
|
@@ -9,21 +9,17 @@ import cn.daxpay.single.core.code.PaySyncStatusEnum;
|
||||
import cn.daxpay.single.core.exception.*;
|
||||
import cn.daxpay.single.core.param.payment.pay.PaySyncParam;
|
||||
import cn.daxpay.single.core.result.sync.PaySyncResult;
|
||||
import cn.daxpay.single.service.code.PayAdjustWayEnum;
|
||||
import cn.daxpay.single.service.code.TradeAdjustSourceEnum;
|
||||
import cn.daxpay.single.service.code.TradeTypeEnum;
|
||||
import cn.daxpay.single.service.common.local.PaymentContextLocal;
|
||||
import cn.daxpay.single.service.core.order.pay.entity.PayOrder;
|
||||
import cn.daxpay.single.service.core.order.pay.service.PayOrderQueryService;
|
||||
import cn.daxpay.single.service.core.order.pay.service.PayOrderService;
|
||||
import cn.daxpay.single.service.core.payment.adjust.param.PayAdjustParam;
|
||||
import cn.daxpay.single.service.core.payment.adjust.service.PayAdjustService;
|
||||
import cn.daxpay.single.service.core.payment.sync.result.PayRemoteSyncResult;
|
||||
import cn.daxpay.single.service.core.record.sync.entity.TradeSyncRecord;
|
||||
import cn.daxpay.single.service.core.record.sync.service.TradeSyncRecordService;
|
||||
import cn.daxpay.single.service.func.AbsPayCloseStrategy;
|
||||
import cn.daxpay.single.service.func.AbsPaySyncStrategy;
|
||||
import cn.daxpay.single.service.util.PayStrategyFactory;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.baomidou.lock.LockInfo;
|
||||
import com.baomidou.lock.LockTemplate;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
@@ -54,8 +50,6 @@ public class PaySyncService {
|
||||
|
||||
private final TradeSyncRecordService tradeSyncRecordService;
|
||||
|
||||
private final PayAdjustService payAdjustService;
|
||||
|
||||
private final LockTemplate lockTemplate;
|
||||
|
||||
/**
|
||||
@@ -95,7 +89,7 @@ public class PaySyncService {
|
||||
// 判断是否同步成功
|
||||
if (Objects.equals(payRemoteSyncResult.getSyncStatus(), FAIL)){
|
||||
// 同步失败, 返回失败响应, 同时记录失败的日志
|
||||
this.saveRecord(payOrder, payRemoteSyncResult, null);
|
||||
this.saveRecord(payOrder, payRemoteSyncResult, false);
|
||||
throw new OperationFailException(payRemoteSyncResult.getErrorMsg());
|
||||
}
|
||||
// 支付订单的网关订单号是否一致, 不一致进行更新
|
||||
@@ -105,20 +99,19 @@ public class PaySyncService {
|
||||
}
|
||||
// 判断网关状态是否和支付单一致, 同时特定情况下更新网关同步状态
|
||||
boolean statusSync = this.checkAndAdjustSyncStatus(payRemoteSyncResult,payOrder);
|
||||
String adjustNo = null;
|
||||
try {
|
||||
// 状态不一致,执行支付单调整逻辑
|
||||
if (!statusSync){
|
||||
adjustNo = this.adjustHandler(payRemoteSyncResult, payOrder);
|
||||
this.adjustHandler(payRemoteSyncResult, payOrder);
|
||||
}
|
||||
} catch (PayFailureException e) {
|
||||
// 同步失败, 返回失败响应, 同时记录失败的日志
|
||||
payRemoteSyncResult.setSyncStatus(FAIL);
|
||||
this.saveRecord(payOrder, payRemoteSyncResult, null);
|
||||
this.saveRecord(payOrder, payRemoteSyncResult, false);
|
||||
throw e;
|
||||
}
|
||||
// 同步成功记录日志
|
||||
this.saveRecord( payOrder, payRemoteSyncResult, adjustNo);
|
||||
this.saveRecord( payOrder, payRemoteSyncResult, statusSync);
|
||||
return new PaySyncResult().setStatus(payRemoteSyncResult.getSyncStatus().getCode());
|
||||
} finally {
|
||||
lockTemplate.releaseLock(lock);
|
||||
@@ -171,34 +164,26 @@ public class PaySyncService {
|
||||
|
||||
/**
|
||||
* 根据同步的结果对支付单进行调整处理
|
||||
* @return 调整单号, 如果为空, 说明订单未做调整
|
||||
*/
|
||||
private String adjustHandler(PayRemoteSyncResult payRemoteSyncResult, PayOrder payOrder){
|
||||
private void adjustHandler(PayRemoteSyncResult payRemoteSyncResult, PayOrder payOrder){
|
||||
PaySyncStatusEnum syncStatusEnum = payRemoteSyncResult.getSyncStatus();
|
||||
PayAdjustParam param = new PayAdjustParam()
|
||||
.setOrder(payOrder)
|
||||
.setSource(TradeAdjustSourceEnum.SYNC)
|
||||
.setFinishTime(payRemoteSyncResult.getFinishTime());
|
||||
// 对支付网关同步的结果进行处理
|
||||
switch (syncStatusEnum) {
|
||||
// 支付成功 支付宝退款时也是支付成功状态, 除非支付完成
|
||||
case SUCCESS: {
|
||||
param.setAdjustWay(PayAdjustWayEnum.SUCCESS);
|
||||
return payAdjustService.adjust(param);
|
||||
this.success(payOrder, payRemoteSyncResult);
|
||||
}
|
||||
case REFUND:
|
||||
throw new TradeStatusErrorException("支付订单为退款状态,请通过执行对应的退款订单进行同步,来更新具体为什么类型退款状态");
|
||||
// 交易关闭和未找到, 都对本地支付订单进行关闭, 不需要再调用网关进行关闭
|
||||
case CLOSED:
|
||||
case NOT_FOUND: {
|
||||
param.setAdjustWay(PayAdjustWayEnum.CLOSE_LOCAL);
|
||||
return payAdjustService.adjust(param);
|
||||
this.closeLocal(payOrder);
|
||||
}
|
||||
// 超时关闭和交易不存在(特殊) 关闭本地支付订单, 同时调用网关进行关闭, 确保后续这个订单不能被支付
|
||||
case TIMEOUT:
|
||||
this.closeRemote(payOrder);
|
||||
case NOT_FOUND_UNKNOWN:{
|
||||
param.setAdjustWay(PayAdjustWayEnum.CLOSE_GATEWAY);
|
||||
return payAdjustService.adjust(param);
|
||||
}
|
||||
// 调用出错
|
||||
case FAIL: {
|
||||
@@ -210,17 +195,55 @@ public class PaySyncService {
|
||||
throw new SystemUnknownErrorException("代码有问题");
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 变更为已支付
|
||||
* 同步: 将异步支付状态修改为成功
|
||||
* 回调: 将异步支付状态修改为成功
|
||||
*/
|
||||
private void success(PayOrder order, PayRemoteSyncResult param) {
|
||||
// 修改订单支付状态为成功
|
||||
order.setStatus(PayStatusEnum.SUCCESS.getCode())
|
||||
.setPayTime(param.getFinishTime())
|
||||
.setOutOrderNo(param.getOutOrderNo())
|
||||
.setCloseTime(null);
|
||||
payOrderService.updateById(order);
|
||||
}
|
||||
|
||||
/**
|
||||
* 关闭支付
|
||||
* 同步/对账: 执行支付单所有的支付通道关闭支付逻辑, 不需要调用网关关闭,
|
||||
*/
|
||||
private void closeLocal(PayOrder order) {
|
||||
// 执行策略的关闭方法
|
||||
order.setStatus(PayStatusEnum.CLOSE.getCode())
|
||||
.setCloseTime(LocalDateTime.now());
|
||||
payOrderService.updateById(order);
|
||||
}
|
||||
/**
|
||||
* 关闭网关交易, 同时也会关闭本地支付
|
||||
* 回调: 执行所有的支付通道关闭支付逻辑
|
||||
*/
|
||||
private void closeRemote(PayOrder payOrder) {
|
||||
// 初始化调整参数
|
||||
AbsPayCloseStrategy strategy = PayStrategyFactory.create(payOrder.getChannel(), AbsPayCloseStrategy.class);
|
||||
strategy.setOrder(payOrder);
|
||||
// 执行策略的关闭方法
|
||||
strategy.doCloseHandler();
|
||||
payOrder.setStatus(PayStatusEnum.CLOSE.getCode())
|
||||
.setCloseTime(LocalDateTime.now());
|
||||
payOrderService.updateById(payOrder);
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存同步记录
|
||||
* @param payOrder 支付单
|
||||
* @param payRemoteSyncResult 同步结果
|
||||
* @param adjustNo 调整号
|
||||
* @param adjust 调整号
|
||||
*/
|
||||
private void saveRecord(PayOrder payOrder, PayRemoteSyncResult payRemoteSyncResult, String adjustNo){
|
||||
private void saveRecord(PayOrder payOrder, PayRemoteSyncResult payRemoteSyncResult, boolean adjust){
|
||||
TradeSyncRecord tradeSyncRecord = new TradeSyncRecord()
|
||||
.setBizTradeNo(payOrder.getBizOrderNo())
|
||||
.setTradeNo(payOrder.getOrderNo())
|
||||
@@ -229,8 +252,7 @@ public class PaySyncService {
|
||||
.setType(TradeTypeEnum.PAY.getCode())
|
||||
.setChannel(payOrder.getChannel())
|
||||
.setSyncInfo(payRemoteSyncResult.getSyncInfo())
|
||||
.setAdjust(StrUtil.isNotBlank(adjustNo))
|
||||
.setAdjustNo(adjustNo)
|
||||
.setAdjust(adjust)
|
||||
.setErrorCode(payRemoteSyncResult.getErrorCode())
|
||||
.setErrorMsg(payRemoteSyncResult.getErrorMsg())
|
||||
.setClientIp(PaymentContextLocal.get().getClientInfo().getClientIp());
|
||||
|
@@ -1,7 +1,10 @@
|
||||
package cn.daxpay.single.service.core.payment.sync.service;
|
||||
|
||||
import cn.bootx.platform.common.core.exception.BizException;
|
||||
import cn.bootx.platform.common.core.exception.DataNotExistException;
|
||||
import cn.bootx.platform.common.core.exception.RepetitiveOperationException;
|
||||
import cn.daxpay.single.core.code.PayOrderRefundStatusEnum;
|
||||
import cn.daxpay.single.core.code.PayStatusEnum;
|
||||
import cn.daxpay.single.core.code.RefundStatusEnum;
|
||||
import cn.daxpay.single.core.code.RefundSyncStatusEnum;
|
||||
import cn.daxpay.single.core.exception.OperationFailException;
|
||||
@@ -9,21 +12,20 @@ import cn.daxpay.single.core.exception.PayFailureException;
|
||||
import cn.daxpay.single.core.exception.TradeNotExistException;
|
||||
import cn.daxpay.single.core.param.payment.refund.RefundSyncParam;
|
||||
import cn.daxpay.single.core.result.sync.RefundSyncResult;
|
||||
import cn.daxpay.single.service.code.RefundAdjustWayEnum;
|
||||
import cn.daxpay.single.service.code.TradeAdjustSourceEnum;
|
||||
import cn.daxpay.single.service.code.TradeTypeEnum;
|
||||
import cn.daxpay.single.service.common.local.PaymentContextLocal;
|
||||
import cn.daxpay.single.service.core.order.pay.entity.PayOrder;
|
||||
import cn.daxpay.single.service.core.order.pay.service.PayOrderService;
|
||||
import cn.daxpay.single.service.core.order.refund.dao.RefundOrderManager;
|
||||
import cn.daxpay.single.service.core.order.refund.entity.RefundOrder;
|
||||
import cn.daxpay.single.service.core.order.refund.service.RefundOrderQueryService;
|
||||
import cn.daxpay.single.service.core.payment.adjust.param.RefundAdjustParam;
|
||||
import cn.daxpay.single.service.core.payment.adjust.service.RefundAdjustService;
|
||||
import cn.daxpay.single.service.core.payment.notice.service.ClientNoticeService;
|
||||
import cn.daxpay.single.service.core.payment.sync.result.RefundRemoteSyncResult;
|
||||
import cn.daxpay.single.service.core.record.flow.service.TradeFlowRecordService;
|
||||
import cn.daxpay.single.service.core.record.sync.entity.TradeSyncRecord;
|
||||
import cn.daxpay.single.service.core.record.sync.service.TradeSyncRecordService;
|
||||
import cn.daxpay.single.service.func.AbsRefundSyncStrategy;
|
||||
import cn.daxpay.single.service.util.PayStrategyFactory;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.baomidou.lock.LockInfo;
|
||||
import com.baomidou.lock.LockTemplate;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
@@ -49,9 +51,10 @@ public class RefundSyncService {
|
||||
|
||||
private final TradeSyncRecordService tradeSyncRecordService;
|
||||
|
||||
private final RefundAdjustService adjustService;
|
||||
|
||||
private final LockTemplate lockTemplate;
|
||||
private final PayOrderService payOrderService;
|
||||
private final TradeFlowRecordService tradeFlowRecordService;
|
||||
private final ClientNoticeService clientNoticeService;
|
||||
|
||||
/**
|
||||
* 退款同步, 开启一个新的事务, 不受外部抛出异常的影响
|
||||
@@ -90,7 +93,7 @@ public class RefundSyncService {
|
||||
// 判断是否同步成功
|
||||
if (Objects.equals(refundRemoteSyncResult.getSyncStatus(), RefundSyncStatusEnum.FAIL)) {
|
||||
// 同步失败, 返回失败响应, 同时记录失败的日志
|
||||
this.saveRecord(refundOrder, refundRemoteSyncResult, null);
|
||||
this.saveRecord(refundOrder, refundRemoteSyncResult, false);
|
||||
throw new OperationFailException(refundRemoteSyncResult.getErrorMsg());
|
||||
}
|
||||
// 订单的通道交易号是否一致, 不一致进行更新
|
||||
@@ -100,21 +103,20 @@ public class RefundSyncService {
|
||||
}
|
||||
// 判断网关状态是否和支付单一致
|
||||
boolean statusSync = this.checkSyncStatus(refundRemoteSyncResult, refundOrder);
|
||||
String adjustNo = null;
|
||||
try {
|
||||
// 状态不一致,执行退款单调整逻辑
|
||||
if (!statusSync) {
|
||||
// 如果没有支付来源, 设置支付来源为同步
|
||||
adjustNo = this.adjustHandler(refundRemoteSyncResult, refundOrder);
|
||||
this.adjustHandler(refundRemoteSyncResult, refundOrder);
|
||||
}
|
||||
} catch (PayFailureException e) {
|
||||
// 同步失败, 返回失败响应, 同时记录失败的日志
|
||||
refundRemoteSyncResult.setSyncStatus(RefundSyncStatusEnum.FAIL);
|
||||
this.saveRecord(refundOrder, refundRemoteSyncResult, null);
|
||||
this.saveRecord(refundOrder, refundRemoteSyncResult, statusSync);
|
||||
throw e;
|
||||
}
|
||||
// 同步成功记录日志
|
||||
this.saveRecord(refundOrder, refundRemoteSyncResult, adjustNo);
|
||||
this.saveRecord(refundOrder, refundRemoteSyncResult, statusSync);
|
||||
return new RefundSyncResult().setStatus(refundRemoteSyncResult.getSyncStatus().getCode());
|
||||
} finally {
|
||||
lockTemplate.releaseLock(lock);
|
||||
@@ -135,7 +137,6 @@ public class RefundSyncService {
|
||||
Objects.equals(orderStatus, RefundStatusEnum.SUCCESS.getCode())) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// 退款失败
|
||||
if (Objects.equals(syncStatus, RefundSyncStatusEnum.FAIL)&&
|
||||
Objects.equals(orderStatus, RefundStatusEnum.FAIL.getCode())) {
|
||||
@@ -152,43 +153,95 @@ public class RefundSyncService {
|
||||
/**
|
||||
* 进行退款订单和支付订单的调整
|
||||
*/
|
||||
private String adjustHandler(RefundRemoteSyncResult syncResult, RefundOrder order){
|
||||
private void adjustHandler(RefundRemoteSyncResult syncResult, RefundOrder order){
|
||||
RefundSyncStatusEnum syncStatusEnum = syncResult.getSyncStatus();
|
||||
RefundAdjustParam param = new RefundAdjustParam()
|
||||
.setOrder(order)
|
||||
.setOutTradeNo(syncResult.getOutRefundNo())
|
||||
.setSource(TradeAdjustSourceEnum.SYNC)
|
||||
.setFinishTime(syncResult.getFinishTime());
|
||||
|
||||
// 对支付网关同步的结果进行处理
|
||||
switch (syncStatusEnum) {
|
||||
case SUCCESS:
|
||||
param.setAdjustWay(RefundAdjustWayEnum.SUCCESS);
|
||||
return adjustService.adjust(param);
|
||||
this.success(order, syncResult);
|
||||
break;
|
||||
case PROGRESS:
|
||||
// 不进行处理
|
||||
break;
|
||||
case FAIL: {
|
||||
param.setAdjustWay(RefundAdjustWayEnum.FAIL);
|
||||
return adjustService.adjust(param);
|
||||
this.close(order);
|
||||
break;
|
||||
}
|
||||
case NOT_FOUND:
|
||||
param.setAdjustWay(RefundAdjustWayEnum.FAIL);
|
||||
return adjustService.adjust(param);
|
||||
this.close(order);
|
||||
break;
|
||||
default: {
|
||||
throw new BizException("代码有问题");
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 退款成功, 更新退款单和支付单
|
||||
*/
|
||||
private void success(RefundOrder refundOrder,RefundRemoteSyncResult syncResult) {
|
||||
PayOrder payOrder = payOrderService.findById(refundOrder.getOrderId())
|
||||
.orElseThrow(() -> new DataNotExistException("退款订单关联支付订单不存在"));
|
||||
|
||||
// 订单相关状态
|
||||
PayOrderRefundStatusEnum afterPayRefundStatus;
|
||||
|
||||
// 判断订单全部退款还是部分退款
|
||||
if (Objects.equals(payOrder.getRefundableBalance(), 0)) {
|
||||
afterPayRefundStatus = PayOrderRefundStatusEnum.REFUNDED;
|
||||
} else {
|
||||
afterPayRefundStatus = PayOrderRefundStatusEnum.PARTIAL_REFUND;
|
||||
}
|
||||
// 设置退款为完成状态和完成时间
|
||||
refundOrder.setStatus(RefundStatusEnum.SUCCESS.getCode())
|
||||
.setFinishTime(syncResult.getFinishTime());
|
||||
payOrder.setRefundStatus(afterPayRefundStatus.getCode());
|
||||
|
||||
// 更新订单和退款相关订单
|
||||
payOrderService.updateById(payOrder);
|
||||
refundOrderManager.updateById(refundOrder);
|
||||
|
||||
// 记录流水
|
||||
tradeFlowRecordService.saveRefund(refundOrder);
|
||||
// 发送通知
|
||||
clientNoticeService.registerRefundNotice(refundOrder);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 退款失败, 关闭退款单并将失败的退款金额归还回订单
|
||||
*/
|
||||
private void close(RefundOrder refundOrder) {
|
||||
PayOrder payOrder = payOrderService.findById(refundOrder.getOrderId())
|
||||
.orElseThrow(() -> new DataNotExistException("退款订单关联支付订单不存在"));
|
||||
// 退款失败返还后的余额
|
||||
int payOrderAmount = refundOrder.getAmount() + payOrder.getRefundableBalance();
|
||||
// 退款失败返还后的余额+可退余额 == 订单金额 支付订单回退为为支付成功状态
|
||||
if (payOrderAmount == payOrder.getAmount()) {
|
||||
payOrder.setStatus(PayStatusEnum.SUCCESS.getCode());
|
||||
} else {
|
||||
// 回归部分退款状态
|
||||
payOrder.setRefundStatus(PayOrderRefundStatusEnum.PARTIAL_REFUND.getCode());
|
||||
}
|
||||
|
||||
// 更新支付订单相关的可退款金额
|
||||
payOrder.setRefundableBalance(payOrderAmount);
|
||||
refundOrder.setStatus(RefundStatusEnum.CLOSE.getCode());
|
||||
|
||||
// 更新订单和退款相关订单
|
||||
payOrderService.updateById(payOrder);
|
||||
refundOrderManager.updateById(refundOrder);
|
||||
// 发送通知
|
||||
clientNoticeService.registerRefundNotice(refundOrder);
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存同步记录, 使用新事务进行保存
|
||||
* @param refundOrder 支付单
|
||||
* @param syncResult 同步结果
|
||||
* @param adjustNo 调整号
|
||||
*/
|
||||
private void saveRecord(RefundOrder refundOrder, RefundRemoteSyncResult syncResult, String adjustNo){
|
||||
private void saveRecord(RefundOrder refundOrder, RefundRemoteSyncResult syncResult, boolean adjust){
|
||||
TradeSyncRecord tradeSyncRecord = new TradeSyncRecord()
|
||||
.setTradeNo(refundOrder.getRefundNo())
|
||||
.setBizTradeNo(refundOrder.getBizRefundNo())
|
||||
@@ -197,8 +250,7 @@ public class RefundSyncService {
|
||||
.setType(TradeTypeEnum.REFUND.getCode())
|
||||
.setChannel(refundOrder.getChannel())
|
||||
.setSyncInfo(syncResult.getSyncInfo())
|
||||
.setAdjust(StrUtil.isNotBlank(adjustNo))
|
||||
.setAdjustNo(adjustNo)
|
||||
.setAdjust(adjust)
|
||||
.setErrorCode(syncResult.getErrorCode())
|
||||
.setErrorMsg(syncResult.getErrorMsg())
|
||||
.setClientIp(PaymentContextLocal.get().getClientInfo().getClientIp());
|
||||
|
@@ -33,7 +33,7 @@ public class AliAllocStrategy extends AbsAllocSyncStrategy {
|
||||
@Override
|
||||
public AllocRemoteSyncResult doSync() {
|
||||
AliPayConfig config = alipayConfigService.getConfig();
|
||||
return aliPayAllocService.sync(this.getAllocOrder(), config);
|
||||
return aliPayAllocService.sync(this.getAllocOrder(),this.getAllocOrderDetails(), config);
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -36,6 +36,6 @@ public class WeChatAllocSyncStrategy extends AbsAllocSyncStrategy {
|
||||
@Override
|
||||
public AllocRemoteSyncResult doSync() {
|
||||
WeChatPayConfig config = weChatPayConfigService.getConfig();
|
||||
return weChatPayAllocService.sync(this.getAllocOrder(),config);
|
||||
return weChatPayAllocService.sync(this.getAllocOrder(),this.getAllocOrderDetails(), config);
|
||||
}
|
||||
}
|
||||
|
@@ -1,18 +0,0 @@
|
||||
package cn.daxpay.single.service.core.record.adjust.convert;
|
||||
|
||||
import cn.daxpay.single.service.core.record.adjust.entity.TradeAdjustRecord;
|
||||
import cn.daxpay.single.service.dto.record.adjust.TradeAdjustRecordDto;
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.factory.Mappers;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author xxm
|
||||
* @since 2024/7/15
|
||||
*/
|
||||
@Mapper
|
||||
public interface TradeAdjustRecordConvert {
|
||||
TradeAdjustRecordConvert CONVERT = Mappers.getMapper(TradeAdjustRecordConvert.class);
|
||||
|
||||
TradeAdjustRecordDto convert(TradeAdjustRecord in);
|
||||
}
|
@@ -1,32 +0,0 @@
|
||||
package cn.daxpay.single.service.core.record.adjust.dao;
|
||||
|
||||
import cn.bootx.platform.common.core.rest.param.PageParam;
|
||||
import cn.bootx.platform.common.mybatisplus.impl.BaseManager;
|
||||
import cn.bootx.platform.common.mybatisplus.util.MpUtil;
|
||||
import cn.bootx.platform.common.query.generator.QueryGenerator;
|
||||
import cn.daxpay.single.service.core.record.adjust.entity.TradeAdjustRecord;
|
||||
import cn.daxpay.single.service.param.report.TradeAdjustRecordQuery;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author xxm
|
||||
* @since 2024/7/15
|
||||
*/
|
||||
@Slf4j
|
||||
@Repository
|
||||
@RequiredArgsConstructor
|
||||
public class TradeAdjustRecordManager extends BaseManager<TradeAdjustRecordMapper, TradeAdjustRecord> {
|
||||
|
||||
public Page<TradeAdjustRecord> page(PageParam pageParam, TradeAdjustRecordQuery param){
|
||||
QueryWrapper<TradeAdjustRecord> generator = QueryGenerator.generator(param);
|
||||
Page<TradeAdjustRecord> mpPage = MpUtil.getMpPage(pageParam, TradeAdjustRecord.class);
|
||||
|
||||
return this.page(mpPage, generator);
|
||||
|
||||
}
|
||||
}
|
@@ -1,14 +0,0 @@
|
||||
package cn.daxpay.single.service.core.record.adjust.dao;
|
||||
|
||||
import cn.daxpay.single.service.core.record.adjust.entity.TradeAdjustRecord;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
/**
|
||||
* 交易调整记录
|
||||
* @author xxm
|
||||
* @since 2024/7/15
|
||||
*/
|
||||
@Mapper
|
||||
public interface TradeAdjustRecordMapper extends BaseMapper<TradeAdjustRecord> {
|
||||
}
|
@@ -1,100 +0,0 @@
|
||||
package cn.daxpay.single.service.core.record.adjust.entity;
|
||||
|
||||
import cn.bootx.platform.common.core.function.EntityBaseFunction;
|
||||
import cn.bootx.platform.common.mybatisplus.base.MpCreateEntity;
|
||||
import cn.bootx.table.modify.annotation.DbColumn;
|
||||
import cn.bootx.table.modify.mysql.annotation.DbMySqlFieldType;
|
||||
import cn.bootx.table.modify.mysql.annotation.DbMySqlIndex;
|
||||
import cn.bootx.table.modify.mysql.constants.MySqlFieldTypeEnum;
|
||||
import cn.daxpay.single.core.code.PayStatusEnum;
|
||||
import cn.daxpay.single.service.code.TradeAdjustSourceEnum;
|
||||
import cn.daxpay.single.service.core.record.adjust.convert.TradeAdjustRecordConvert;
|
||||
import cn.daxpay.single.service.dto.record.adjust.TradeAdjustRecordDto;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
/**
|
||||
* 订单调整记录
|
||||
* @author xxm
|
||||
* @since 2024/7/15
|
||||
*/
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
@TableName("pay_trade_adjust_record")
|
||||
public class TradeAdjustRecord extends MpCreateEntity implements EntityBaseFunction<TradeAdjustRecordDto> {
|
||||
|
||||
/**
|
||||
* 调整号
|
||||
*/
|
||||
@DbColumn(comment = "调整号", length = 32, isNull = false)
|
||||
private String adjustNo;
|
||||
|
||||
/** 交易ID */
|
||||
@DbColumn(comment = "本地订单ID", isNull = false)
|
||||
private Long tradeId;
|
||||
|
||||
/**
|
||||
* 本地交易号, 支付号/退款号
|
||||
*/
|
||||
@DbMySqlIndex(comment = "本地交易号索引")
|
||||
@DbColumn(comment = "本地交易号", length = 32, isNull = false)
|
||||
private String tradeNo;
|
||||
|
||||
/** 通道 */
|
||||
@DbColumn(comment = "通道", length = 20, isNull = false)
|
||||
private String channel;
|
||||
|
||||
/**
|
||||
* 来源
|
||||
* @see TradeAdjustSourceEnum
|
||||
*/
|
||||
@DbColumn(comment = "调整来源", length = 20, isNull = false)
|
||||
private String source;
|
||||
|
||||
/**
|
||||
* 调整类型
|
||||
* @see cn.daxpay.single.service.code.TradeNotifyTypeEnum
|
||||
*/
|
||||
@DbColumn(comment = "调整类型", length = 20, isNull = false)
|
||||
private String type;
|
||||
|
||||
/**
|
||||
* 调整方式
|
||||
*/
|
||||
@DbColumn(comment = "调整方式", length = 20, isNull = false)
|
||||
private String way;
|
||||
/**
|
||||
* 调整前状态
|
||||
* @see PayStatusEnum
|
||||
*/
|
||||
@DbColumn(comment = "调整前状态", length = 20, isNull = false)
|
||||
private String beforeStatus;
|
||||
|
||||
/**
|
||||
* 调整后状态
|
||||
*/
|
||||
@DbColumn(comment = "调整后状态", length = 20, isNull = false)
|
||||
private String afterStatus;
|
||||
|
||||
/**
|
||||
* 扩展信息, json格式
|
||||
*/
|
||||
@DbColumn(comment = "扩展信息")
|
||||
@DbMySqlFieldType(MySqlFieldTypeEnum.LONGTEXT)
|
||||
private String ext;
|
||||
|
||||
/**
|
||||
* 备注
|
||||
*/
|
||||
@DbColumn(comment = "备注", length = 600)
|
||||
private String remark;
|
||||
|
||||
|
||||
@Override
|
||||
public TradeAdjustRecordDto toDto() {
|
||||
return TradeAdjustRecordConvert.CONVERT.convert(this);
|
||||
}
|
||||
}
|
@@ -1,58 +0,0 @@
|
||||
package cn.daxpay.single.service.core.record.adjust.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.daxpay.single.service.core.record.adjust.dao.TradeAdjustRecordManager;
|
||||
import cn.daxpay.single.service.core.record.adjust.entity.TradeAdjustRecord;
|
||||
import cn.daxpay.single.service.dto.record.adjust.TradeAdjustRecordDto;
|
||||
import cn.daxpay.single.service.param.report.TradeAdjustRecordQuery;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Propagation;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 交易调整记录
|
||||
* @author xxm
|
||||
* @since 2024/7/15
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class TradeAdjustRecordService {
|
||||
private final TradeAdjustRecordManager tradeAdjustRecordManager;
|
||||
|
||||
/**
|
||||
* 根据id查询
|
||||
*/
|
||||
public TradeAdjustRecordDto findById(Long id) {
|
||||
return tradeAdjustRecordManager.findById(id).map(TradeAdjustRecord::toDto).orElseThrow(DataNotExistException::new);
|
||||
}
|
||||
|
||||
/**
|
||||
* 分页查询
|
||||
*/
|
||||
public PageResult<TradeAdjustRecordDto> page(PageParam pageParam, TradeAdjustRecordQuery param){
|
||||
return MpUtil.convert2DtoPageResult(tradeAdjustRecordManager.page(pageParam,param));
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存记录
|
||||
*/
|
||||
@Transactional(propagation = Propagation.REQUIRES_NEW, rollbackFor = Exception.class)
|
||||
public void saveRecord(TradeAdjustRecord record){
|
||||
tradeAdjustRecordManager.save(record);
|
||||
}
|
||||
/**
|
||||
* 保存记录
|
||||
*/
|
||||
@Transactional(propagation = Propagation.REQUIRES_NEW, rollbackFor = Exception.class)
|
||||
public void saveAllRecord(List<TradeAdjustRecord> records){
|
||||
tradeAdjustRecordManager.saveAll(records);
|
||||
}
|
||||
}
|
@@ -59,15 +59,12 @@ public class PayCallbackRecord extends MpCreateEntity implements EntityBaseFunct
|
||||
private String notifyInfo;
|
||||
|
||||
/**
|
||||
* 回调处理状态
|
||||
* @see PayCallbackStatusEnum
|
||||
*/
|
||||
@DbColumn(comment = "回调处理状态", length = 20, isNull = false)
|
||||
private String status;
|
||||
|
||||
/** 调整号 */
|
||||
@DbColumn(comment = "调整号", length = 32, isNull = false)
|
||||
private String adjustNo;
|
||||
|
||||
/** 错误码 */
|
||||
@DbColumn(comment = "错误码", length = 10)
|
||||
private String errorCode;
|
||||
|
@@ -54,7 +54,6 @@ public class PayCallbackRecordService {
|
||||
.setChannel(callbackInfo.getChannel())
|
||||
.setNotifyInfo(JSONUtil.toJsonStr(callbackInfo.getCallbackParam()))
|
||||
.setCallbackType(callbackInfo.getCallbackType().getCode())
|
||||
.setAdjustNo(callbackInfo.getAdjustNo())
|
||||
.setStatus(callbackInfo.getCallbackStatus().getCode())
|
||||
.setErrorMsg(callbackInfo.getErrorMsg());
|
||||
callbackRecordManager.save(payNotifyRecord);
|
||||
|
@@ -78,10 +78,6 @@ public class TradeSyncRecord extends MpCreateEntity implements EntityBaseFunctio
|
||||
@DbColumn(comment = "是否进行调整", isNull = false)
|
||||
private boolean adjust;
|
||||
|
||||
/** 调整记录号 */
|
||||
@DbColumn(comment = "调整记录号", length = 32)
|
||||
private String adjustNo;
|
||||
|
||||
/** 错误码 */
|
||||
@DbColumn(comment = "错误码", length = 10)
|
||||
private String errorCode;
|
||||
|
@@ -15,6 +15,6 @@ import lombok.experimental.Accessors;
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
@Schema(title = "交易调整记录")
|
||||
public class TradeAdjustRecordDto extends BaseDto {
|
||||
public class PayAdjustRecordDto extends BaseDto {
|
||||
|
||||
}
|
@@ -0,0 +1,20 @@
|
||||
package cn.daxpay.single.service.dto.record.adjust;
|
||||
|
||||
import cn.bootx.platform.common.core.rest.dto.BaseDto;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
/**
|
||||
* 退款调整记录
|
||||
* @author xxm
|
||||
* @since 2024/7/15
|
||||
*/
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
@Schema(title = "交易调整记录")
|
||||
public class RefundAdjustRecordDto extends BaseDto {
|
||||
|
||||
}
|
@@ -0,0 +1,20 @@
|
||||
package cn.daxpay.single.service.dto.record.adjust;
|
||||
|
||||
import cn.bootx.platform.common.core.rest.dto.BaseDto;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.experimental.Accessors;
|
||||
|
||||
/**
|
||||
* 退款调整记录
|
||||
* @author xxm
|
||||
* @since 2024/7/15
|
||||
*/
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Data
|
||||
@Accessors(chain = true)
|
||||
@Schema(title = "交易调整记录")
|
||||
public class TransferAdjustRecordDto extends BaseDto {
|
||||
|
||||
}
|
@@ -2,6 +2,7 @@ package cn.daxpay.single.service.func;
|
||||
|
||||
import cn.daxpay.single.service.core.order.allocation.entity.AllocOrder;
|
||||
import cn.daxpay.single.service.core.order.allocation.entity.AllocOrderDetail;
|
||||
import cn.daxpay.single.service.core.payment.sync.result.AllocRemoteSyncResult;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
@@ -44,4 +45,9 @@ public abstract class AbsAllocStrategy implements PayStrategy{
|
||||
* 分账完结
|
||||
*/
|
||||
public abstract void finish();
|
||||
|
||||
/**
|
||||
* 同步状态
|
||||
*/
|
||||
public abstract AllocRemoteSyncResult doSync();
|
||||
}
|
||||
|
@@ -1,11 +1,14 @@
|
||||
package cn.daxpay.single.service.func;
|
||||
|
||||
import cn.daxpay.single.service.core.order.allocation.entity.AllocOrder;
|
||||
import cn.daxpay.single.service.core.order.allocation.entity.AllocOrderDetail;
|
||||
import cn.daxpay.single.service.core.payment.sync.result.AllocRemoteSyncResult;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 分账同步策略
|
||||
* @author xxm
|
||||
@@ -18,11 +21,14 @@ public abstract class AbsAllocSyncStrategy implements PayStrategy{
|
||||
|
||||
private AllocOrder allocOrder;
|
||||
|
||||
private List<AllocOrderDetail> allocOrderDetails;
|
||||
|
||||
/**
|
||||
* 初始化参数
|
||||
*/
|
||||
public void initParam(AllocOrder allocOrder) {
|
||||
public void initParam(AllocOrder allocOrder, List<AllocOrderDetail> allocOrderDetails) {
|
||||
this.allocOrder = allocOrder;
|
||||
this.allocOrderDetails = allocOrderDetails;
|
||||
}
|
||||
|
||||
/**
|
||||
|
Reference in New Issue
Block a user