From d133957e6362cd11e3ed5e255855a1366055a5ef Mon Sep 17 00:00:00 2001 From: DaxPay Date: Mon, 6 May 2024 21:13:39 +0800 Subject: [PATCH] =?UTF-8?q?feat=20=E8=87=AA=E5=8A=A8=E5=88=86=E8=B4=A6/?= =?UTF-8?q?=E7=8A=B6=E6=80=81=E5=90=8C=E6=AD=A5/=E8=87=AA=E5=8A=A8?= =?UTF-8?q?=E5=AE=8C=E7=BB=93?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- _doc/Task.md | 7 +- .../controller/order/PayOrderController.java | 2 + .../allocation/AllocationStartParam.java | 3 + .../dao/AllocationOrderManager.java | 13 ++ .../core/order/pay/dao/PayOrderManager.java | 26 ++- .../order/refund/dao/RefundOrderManager.java | 9 +- .../service/AllocationOrderSyncService.java | 16 -- .../allocation/service/AllocationService.java | 204 +++++++++++------- .../service/ReconcileAssistService.java | 8 +- .../service/task/AllocationAutoStartTask.java | 42 ++++ .../service/task/AllocationSyncTask.java | 50 +++++ 11 files changed, 265 insertions(+), 115 deletions(-) delete mode 100644 daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/allocation/service/AllocationOrderSyncService.java create mode 100644 daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/task/AllocationAutoStartTask.java create mode 100644 daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/task/AllocationSyncTask.java diff --git a/_doc/Task.md b/_doc/Task.md index 71a9e0d16..8759377aa 100644 --- a/_doc/Task.md +++ b/_doc/Task.md @@ -32,12 +32,13 @@ - [x] 支付订单和退款订单页面添加实时金额汇总展示 - [ ] 自动分账改造 - [ ] SDK新增对账接收放添加接口 - - [ ] 创建定时任务, 自动对待分账订单进行分账 - - [ ] 增加定时同步分账状态任务 - - [ ] 增加自动完结功能 + - [x] 创建定时任务, 自动对待分账订单进行分账 + - [x] 增加定时同步分账状态任务 + - [x] 增加自动完结功能 2.0.7: 分账完善和基础架构优化 - [ ] 资金流水优化 - [ ] 数据加密方式改为类型处理器模式 +- [ ] - [ ] 支持分账组分账和自己传接收方进行分账 - [ ] DEMO增加获取微信OpenID和支付宝OpenId功能 - [ ] 分账接收方管理提供接口调用 diff --git a/daxpay-single/daxpay-single-admin/src/main/java/cn/bootx/platform/daxpay/admin/controller/order/PayOrderController.java b/daxpay-single/daxpay-single-admin/src/main/java/cn/bootx/platform/daxpay/admin/controller/order/PayOrderController.java index 23674fcfc..22c6f9f43 100644 --- a/daxpay-single/daxpay-single-admin/src/main/java/cn/bootx/platform/daxpay/admin/controller/order/PayOrderController.java +++ b/daxpay-single/daxpay-single-admin/src/main/java/cn/bootx/platform/daxpay/admin/controller/order/PayOrderController.java @@ -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.PayOrderExtraDto; 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.tags.Tag; import lombok.RequiredArgsConstructor; @@ -100,6 +101,7 @@ public class PayOrderController { public ResResult allocation(String orderNo){ AllocationStartParam param = new AllocationStartParam(); param.setOrderNo(orderNo); + param.setBizAllocationNo(OrderNoGenerateUtil.allocation()); allocationService.allocation(param); return Res.ok(); } diff --git a/daxpay-single/daxpay-single-core/src/main/java/cn/bootx/platform/daxpay/param/payment/allocation/AllocationStartParam.java b/daxpay-single/daxpay-single-core/src/main/java/cn/bootx/platform/daxpay/param/payment/allocation/AllocationStartParam.java index f037de0bb..c8add18b3 100644 --- a/daxpay-single/daxpay-single-core/src/main/java/cn/bootx/platform/daxpay/param/payment/allocation/AllocationStartParam.java +++ b/daxpay-single/daxpay-single-core/src/main/java/cn/bootx/platform/daxpay/param/payment/allocation/AllocationStartParam.java @@ -5,6 +5,8 @@ import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import lombok.EqualsAndHashCode; +import javax.validation.constraints.NotBlank; + /** * 开始分账请求参数 * @author xxm @@ -16,6 +18,7 @@ import lombok.EqualsAndHashCode; public class AllocationStartParam extends PaymentCommonParam { @Schema(description = "商户分账单号") + @NotBlank(message = "商户分账单号不可为空") private String bizAllocationNo; @Schema(description = "支付订单号") diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/order/allocation/dao/AllocationOrderManager.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/order/allocation/dao/AllocationOrderManager.java index 7ddeb6901..b0ad345b6 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/order/allocation/dao/AllocationOrderManager.java +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/order/allocation/dao/AllocationOrderManager.java @@ -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.util.MpUtil; 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.param.order.AllocationOrderQuery; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; @@ -12,6 +13,8 @@ import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Repository; +import java.util.Arrays; +import java.util.List; import java.util.Optional; /** @@ -46,4 +49,14 @@ public class AllocationOrderManager extends BaseManager generator = QueryGenerator.generator(param); return this.page(mpPage, generator); } + + /** + * 查询待同步的分账单 + */ + public List findSyncOrder(){ + List statusList = Arrays.asList(AllocOrderStatusEnum.ALLOCATION_PROCESSING.getCode(), AllocOrderStatusEnum.ALLOCATION_END.getCode()); + return lambdaQuery() + .in(AllocationOrder::getStatus, statusList) + .list(); + } } diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/order/pay/dao/PayOrderManager.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/order/pay/dao/PayOrderManager.java index f75bdb3f3..97bcddfa6 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/order/pay/dao/PayOrderManager.java +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/order/pay/dao/PayOrderManager.java @@ -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.util.MpUtil; 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.service.core.order.pay.entity.PayOrder; import cn.bootx.platform.daxpay.service.param.order.PayOrderQuery; @@ -17,7 +18,6 @@ import java.time.LocalDateTime; import java.util.Arrays; import java.util.List; import java.util.Optional; -import java.util.stream.Collectors; /** * 支付订单 @@ -57,10 +57,11 @@ public class PayOrderManager extends BaseManager { /** * 查询对账用订单记录(指定时间和状态的订单) */ - public List findReconcile(String channel, LocalDateTime startTime, LocalDateTime endTime, PayStatusEnum...statusEnum) { - List status = Arrays.stream(statusEnum) - .map(PayStatusEnum::getCode) - .collect(Collectors.toList()); + public List findReconcile(String channel, LocalDateTime startTime, LocalDateTime endTime) { + List status = Arrays.asList(PayStatusEnum.SUCCESS.getCode(), + PayStatusEnum.PARTIAL_REFUND.getCode(), + PayStatusEnum.REFUNDING.getCode(), + PayStatusEnum.REFUNDED.getCode()); return this.lambdaQuery() .eq(PayOrder::getChannel, channel) .between(PayOrder::getPayTime, startTime, endTime) @@ -68,6 +69,21 @@ public class PayOrderManager extends BaseManager { .list(); } + /** + * 查询自动分账用订单记录(指定时间和状态的订单) + */ + public List findAllocation() { + List 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(); + } + /** * 查询汇总金额 */ diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/order/refund/dao/RefundOrderManager.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/order/refund/dao/RefundOrderManager.java index 2901bfd2c..e906b6fb4 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/order/refund/dao/RefundOrderManager.java +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/order/refund/dao/RefundOrderManager.java @@ -16,10 +16,8 @@ import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Repository; import java.time.LocalDateTime; -import java.util.Arrays; import java.util.List; import java.util.Optional; -import java.util.stream.Collectors; /** * 支付退款订单管理 @@ -77,14 +75,11 @@ public class RefundOrderManager extends BaseManager findReconcile(String channel, LocalDateTime startTime, LocalDateTime endTime, RefundStatusEnum...statusEnum) { - List status = Arrays.stream(statusEnum) - .map(RefundStatusEnum::getCode) - .collect(Collectors.toList()); + public List findReconcile(String channel, LocalDateTime startTime, LocalDateTime endTime) { return this.lambdaQuery() .eq(RefundOrder::getChannel, channel) .between(RefundOrder::getFinishTime, startTime, endTime) - .in(RefundOrder::getStatus, status) + .eq(RefundOrder::getStatus, RefundStatusEnum.SUCCESS) .list(); } diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/allocation/service/AllocationOrderSyncService.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/allocation/service/AllocationOrderSyncService.java deleted file mode 100644 index 941f2b179..000000000 --- a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/allocation/service/AllocationOrderSyncService.java +++ /dev/null @@ -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 { -} diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/allocation/service/AllocationService.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/allocation/service/AllocationService.java index 495222570..73bcf5b10 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/allocation/service/AllocationService.java +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/allocation/service/AllocationService.java @@ -1,15 +1,16 @@ 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.RepetitiveOperationException; import cn.bootx.platform.daxpay.code.AllocDetailResultEnum; import cn.bootx.platform.daxpay.code.AllocOrderResultEnum; import cn.bootx.platform.daxpay.code.AllocOrderStatusEnum; import cn.bootx.platform.daxpay.code.PayOrderAllocStatusEnum; 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.AllocationResetParam; 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.service.common.local.PaymentContextLocal; 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.OrderAndDetail; 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.service.PayOrderQueryService; 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.dto.allocation.AllocationGroupReceiverResult; import cn.bootx.platform.daxpay.service.func.AbsAllocationStrategy; +import com.baomidou.lock.LockInfo; +import com.baomidou.lock.LockTemplate; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; @@ -46,8 +48,6 @@ import java.util.Objects; @RequiredArgsConstructor public class AllocationService { - private final PayOrderManager payOrderManager; - private final AllocationGroupManager groupManager; private final AllocationOrderManager allocationOrderManager; @@ -58,55 +58,70 @@ public class AllocationService { private final AllocationOrderDetailManager allocationOrderDetailManager; private final PayOrderQueryService payOrderQueryService; + private final LockTemplate lockTemplate; + /** * 开启分账, 使用分账组进行分账 */ public AllocationResult allocation(AllocationStartParam param) { PayOrder payOrder = this.getAndCheckPayOrder(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("未查询到默认分账组")); + return this.allocation(payOrder, param); + } + + /** + * 开启分账, 未传输默认分账组, 则使用默认该通道默认分账组 + */ + 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 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 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); + // 查询默认分账组 + AllocationGroup allocationGroup; + if (Objects.nonNull(param.getAllocationGroupId())) { + allocationGroup = groupManager.findById(param.getAllocationGroupId()).orElseThrow(() -> new DataNotExistException("未查询到分账组")); + } else { + allocationGroup = groupManager.findDefaultGroup(payOrder.getChannel()).orElseThrow(() -> new DataNotExistException("未查询到默认分账组")); + } + List receiversByGroups = allocationGroupService.findReceiversByGroups(allocationGroup.getId()); + // 创建分账单和明细并保存, 同时更新支付订单状态 使用事务 + OrderAndDetail orderAndDetail = allocationOrderService.createAndUpdate(param ,payOrder, payOrder.getAmount(), receiversByGroups); - return new AllocationResult().setOrderId(order.getId()) - .setAllocationNo(order.getAllocationNo()) - .setStatus(order.getStatus()); + // 创建分账策略并初始化 + AbsAllocationStrategy allocationStrategy = AllocationFactory.create(payOrder.getChannel()); + AllocationOrder order = orderAndDetail.getOrder(); + List 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()) .orElseThrow(() -> new DataNotExistException("未查询到分账单信息")); } - // 需要是分账中分账中或者完成状态才能重新分账 - List list = Arrays.asList(AllocOrderStatusEnum.ALLOCATION_END.getCode(), - AllocOrderStatusEnum.ALLOCATION_FAILED.getCode(), - AllocOrderStatusEnum.ALLOCATION_PROCESSING.getCode()); - if (!list.contains(allocationOrder.getStatus())){ - throw new PayFailureException("分账单状态错误"); + LockInfo lock = lockTemplate.lock("payment:allocation:" + allocationOrder.getOrderId(),10000,200); + if (Objects.isNull(lock)){ + throw new RepetitiveOperationException("分账发起处理中,请勿重复操作"); } - List 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); + // 需要是分账中分账中或者完成状态才能重新分账 + List list = Arrays.asList(AllocOrderStatusEnum.ALLOCATION_END.getCode(), + AllocOrderStatusEnum.ALLOCATION_FAILED.getCode(), + AllocOrderStatusEnum.ALLOCATION_PROCESSING.getCode()); + if (!list.contains(allocationOrder.getStatus())){ + throw new PayFailureException("分账单状态错误"); + } + + List 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()) .orElseThrow(() -> new DataNotExistException("未查询到分账单信息")); } + this.finish(allocationOrder); + } + + /** + * 分账完结 + */ + public void finish(AllocationOrder allocationOrder) { // 只有分账结束后才可以完结 if (!AllocOrderStatusEnum.ALLOCATION_END.getCode().equals(allocationOrder.getStatus())){ throw new PayFailureException("分账单状态错误"); @@ -206,19 +237,34 @@ public class AllocationService { allocationOrder = allocationOrderManager.findByAllocationNo(param.getAllocationNo()) .orElseThrow(() -> new DataNotExistException("分账单不存在")); } - List detailList = allocationOrderDetailManager.findAllByOrderId(allocationOrder.getId()); - // 获取分账策略 - AbsAllocationStrategy allocationStrategy = AllocationFactory.create(allocationOrder.getChannel()); - allocationStrategy.initParam(allocationOrder, detailList); - // 分账完结预处理 - allocationStrategy.doBeforeHandler(); - allocationStrategy.doSync(); + this.sync(allocationOrder); + } - // 根据订单明细更新订单的状态和处理结果 - 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 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); + } } /** diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/reconcile/service/ReconcileAssistService.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/reconcile/service/ReconcileAssistService.java index 90240ce14..1f206f146 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/reconcile/service/ReconcileAssistService.java +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/reconcile/service/ReconcileAssistService.java @@ -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.util.CollUtil; 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.RefundStatusEnum; import cn.bootx.platform.daxpay.service.code.PaymentTypeEnum; 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.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.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.entity.RefundOrder; import cn.bootx.platform.daxpay.service.core.payment.reconcile.domain.GeneralTradeInfo; @@ -55,8 +53,8 @@ public class ReconcileAssistService { LocalDateTime end = LocalDateTimeUtil.endOfDay(localDateTime); // 下载支付订单 - List payOrders = payOrderManager.findReconcile(reconcileOrder.getChannel(), start, end, PayStatusEnum.SUCCESS, PayStatusEnum.PARTIAL_REFUND, PayStatusEnum.REFUNDING, PayStatusEnum.REFUNDED); - List refundOrders = refundOrderManager.findReconcile(reconcileOrder.getChannel(), start, end, RefundStatusEnum.SUCCESS); + List payOrders = payOrderManager.findReconcile(reconcileOrder.getChannel(), start, end); + List refundOrders = refundOrderManager.findReconcile(reconcileOrder.getChannel(), start, end); for (PayOrder payOrder : payOrders) { generalTradeInfoList.add(new GeneralTradeInfo() .setTitle(payOrder.getTitle()) diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/task/AllocationAutoStartTask.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/task/AllocationAutoStartTask.java new file mode 100644 index 000000000..c6a0d3bc1 --- /dev/null +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/task/AllocationAutoStartTask.java @@ -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()); + } + + } + + } +} diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/task/AllocationSyncTask.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/task/AllocationSyncTask.java new file mode 100644 index 000000000..d7410bba8 --- /dev/null +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/task/AllocationSyncTask.java @@ -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); + } + } + + } +}