mirror of
https://gitee.com/dromara/dax-pay.git
synced 2025-09-03 19:16:21 +00:00
feat 自动分账/状态同步/自动完结
This commit is contained in:
@@ -32,12 +32,13 @@
|
|||||||
- [x] 支付订单和退款订单页面添加实时金额汇总展示
|
- [x] 支付订单和退款订单页面添加实时金额汇总展示
|
||||||
- [ ] 自动分账改造
|
- [ ] 自动分账改造
|
||||||
- [ ] SDK新增对账接收放添加接口
|
- [ ] SDK新增对账接收放添加接口
|
||||||
- [ ] 创建定时任务, 自动对待分账订单进行分账
|
- [x] 创建定时任务, 自动对待分账订单进行分账
|
||||||
- [ ] 增加定时同步分账状态任务
|
- [x] 增加定时同步分账状态任务
|
||||||
- [ ] 增加自动完结功能
|
- [x] 增加自动完结功能
|
||||||
2.0.7: 分账完善和基础架构优化
|
2.0.7: 分账完善和基础架构优化
|
||||||
- [ ] 资金流水优化
|
- [ ] 资金流水优化
|
||||||
- [ ] 数据加密方式改为类型处理器模式
|
- [ ] 数据加密方式改为类型处理器模式
|
||||||
|
- [ ]
|
||||||
- [ ] 支持分账组分账和自己传接收方进行分账
|
- [ ] 支持分账组分账和自己传接收方进行分账
|
||||||
- [ ] DEMO增加获取微信OpenID和支付宝OpenId功能
|
- [ ] DEMO增加获取微信OpenID和支付宝OpenId功能
|
||||||
- [ ] 分账接收方管理提供接口调用
|
- [ ] 分账接收方管理提供接口调用
|
||||||
|
@@ -19,6 +19,7 @@ import cn.bootx.platform.daxpay.service.dto.order.pay.PayOrderDetailDto;
|
|||||||
import cn.bootx.platform.daxpay.service.dto.order.pay.PayOrderDto;
|
import cn.bootx.platform.daxpay.service.dto.order.pay.PayOrderDto;
|
||||||
import cn.bootx.platform.daxpay.service.dto.order.pay.PayOrderExtraDto;
|
import cn.bootx.platform.daxpay.service.dto.order.pay.PayOrderExtraDto;
|
||||||
import cn.bootx.platform.daxpay.service.param.order.PayOrderQuery;
|
import cn.bootx.platform.daxpay.service.param.order.PayOrderQuery;
|
||||||
|
import cn.bootx.platform.daxpay.util.OrderNoGenerateUtil;
|
||||||
import io.swagger.v3.oas.annotations.Operation;
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
@@ -100,6 +101,7 @@ public class PayOrderController {
|
|||||||
public ResResult<Void> allocation(String orderNo){
|
public ResResult<Void> allocation(String orderNo){
|
||||||
AllocationStartParam param = new AllocationStartParam();
|
AllocationStartParam param = new AllocationStartParam();
|
||||||
param.setOrderNo(orderNo);
|
param.setOrderNo(orderNo);
|
||||||
|
param.setBizAllocationNo(OrderNoGenerateUtil.allocation());
|
||||||
allocationService.allocation(param);
|
allocationService.allocation(param);
|
||||||
return Res.ok();
|
return Res.ok();
|
||||||
}
|
}
|
||||||
|
@@ -5,6 +5,8 @@ import io.swagger.v3.oas.annotations.media.Schema;
|
|||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.EqualsAndHashCode;
|
import lombok.EqualsAndHashCode;
|
||||||
|
|
||||||
|
import javax.validation.constraints.NotBlank;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 开始分账请求参数
|
* 开始分账请求参数
|
||||||
* @author xxm
|
* @author xxm
|
||||||
@@ -16,6 +18,7 @@ import lombok.EqualsAndHashCode;
|
|||||||
public class AllocationStartParam extends PaymentCommonParam {
|
public class AllocationStartParam extends PaymentCommonParam {
|
||||||
|
|
||||||
@Schema(description = "商户分账单号")
|
@Schema(description = "商户分账单号")
|
||||||
|
@NotBlank(message = "商户分账单号不可为空")
|
||||||
private String bizAllocationNo;
|
private String bizAllocationNo;
|
||||||
|
|
||||||
@Schema(description = "支付订单号")
|
@Schema(description = "支付订单号")
|
||||||
|
@@ -4,6 +4,7 @@ import cn.bootx.platform.common.core.rest.param.PageParam;
|
|||||||
import cn.bootx.platform.common.mybatisplus.impl.BaseManager;
|
import cn.bootx.platform.common.mybatisplus.impl.BaseManager;
|
||||||
import cn.bootx.platform.common.mybatisplus.util.MpUtil;
|
import cn.bootx.platform.common.mybatisplus.util.MpUtil;
|
||||||
import cn.bootx.platform.common.query.generator.QueryGenerator;
|
import cn.bootx.platform.common.query.generator.QueryGenerator;
|
||||||
|
import cn.bootx.platform.daxpay.code.AllocOrderStatusEnum;
|
||||||
import cn.bootx.platform.daxpay.service.core.order.allocation.entity.AllocationOrder;
|
import cn.bootx.platform.daxpay.service.core.order.allocation.entity.AllocationOrder;
|
||||||
import cn.bootx.platform.daxpay.service.param.order.AllocationOrderQuery;
|
import cn.bootx.platform.daxpay.service.param.order.AllocationOrderQuery;
|
||||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||||
@@ -12,6 +13,8 @@ import lombok.RequiredArgsConstructor;
|
|||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.stereotype.Repository;
|
import org.springframework.stereotype.Repository;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -46,4 +49,14 @@ public class AllocationOrderManager extends BaseManager<AllocationOrderMapper, A
|
|||||||
QueryWrapper<AllocationOrder> generator = QueryGenerator.generator(param);
|
QueryWrapper<AllocationOrder> generator = QueryGenerator.generator(param);
|
||||||
return this.page(mpPage, generator);
|
return this.page(mpPage, generator);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询待同步的分账单
|
||||||
|
*/
|
||||||
|
public List<AllocationOrder> findSyncOrder(){
|
||||||
|
List<String> statusList = Arrays.asList(AllocOrderStatusEnum.ALLOCATION_PROCESSING.getCode(), AllocOrderStatusEnum.ALLOCATION_END.getCode());
|
||||||
|
return lambdaQuery()
|
||||||
|
.in(AllocationOrder::getStatus, statusList)
|
||||||
|
.list();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -4,6 +4,7 @@ import cn.bootx.platform.common.core.rest.param.PageParam;
|
|||||||
import cn.bootx.platform.common.mybatisplus.impl.BaseManager;
|
import cn.bootx.platform.common.mybatisplus.impl.BaseManager;
|
||||||
import cn.bootx.platform.common.mybatisplus.util.MpUtil;
|
import cn.bootx.platform.common.mybatisplus.util.MpUtil;
|
||||||
import cn.bootx.platform.common.query.generator.QueryGenerator;
|
import cn.bootx.platform.common.query.generator.QueryGenerator;
|
||||||
|
import cn.bootx.platform.daxpay.code.PayOrderAllocStatusEnum;
|
||||||
import cn.bootx.platform.daxpay.code.PayStatusEnum;
|
import cn.bootx.platform.daxpay.code.PayStatusEnum;
|
||||||
import cn.bootx.platform.daxpay.service.core.order.pay.entity.PayOrder;
|
import cn.bootx.platform.daxpay.service.core.order.pay.entity.PayOrder;
|
||||||
import cn.bootx.platform.daxpay.service.param.order.PayOrderQuery;
|
import cn.bootx.platform.daxpay.service.param.order.PayOrderQuery;
|
||||||
@@ -17,7 +18,6 @@ import java.time.LocalDateTime;
|
|||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 支付订单
|
* 支付订单
|
||||||
@@ -57,10 +57,11 @@ public class PayOrderManager extends BaseManager<PayOrderMapper, PayOrder> {
|
|||||||
/**
|
/**
|
||||||
* 查询对账用订单记录(指定时间和状态的订单)
|
* 查询对账用订单记录(指定时间和状态的订单)
|
||||||
*/
|
*/
|
||||||
public List<PayOrder> findReconcile(String channel, LocalDateTime startTime, LocalDateTime endTime, PayStatusEnum...statusEnum) {
|
public List<PayOrder> findReconcile(String channel, LocalDateTime startTime, LocalDateTime endTime) {
|
||||||
List<String> status = Arrays.stream(statusEnum)
|
List<String> status = Arrays.asList(PayStatusEnum.SUCCESS.getCode(),
|
||||||
.map(PayStatusEnum::getCode)
|
PayStatusEnum.PARTIAL_REFUND.getCode(),
|
||||||
.collect(Collectors.toList());
|
PayStatusEnum.REFUNDING.getCode(),
|
||||||
|
PayStatusEnum.REFUNDED.getCode());
|
||||||
return this.lambdaQuery()
|
return this.lambdaQuery()
|
||||||
.eq(PayOrder::getChannel, channel)
|
.eq(PayOrder::getChannel, channel)
|
||||||
.between(PayOrder::getPayTime, startTime, endTime)
|
.between(PayOrder::getPayTime, startTime, endTime)
|
||||||
@@ -68,6 +69,21 @@ public class PayOrderManager extends BaseManager<PayOrderMapper, PayOrder> {
|
|||||||
.list();
|
.list();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询自动分账用订单记录(指定时间和状态的订单)
|
||||||
|
*/
|
||||||
|
public List<PayOrder> findAllocation() {
|
||||||
|
List<String> status = Arrays.asList(PayStatusEnum.SUCCESS.getCode(),
|
||||||
|
PayStatusEnum.PARTIAL_REFUND.getCode(),
|
||||||
|
PayStatusEnum.REFUNDING.getCode(),
|
||||||
|
PayStatusEnum.REFUNDED.getCode());
|
||||||
|
return this.lambdaQuery()
|
||||||
|
.eq(PayOrder::getAllocation, true)
|
||||||
|
.eq(PayOrder::getAllocationStatus, PayOrderAllocStatusEnum.WAITING.getCode())
|
||||||
|
.in(PayOrder::getStatus, status)
|
||||||
|
.list();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 查询汇总金额
|
* 查询汇总金额
|
||||||
*/
|
*/
|
||||||
|
@@ -16,10 +16,8 @@ import lombok.extern.slf4j.Slf4j;
|
|||||||
import org.springframework.stereotype.Repository;
|
import org.springframework.stereotype.Repository;
|
||||||
|
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 支付退款订单管理
|
* 支付退款订单管理
|
||||||
@@ -77,14 +75,11 @@ public class RefundOrderManager extends BaseManager<RefundOrderMapper, RefundOrd
|
|||||||
/**
|
/**
|
||||||
* 查询对账用订单记录(指定时间和状态的订单)
|
* 查询对账用订单记录(指定时间和状态的订单)
|
||||||
*/
|
*/
|
||||||
public List<RefundOrder> findReconcile(String channel, LocalDateTime startTime, LocalDateTime endTime, RefundStatusEnum...statusEnum) {
|
public List<RefundOrder> findReconcile(String channel, LocalDateTime startTime, LocalDateTime endTime) {
|
||||||
List<String> status = Arrays.stream(statusEnum)
|
|
||||||
.map(RefundStatusEnum::getCode)
|
|
||||||
.collect(Collectors.toList());
|
|
||||||
return this.lambdaQuery()
|
return this.lambdaQuery()
|
||||||
.eq(RefundOrder::getChannel, channel)
|
.eq(RefundOrder::getChannel, channel)
|
||||||
.between(RefundOrder::getFinishTime, startTime, endTime)
|
.between(RefundOrder::getFinishTime, startTime, endTime)
|
||||||
.in(RefundOrder::getStatus, status)
|
.eq(RefundOrder::getStatus, RefundStatusEnum.SUCCESS)
|
||||||
.list();
|
.list();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1,16 +0,0 @@
|
|||||||
package cn.bootx.platform.daxpay.service.core.payment.allocation.service;
|
|
||||||
|
|
||||||
import lombok.RequiredArgsConstructor;
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
import org.springframework.stereotype.Service;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 分账订单同步服务
|
|
||||||
* @author xxm
|
|
||||||
* @since 2024/4/7
|
|
||||||
*/
|
|
||||||
@Slf4j
|
|
||||||
@Service
|
|
||||||
@RequiredArgsConstructor
|
|
||||||
public class AllocationOrderSyncService {
|
|
||||||
}
|
|
@@ -1,15 +1,16 @@
|
|||||||
package cn.bootx.platform.daxpay.service.core.payment.allocation.service;
|
package cn.bootx.platform.daxpay.service.core.payment.allocation.service;
|
||||||
|
|
||||||
import cn.bootx.platform.common.core.exception.DataNotExistException;
|
import cn.bootx.platform.common.core.exception.DataNotExistException;
|
||||||
|
import cn.bootx.platform.common.core.exception.RepetitiveOperationException;
|
||||||
import cn.bootx.platform.daxpay.code.AllocDetailResultEnum;
|
import cn.bootx.platform.daxpay.code.AllocDetailResultEnum;
|
||||||
import cn.bootx.platform.daxpay.code.AllocOrderResultEnum;
|
import cn.bootx.platform.daxpay.code.AllocOrderResultEnum;
|
||||||
import cn.bootx.platform.daxpay.code.AllocOrderStatusEnum;
|
import cn.bootx.platform.daxpay.code.AllocOrderStatusEnum;
|
||||||
import cn.bootx.platform.daxpay.code.PayOrderAllocStatusEnum;
|
import cn.bootx.platform.daxpay.code.PayOrderAllocStatusEnum;
|
||||||
import cn.bootx.platform.daxpay.exception.pay.PayFailureException;
|
import cn.bootx.platform.daxpay.exception.pay.PayFailureException;
|
||||||
import cn.bootx.platform.daxpay.param.payment.allocation.AllocationSyncParam;
|
|
||||||
import cn.bootx.platform.daxpay.param.payment.allocation.AllocationFinishParam;
|
import cn.bootx.platform.daxpay.param.payment.allocation.AllocationFinishParam;
|
||||||
import cn.bootx.platform.daxpay.param.payment.allocation.AllocationResetParam;
|
import cn.bootx.platform.daxpay.param.payment.allocation.AllocationResetParam;
|
||||||
import cn.bootx.platform.daxpay.param.payment.allocation.AllocationStartParam;
|
import cn.bootx.platform.daxpay.param.payment.allocation.AllocationStartParam;
|
||||||
|
import cn.bootx.platform.daxpay.param.payment.allocation.AllocationSyncParam;
|
||||||
import cn.bootx.platform.daxpay.result.allocation.AllocationResult;
|
import cn.bootx.platform.daxpay.result.allocation.AllocationResult;
|
||||||
import cn.bootx.platform.daxpay.service.common.local.PaymentContextLocal;
|
import cn.bootx.platform.daxpay.service.common.local.PaymentContextLocal;
|
||||||
import cn.bootx.platform.daxpay.service.core.order.allocation.dao.AllocationOrderDetailManager;
|
import cn.bootx.platform.daxpay.service.core.order.allocation.dao.AllocationOrderDetailManager;
|
||||||
@@ -18,7 +19,6 @@ import cn.bootx.platform.daxpay.service.core.order.allocation.entity.AllocationO
|
|||||||
import cn.bootx.platform.daxpay.service.core.order.allocation.entity.AllocationOrderDetail;
|
import cn.bootx.platform.daxpay.service.core.order.allocation.entity.AllocationOrderDetail;
|
||||||
import cn.bootx.platform.daxpay.service.core.order.allocation.entity.OrderAndDetail;
|
import cn.bootx.platform.daxpay.service.core.order.allocation.entity.OrderAndDetail;
|
||||||
import cn.bootx.platform.daxpay.service.core.order.allocation.service.AllocationOrderService;
|
import cn.bootx.platform.daxpay.service.core.order.allocation.service.AllocationOrderService;
|
||||||
import cn.bootx.platform.daxpay.service.core.order.pay.dao.PayOrderManager;
|
|
||||||
import cn.bootx.platform.daxpay.service.core.order.pay.entity.PayOrder;
|
import cn.bootx.platform.daxpay.service.core.order.pay.entity.PayOrder;
|
||||||
import cn.bootx.platform.daxpay.service.core.order.pay.service.PayOrderQueryService;
|
import cn.bootx.platform.daxpay.service.core.order.pay.service.PayOrderQueryService;
|
||||||
import cn.bootx.platform.daxpay.service.core.payment.allocation.dao.AllocationGroupManager;
|
import cn.bootx.platform.daxpay.service.core.payment.allocation.dao.AllocationGroupManager;
|
||||||
@@ -26,6 +26,8 @@ import cn.bootx.platform.daxpay.service.core.payment.allocation.entity.Allocatio
|
|||||||
import cn.bootx.platform.daxpay.service.core.payment.allocation.factory.AllocationFactory;
|
import cn.bootx.platform.daxpay.service.core.payment.allocation.factory.AllocationFactory;
|
||||||
import cn.bootx.platform.daxpay.service.dto.allocation.AllocationGroupReceiverResult;
|
import cn.bootx.platform.daxpay.service.dto.allocation.AllocationGroupReceiverResult;
|
||||||
import cn.bootx.platform.daxpay.service.func.AbsAllocationStrategy;
|
import cn.bootx.platform.daxpay.service.func.AbsAllocationStrategy;
|
||||||
|
import com.baomidou.lock.LockInfo;
|
||||||
|
import com.baomidou.lock.LockTemplate;
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
@@ -46,8 +48,6 @@ import java.util.Objects;
|
|||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
public class AllocationService {
|
public class AllocationService {
|
||||||
|
|
||||||
private final PayOrderManager payOrderManager;
|
|
||||||
|
|
||||||
private final AllocationGroupManager groupManager;
|
private final AllocationGroupManager groupManager;
|
||||||
|
|
||||||
private final AllocationOrderManager allocationOrderManager;
|
private final AllocationOrderManager allocationOrderManager;
|
||||||
@@ -58,55 +58,70 @@ public class AllocationService {
|
|||||||
|
|
||||||
private final AllocationOrderDetailManager allocationOrderDetailManager;
|
private final AllocationOrderDetailManager allocationOrderDetailManager;
|
||||||
private final PayOrderQueryService payOrderQueryService;
|
private final PayOrderQueryService payOrderQueryService;
|
||||||
|
private final LockTemplate lockTemplate;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 开启分账, 使用分账组进行分账
|
* 开启分账, 使用分账组进行分账
|
||||||
*/
|
*/
|
||||||
public AllocationResult allocation(AllocationStartParam param) {
|
public AllocationResult allocation(AllocationStartParam param) {
|
||||||
PayOrder payOrder = this.getAndCheckPayOrder(param);
|
PayOrder payOrder = this.getAndCheckPayOrder(param);
|
||||||
// 查询分账组 未传输使用默认该通道默认分账组
|
return this.allocation(payOrder, param);
|
||||||
AllocationGroup allocationGroup;
|
}
|
||||||
if (Objects.nonNull(param.getAllocationGroupId())) {
|
|
||||||
allocationGroup = groupManager.findById(param.getAllocationGroupId()).orElseThrow(() -> new DataNotExistException("未查询到分账组"));
|
/**
|
||||||
} else {
|
* 开启分账, 未传输默认分账组, 则使用默认该通道默认分账组
|
||||||
allocationGroup = groupManager.findDefaultGroup(payOrder.getChannel()).orElseThrow(() -> new DataNotExistException("未查询到默认分账组"));
|
*/
|
||||||
|
public AllocationResult allocation(PayOrder payOrder, AllocationStartParam param) {
|
||||||
|
LockInfo lock = lockTemplate.lock("payment:allocation:" + payOrder.getId(),10000,200);
|
||||||
|
if (Objects.isNull(lock)){
|
||||||
|
throw new RepetitiveOperationException("分账发起处理中,请勿重复操作");
|
||||||
}
|
}
|
||||||
|
|
||||||
List<AllocationGroupReceiverResult> receiversByGroups = allocationGroupService.findReceiversByGroups(allocationGroup.getId());
|
|
||||||
|
|
||||||
// 创建分账单和明细并保存, 同时更新支付订单状态 使用事务
|
|
||||||
OrderAndDetail orderAndDetail = allocationOrderService.createAndUpdate(param ,payOrder, payOrder.getAmount(), receiversByGroups);
|
|
||||||
|
|
||||||
// 创建分账策略并初始化
|
|
||||||
AbsAllocationStrategy allocationStrategy = AllocationFactory.create(payOrder.getChannel());
|
|
||||||
AllocationOrder order = orderAndDetail.getOrder();
|
|
||||||
List<AllocationOrderDetail> details = orderAndDetail.getDetails();
|
|
||||||
allocationStrategy.initParam(order, details);
|
|
||||||
|
|
||||||
// 分账预处理
|
|
||||||
allocationStrategy.doBeforeHandler();
|
|
||||||
try {
|
try {
|
||||||
// 分账处理
|
// 查询默认分账组
|
||||||
allocationStrategy.allocation();
|
AllocationGroup allocationGroup;
|
||||||
// 执行中
|
if (Objects.nonNull(param.getAllocationGroupId())) {
|
||||||
order.setStatus(AllocOrderStatusEnum.ALLOCATION_PROCESSING.getCode())
|
allocationGroup = groupManager.findById(param.getAllocationGroupId()).orElseThrow(() -> new DataNotExistException("未查询到分账组"));
|
||||||
.setErrorMsg(null);
|
} else {
|
||||||
} catch (Exception e) {
|
allocationGroup = groupManager.findDefaultGroup(payOrder.getChannel()).orElseThrow(() -> new DataNotExistException("未查询到默认分账组"));
|
||||||
log.error("分账出现错误:", e);
|
}
|
||||||
// 失败
|
List<AllocationGroupReceiverResult> receiversByGroups = allocationGroupService.findReceiversByGroups(allocationGroup.getId());
|
||||||
order.setStatus(AllocOrderStatusEnum.ALLOCATION_FAILED.getCode())
|
// 创建分账单和明细并保存, 同时更新支付订单状态 使用事务
|
||||||
.setErrorMsg(e.getMessage());
|
OrderAndDetail orderAndDetail = allocationOrderService.createAndUpdate(param ,payOrder, payOrder.getAmount(), receiversByGroups);
|
||||||
}
|
|
||||||
// 网关分账号
|
|
||||||
String gatewayNo = PaymentContextLocal.get()
|
|
||||||
.getAllocationInfo()
|
|
||||||
.getOutAllocationNo();
|
|
||||||
order.setOutAllocationNo(gatewayNo);
|
|
||||||
allocationOrderManager.updateById(order);
|
|
||||||
|
|
||||||
return new AllocationResult().setOrderId(order.getId())
|
// 创建分账策略并初始化
|
||||||
.setAllocationNo(order.getAllocationNo())
|
AbsAllocationStrategy allocationStrategy = AllocationFactory.create(payOrder.getChannel());
|
||||||
.setStatus(order.getStatus());
|
AllocationOrder order = orderAndDetail.getOrder();
|
||||||
|
List<AllocationOrderDetail> details = orderAndDetail.getDetails();
|
||||||
|
allocationStrategy.initParam(order, details);
|
||||||
|
|
||||||
|
// 分账预处理
|
||||||
|
allocationStrategy.doBeforeHandler();
|
||||||
|
try {
|
||||||
|
// 分账处理
|
||||||
|
allocationStrategy.allocation();
|
||||||
|
// 执行中
|
||||||
|
order.setStatus(AllocOrderStatusEnum.ALLOCATION_PROCESSING.getCode())
|
||||||
|
.setErrorMsg(null);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("分账出现错误:", e);
|
||||||
|
// 失败
|
||||||
|
order.setStatus(AllocOrderStatusEnum.ALLOCATION_FAILED.getCode())
|
||||||
|
.setErrorMsg(e.getMessage());
|
||||||
|
}
|
||||||
|
// 网关分账号
|
||||||
|
String gatewayNo = PaymentContextLocal.get()
|
||||||
|
.getAllocationInfo()
|
||||||
|
.getOutAllocationNo();
|
||||||
|
order.setOutAllocationNo(gatewayNo);
|
||||||
|
allocationOrderManager.updateById(order);
|
||||||
|
|
||||||
|
return new AllocationResult().setOrderId(order.getId())
|
||||||
|
.setAllocationNo(order.getAllocationNo())
|
||||||
|
.setStatus(order.getStatus());
|
||||||
|
} finally {
|
||||||
|
lockTemplate.releaseLock(lock);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -121,35 +136,44 @@ public class AllocationService {
|
|||||||
allocationOrder = allocationOrderManager.findByAllocationNo(param.getAllocationNo())
|
allocationOrder = allocationOrderManager.findByAllocationNo(param.getAllocationNo())
|
||||||
.orElseThrow(() -> new DataNotExistException("未查询到分账单信息"));
|
.orElseThrow(() -> new DataNotExistException("未查询到分账单信息"));
|
||||||
}
|
}
|
||||||
// 需要是分账中分账中或者完成状态才能重新分账
|
LockInfo lock = lockTemplate.lock("payment:allocation:" + allocationOrder.getOrderId(),10000,200);
|
||||||
List<String> list = Arrays.asList(AllocOrderStatusEnum.ALLOCATION_END.getCode(),
|
if (Objects.isNull(lock)){
|
||||||
AllocOrderStatusEnum.ALLOCATION_FAILED.getCode(),
|
throw new RepetitiveOperationException("分账发起处理中,请勿重复操作");
|
||||||
AllocOrderStatusEnum.ALLOCATION_PROCESSING.getCode());
|
|
||||||
if (!list.contains(allocationOrder.getStatus())){
|
|
||||||
throw new PayFailureException("分账单状态错误");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
List<AllocationOrderDetail> details = allocationOrderDetailManager.findAllByOrderId(allocationOrder.getId());
|
|
||||||
|
|
||||||
// 创建分账策略并初始化
|
|
||||||
AbsAllocationStrategy allocationStrategy = AllocationFactory.create(allocationOrder.getChannel());
|
|
||||||
allocationStrategy.initParam(allocationOrder, details);
|
|
||||||
|
|
||||||
// 分账预处理
|
|
||||||
allocationStrategy.doBeforeHandler();
|
|
||||||
try {
|
try {
|
||||||
// 重复分账处理
|
// 需要是分账中分账中或者完成状态才能重新分账
|
||||||
allocationStrategy.allocation();
|
List<String> list = Arrays.asList(AllocOrderStatusEnum.ALLOCATION_END.getCode(),
|
||||||
allocationOrder.setStatus(AllocOrderStatusEnum.ALLOCATION_PROCESSING.getCode())
|
AllocOrderStatusEnum.ALLOCATION_FAILED.getCode(),
|
||||||
.setErrorMsg(null);
|
AllocOrderStatusEnum.ALLOCATION_PROCESSING.getCode());
|
||||||
|
if (!list.contains(allocationOrder.getStatus())){
|
||||||
|
throw new PayFailureException("分账单状态错误");
|
||||||
|
}
|
||||||
|
|
||||||
|
List<AllocationOrderDetail> details = allocationOrderDetailManager.findAllByOrderId(allocationOrder.getId());
|
||||||
|
|
||||||
|
// 创建分账策略并初始化
|
||||||
|
AbsAllocationStrategy allocationStrategy = AllocationFactory.create(allocationOrder.getChannel());
|
||||||
|
allocationStrategy.initParam(allocationOrder, details);
|
||||||
|
|
||||||
|
// 分账预处理
|
||||||
|
allocationStrategy.doBeforeHandler();
|
||||||
|
try {
|
||||||
|
// 重复分账处理
|
||||||
|
allocationStrategy.allocation();
|
||||||
|
allocationOrder.setStatus(AllocOrderStatusEnum.ALLOCATION_PROCESSING.getCode())
|
||||||
|
.setErrorMsg(null);
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("重新分账出现错误:", e);
|
||||||
|
// 失败
|
||||||
|
allocationOrder.setStatus(AllocOrderStatusEnum.ALLOCATION_FAILED.getCode())
|
||||||
|
.setErrorMsg(e.getMessage());
|
||||||
|
}
|
||||||
|
allocationOrderManager.updateById(allocationOrder);
|
||||||
|
} finally {
|
||||||
|
|
||||||
} catch (Exception e) {
|
|
||||||
log.error("重新分账出现错误:", e);
|
|
||||||
// 失败
|
|
||||||
allocationOrder.setStatus(AllocOrderStatusEnum.ALLOCATION_FAILED.getCode())
|
|
||||||
.setErrorMsg(e.getMessage());
|
|
||||||
}
|
}
|
||||||
allocationOrderManager.updateById(allocationOrder);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -164,6 +188,13 @@ public class AllocationService {
|
|||||||
allocationOrder = allocationOrderManager.findByAllocationNo(param.getAllocationNo())
|
allocationOrder = allocationOrderManager.findByAllocationNo(param.getAllocationNo())
|
||||||
.orElseThrow(() -> new DataNotExistException("未查询到分账单信息"));
|
.orElseThrow(() -> new DataNotExistException("未查询到分账单信息"));
|
||||||
}
|
}
|
||||||
|
this.finish(allocationOrder);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 分账完结
|
||||||
|
*/
|
||||||
|
public void finish(AllocationOrder allocationOrder) {
|
||||||
// 只有分账结束后才可以完结
|
// 只有分账结束后才可以完结
|
||||||
if (!AllocOrderStatusEnum.ALLOCATION_END.getCode().equals(allocationOrder.getStatus())){
|
if (!AllocOrderStatusEnum.ALLOCATION_END.getCode().equals(allocationOrder.getStatus())){
|
||||||
throw new PayFailureException("分账单状态错误");
|
throw new PayFailureException("分账单状态错误");
|
||||||
@@ -206,19 +237,34 @@ public class AllocationService {
|
|||||||
allocationOrder = allocationOrderManager.findByAllocationNo(param.getAllocationNo())
|
allocationOrder = allocationOrderManager.findByAllocationNo(param.getAllocationNo())
|
||||||
.orElseThrow(() -> new DataNotExistException("分账单不存在"));
|
.orElseThrow(() -> new DataNotExistException("分账单不存在"));
|
||||||
}
|
}
|
||||||
List<AllocationOrderDetail> detailList = allocationOrderDetailManager.findAllByOrderId(allocationOrder.getId());
|
this.sync(allocationOrder);
|
||||||
// 获取分账策略
|
}
|
||||||
AbsAllocationStrategy allocationStrategy = AllocationFactory.create(allocationOrder.getChannel());
|
|
||||||
allocationStrategy.initParam(allocationOrder, detailList);
|
|
||||||
// 分账完结预处理
|
|
||||||
allocationStrategy.doBeforeHandler();
|
|
||||||
allocationStrategy.doSync();
|
|
||||||
|
|
||||||
// 根据订单明细更新订单的状态和处理结果
|
/**
|
||||||
this.updateOrderStatus(allocationOrder, detailList);
|
* 分账同步
|
||||||
|
*/
|
||||||
|
public void sync(AllocationOrder allocationOrder){
|
||||||
|
LockInfo lock = lockTemplate.lock("payment:allocation:" + allocationOrder.getOrderId(),10000,200);
|
||||||
|
if (Objects.isNull(lock)){
|
||||||
|
throw new RepetitiveOperationException("分账同步中,请勿重复操作");
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
List<AllocationOrderDetail> detailList = allocationOrderDetailManager.findAllByOrderId(allocationOrder.getId());
|
||||||
|
// 获取分账策略
|
||||||
|
AbsAllocationStrategy allocationStrategy = AllocationFactory.create(allocationOrder.getChannel());
|
||||||
|
allocationStrategy.initParam(allocationOrder, detailList);
|
||||||
|
// 分账完结预处理
|
||||||
|
allocationStrategy.doBeforeHandler();
|
||||||
|
allocationStrategy.doSync();
|
||||||
|
|
||||||
allocationOrderDetailManager.updateAllById(detailList);
|
// 根据订单明细更新订单的状态和处理结果
|
||||||
allocationOrderManager.updateById(allocationOrder);
|
this.updateOrderStatus(allocationOrder, detailList);
|
||||||
|
|
||||||
|
allocationOrderDetailManager.updateAllById(detailList);
|
||||||
|
allocationOrderManager.updateById(allocationOrder);
|
||||||
|
} finally {
|
||||||
|
lockTemplate.releaseLock(lock);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -3,16 +3,14 @@ package cn.bootx.platform.daxpay.service.core.payment.reconcile.service;
|
|||||||
import cn.bootx.platform.common.core.function.CollectorsFunction;
|
import cn.bootx.platform.common.core.function.CollectorsFunction;
|
||||||
import cn.bootx.platform.common.core.util.CollUtil;
|
import cn.bootx.platform.common.core.util.CollUtil;
|
||||||
import cn.bootx.platform.common.core.util.LocalDateTimeUtil;
|
import cn.bootx.platform.common.core.util.LocalDateTimeUtil;
|
||||||
import cn.bootx.platform.daxpay.code.PayStatusEnum;
|
|
||||||
import cn.bootx.platform.daxpay.code.ReconcileTradeEnum;
|
import cn.bootx.platform.daxpay.code.ReconcileTradeEnum;
|
||||||
import cn.bootx.platform.daxpay.code.RefundStatusEnum;
|
|
||||||
import cn.bootx.platform.daxpay.service.code.PaymentTypeEnum;
|
import cn.bootx.platform.daxpay.service.code.PaymentTypeEnum;
|
||||||
import cn.bootx.platform.daxpay.service.code.ReconcileDiffTypeEnum;
|
import cn.bootx.platform.daxpay.service.code.ReconcileDiffTypeEnum;
|
||||||
import cn.bootx.platform.daxpay.service.core.order.pay.dao.PayOrderManager;
|
import cn.bootx.platform.daxpay.service.core.order.pay.dao.PayOrderManager;
|
||||||
import cn.bootx.platform.daxpay.service.core.order.pay.entity.PayOrder;
|
import cn.bootx.platform.daxpay.service.core.order.pay.entity.PayOrder;
|
||||||
import cn.bootx.platform.daxpay.service.core.order.reconcile.entity.ReconcileTradeDetail;
|
|
||||||
import cn.bootx.platform.daxpay.service.core.order.reconcile.entity.ReconcileDiff;
|
import cn.bootx.platform.daxpay.service.core.order.reconcile.entity.ReconcileDiff;
|
||||||
import cn.bootx.platform.daxpay.service.core.order.reconcile.entity.ReconcileOrder;
|
import cn.bootx.platform.daxpay.service.core.order.reconcile.entity.ReconcileOrder;
|
||||||
|
import cn.bootx.platform.daxpay.service.core.order.reconcile.entity.ReconcileTradeDetail;
|
||||||
import cn.bootx.platform.daxpay.service.core.order.refund.dao.RefundOrderManager;
|
import cn.bootx.platform.daxpay.service.core.order.refund.dao.RefundOrderManager;
|
||||||
import cn.bootx.platform.daxpay.service.core.order.refund.entity.RefundOrder;
|
import cn.bootx.platform.daxpay.service.core.order.refund.entity.RefundOrder;
|
||||||
import cn.bootx.platform.daxpay.service.core.payment.reconcile.domain.GeneralTradeInfo;
|
import cn.bootx.platform.daxpay.service.core.payment.reconcile.domain.GeneralTradeInfo;
|
||||||
@@ -55,8 +53,8 @@ public class ReconcileAssistService {
|
|||||||
LocalDateTime end = LocalDateTimeUtil.endOfDay(localDateTime);
|
LocalDateTime end = LocalDateTimeUtil.endOfDay(localDateTime);
|
||||||
|
|
||||||
// 下载支付订单
|
// 下载支付订单
|
||||||
List<PayOrder> payOrders = payOrderManager.findReconcile(reconcileOrder.getChannel(), start, end, PayStatusEnum.SUCCESS, PayStatusEnum.PARTIAL_REFUND, PayStatusEnum.REFUNDING, PayStatusEnum.REFUNDED);
|
List<PayOrder> payOrders = payOrderManager.findReconcile(reconcileOrder.getChannel(), start, end);
|
||||||
List<RefundOrder> refundOrders = refundOrderManager.findReconcile(reconcileOrder.getChannel(), start, end, RefundStatusEnum.SUCCESS);
|
List<RefundOrder> refundOrders = refundOrderManager.findReconcile(reconcileOrder.getChannel(), start, end);
|
||||||
for (PayOrder payOrder : payOrders) {
|
for (PayOrder payOrder : payOrders) {
|
||||||
generalTradeInfoList.add(new GeneralTradeInfo()
|
generalTradeInfoList.add(new GeneralTradeInfo()
|
||||||
.setTitle(payOrder.getTitle())
|
.setTitle(payOrder.getTitle())
|
||||||
|
@@ -0,0 +1,42 @@
|
|||||||
|
package cn.bootx.platform.daxpay.service.task;
|
||||||
|
|
||||||
|
import cn.bootx.platform.daxpay.param.payment.allocation.AllocationStartParam;
|
||||||
|
import cn.bootx.platform.daxpay.service.core.order.pay.dao.PayOrderManager;
|
||||||
|
import cn.bootx.platform.daxpay.service.core.order.pay.entity.PayOrder;
|
||||||
|
import cn.bootx.platform.daxpay.service.core.payment.allocation.service.AllocationService;
|
||||||
|
import cn.bootx.platform.daxpay.util.OrderNoGenerateUtil;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.quartz.*;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 自动分账定时任务, 10s一次
|
||||||
|
* @author xxm
|
||||||
|
* @since 2024/5/6
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@Component
|
||||||
|
@DisallowConcurrentExecution
|
||||||
|
@PersistJobDataAfterExecution
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class AllocationAutoStartTask implements Job {
|
||||||
|
private final PayOrderManager payOrderManager;
|
||||||
|
private final AllocationService allocationService;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
|
||||||
|
for (PayOrder payOrder : payOrderManager.findAllocation()) {
|
||||||
|
AllocationStartParam param = new AllocationStartParam();
|
||||||
|
param.setBizAllocationNo(OrderNoGenerateUtil.allocation());
|
||||||
|
try {
|
||||||
|
allocationService.allocation(payOrder, param);
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.warn("自动分账失败, 支付订单号: {}", payOrder.getOrderNo());
|
||||||
|
log.warn("自动分账失败:{}", e.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,50 @@
|
|||||||
|
package cn.bootx.platform.daxpay.service.task;
|
||||||
|
|
||||||
|
import cn.bootx.platform.daxpay.code.AllocOrderStatusEnum;
|
||||||
|
import cn.bootx.platform.daxpay.service.core.order.allocation.dao.AllocationOrderManager;
|
||||||
|
import cn.bootx.platform.daxpay.service.core.order.allocation.entity.AllocationOrder;
|
||||||
|
import cn.bootx.platform.daxpay.service.core.payment.allocation.service.AllocationService;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.quartz.*;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 自动分账信息同步和完结接口 10s一次
|
||||||
|
* @author xxm
|
||||||
|
* @since 2024/5/6
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@Component
|
||||||
|
@DisallowConcurrentExecution
|
||||||
|
@PersistJobDataAfterExecution
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class AllocationSyncTask implements Job {
|
||||||
|
|
||||||
|
private final AllocationOrderManager allocationOrderManager;
|
||||||
|
|
||||||
|
private final AllocationService allocationService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 分账同步
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
|
||||||
|
for (AllocationOrder allocationOrder : allocationOrderManager.findSyncOrder()) {
|
||||||
|
try {
|
||||||
|
// 分账中走同步逻辑
|
||||||
|
if (allocationOrder.getStatus().equals(AllocOrderStatusEnum.ALLOCATION_PROCESSING.getCode())) {
|
||||||
|
allocationService.sync(allocationOrder);
|
||||||
|
}
|
||||||
|
// 如果分账结束, 调用自动完结逻辑
|
||||||
|
if (allocationOrder.getStatus().equals(AllocOrderStatusEnum.ALLOCATION_END.getCode())) {
|
||||||
|
allocationService.finish(allocationOrder);
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.warn("分账同步或完结失败, 分账号:{}", allocationOrder.getAllocationNo());
|
||||||
|
log.warn("分账同步或完结失败", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
Reference in New Issue
Block a user