diff --git a/daxpay-single/daxpay-single-admin/src/main/java/cn/bootx/platform/daxpay/admin/controller/order/PayReconcileOrderController.java b/daxpay-single/daxpay-single-admin/src/main/java/cn/bootx/platform/daxpay/admin/controller/order/PayReconcileOrderController.java index 4e77b9f9..a581a859 100644 --- a/daxpay-single/daxpay-single-admin/src/main/java/cn/bootx/platform/daxpay/admin/controller/order/PayReconcileOrderController.java +++ b/daxpay-single/daxpay-single-admin/src/main/java/cn/bootx/platform/daxpay/admin/controller/order/PayReconcileOrderController.java @@ -5,7 +5,6 @@ import cn.bootx.platform.common.core.rest.Res; import cn.bootx.platform.common.core.rest.ResResult; import cn.bootx.platform.common.core.rest.param.PageParam; import cn.bootx.platform.common.core.util.ValidationUtil; -import cn.bootx.platform.daxpay.service.core.order.reconcile.service.PayReconcileOrderService; import cn.bootx.platform.daxpay.service.core.order.reconcile.service.PayReconcileQueryService; import cn.bootx.platform.daxpay.service.core.payment.reconcile.service.PayReconcileService; import cn.bootx.platform.daxpay.service.dto.order.reconcile.PayReconcileDetailDto; @@ -29,14 +28,13 @@ import org.springframework.web.bind.annotation.*; @RequiredArgsConstructor public class PayReconcileOrderController { private final PayReconcileService reconcileService; - private final PayReconcileOrderService reconcileOrderService; private final PayReconcileQueryService reconcileQueryService; @Operation(summary = "手动创建支付对账订单") @PostMapping("/create") public ResResult create(@RequestBody ReconcileOrderCreate param){ ValidationUtil.validateParam(param); - reconcileOrderService.create(param.getDate(), param.getChannel()); + reconcileService.create(param.getDate(), param.getChannel()); return Res.ok(); } @@ -47,6 +45,13 @@ public class PayReconcileOrderController { return Res.ok(); } + @Operation(summary = "手动触发对账单比对") + @PostMapping("/compare") + public ResResult compare(Long id){ + reconcileService.compare(id); + return Res.ok(); + } + @Operation(summary = "订单分页") @GetMapping("/page") public ResResult> page(PageParam pageParam, ReconcileOrderQuery query){ diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/common/context/ReconcileLocal.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/common/context/ReconcileLocal.java index 0184f343..f1d73d6d 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/common/context/ReconcileLocal.java +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/common/context/ReconcileLocal.java @@ -4,7 +4,6 @@ import cn.bootx.platform.daxpay.service.core.order.reconcile.entity.PayReconcile import lombok.Data; import lombok.experimental.Accessors; -import java.time.LocalDateTime; import java.util.List; /** @@ -19,8 +18,4 @@ public class ReconcileLocal { /** 通用支付对账记录 */ private List reconcileDetails; - - /** 支付完成时间 从支付网关中获取 */ - private LocalDateTime payTime; - } diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/configuration/sequence/DaxPaySequenceConfiguration.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/configuration/sequence/DaxPaySequenceConfiguration.java new file mode 100644 index 00000000..d4966a79 --- /dev/null +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/configuration/sequence/DaxPaySequenceConfiguration.java @@ -0,0 +1,34 @@ +package cn.bootx.platform.daxpay.service.configuration.sequence; + +import cn.bootx.platform.common.sequence.func.Sequence; +import cn.bootx.platform.common.sequence.range.SeqRangeManager; +import cn.bootx.platform.common.sequence.util.SequenceUtil; +import lombok.RequiredArgsConstructor; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +/** + * 序列生成器配置类 + * @author xxm + * @since 2024/2/28 + */ +@Configuration +@RequiredArgsConstructor +public class DaxPaySequenceConfiguration { + + /** + * 支付宝对账单序列生成器 + */ + @Bean + public Sequence alipayReconcileSequence(SeqRangeManager seqRangeManager) { + return SequenceUtil.create(1,1,1,"AlipayReconcileSequence"); + } + + /** + * 微信对账单序列生成器 + */ + @Bean + public Sequence wechatReconcileSequence(SeqRangeManager seqRangeManager) { + return SequenceUtil.create(1,1,1,"WechatReconcileSequence"); + } +} diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/channel/alipay/dao/AliPayRecordManager.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/channel/alipay/dao/AliPayRecordManager.java index 2f8070d9..467a8b7c 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/channel/alipay/dao/AliPayRecordManager.java +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/channel/alipay/dao/AliPayRecordManager.java @@ -12,6 +12,9 @@ import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Repository; +import java.time.LocalDateTime; +import java.util.List; + /** * * @author xxm @@ -31,4 +34,13 @@ public class AliPayRecordManager extends BaseManager generator = QueryGenerator.generator(param); return this.page(mpPage, generator); } + + /** + * 按时间范围查询 + */ + public List findByDate(LocalDateTime startDate, LocalDateTime endDate){ + return this.lambdaQuery() + .between(AliPayRecord::getGatewayTime, startDate, endDate) + .list(); + } } diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/channel/alipay/entity/AliPayRecord.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/channel/alipay/entity/AliPayRecord.java index f62519c8..ccddffad 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/channel/alipay/entity/AliPayRecord.java +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/channel/alipay/entity/AliPayRecord.java @@ -12,6 +12,8 @@ import lombok.Data; import lombok.EqualsAndHashCode; import lombok.experimental.Accessors; +import java.time.LocalDateTime; + /** * 支付宝流水记录 * @author xxm @@ -47,6 +49,10 @@ public class AliPayRecord extends MpCreateEntity implements EntityBaseFunction generator = QueryGenerator.generator(param); return this.page(mpPage, generator); } + + /** + * 按时间范围查询 + */ + public List findByDate(LocalDateTime start, LocalDateTime end) { + return this.lambdaQuery() + .between(WeChatPayRecord::getGatewayTime, start, end) + .list(); + } } diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/channel/wechat/entity/WeChatPayRecord.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/channel/wechat/entity/WeChatPayRecord.java index 9738e955..abb8248e 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/channel/wechat/entity/WeChatPayRecord.java +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/channel/wechat/entity/WeChatPayRecord.java @@ -12,6 +12,8 @@ import lombok.Data; import lombok.EqualsAndHashCode; import lombok.experimental.Accessors; +import java.time.LocalDateTime; + /** * 微信支付记录 * @author xxm @@ -47,6 +49,10 @@ public class WeChatPayRecord extends MpCreateEntity implements EntityBaseFunctio @DbColumn(comment = "网关订单号") private String gatewayOrderNo; + /** 网关完成时间 */ + @DbColumn(comment = "网关完成时间") + private LocalDateTime gatewayTime; + @Override public WeChatPayRecordDto toDto() { return WeChatConvert.CONVERT.convert(this); diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/channel/wechat/service/WeChatPayRecordService.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/channel/wechat/service/WeChatPayRecordService.java index 4b2d191b..34e21033 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/channel/wechat/service/WeChatPayRecordService.java +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/channel/wechat/service/WeChatPayRecordService.java @@ -36,8 +36,9 @@ public class WeChatPayRecordService { .setType(WechatPayRecordTypeEnum.PAY.getCode()) .setTitle(order.getTitle()) .setOrderId(order.getId()) + .setAmount(channelOrder.getAmount()) .setGatewayOrderNo(order.getGatewayOrderNo()) - .setAmount(channelOrder.getAmount()); + .setGatewayTime(channelOrder.getPayTime()); weChatPayRecordManager.save(weChatPayRecord); } @@ -49,8 +50,9 @@ public class WeChatPayRecordService { .setType(WechatPayRecordTypeEnum.REFUND.getCode()) .setTitle(order.getTitle()) .setOrderId(order.getId()) + .setAmount(channelOrder.getAmount()) .setGatewayOrderNo(order.getGatewayOrderNo()) - .setAmount(channelOrder.getAmount()); + .setGatewayTime(channelOrder.getRefundTime()); weChatPayRecordManager.save(weChatPayRecord); } diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/channel/wechat/service/WechatPayReconcileService.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/channel/wechat/service/WechatPayReconcileService.java index 73d5c318..07c634da 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/channel/wechat/service/WechatPayReconcileService.java +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/channel/wechat/service/WechatPayReconcileService.java @@ -118,7 +118,7 @@ public class WechatPayReconcileService{ // 默认为支付对账记录 PayReconcileDetail payReconcileDetail = new PayReconcileDetail() .setRecordOrderId(billDetail.getRecordOrderId()) - .setPaymentId(billDetail.getMchOrderNo()) + .setOrderId(billDetail.getMchOrderNo()) .setTitle(billDetail.getSubject()) .setGatewayOrderNo(billDetail.getWeiXinOrderNo()); // 支付 @@ -138,7 +138,7 @@ public class WechatPayReconcileService{ int amount = Math.abs(((int) v)); payReconcileDetail.setType(PayReconcileTradeEnum.REFUND.getCode()) .setAmount(amount) - .setRefundId(billDetail.getMchRefundNo()); + .setOrderId(billDetail.getMchRefundNo()); } // TODO 已撤销, 暂时未处理 if (Objects.equals(billDetail.getStatus(), "REVOKED")){ diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/order/pay/entity/PayChannelOrder.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/order/pay/entity/PayChannelOrder.java index 3be2d17e..77e46122 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/order/pay/entity/PayChannelOrder.java +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/order/pay/entity/PayChannelOrder.java @@ -58,6 +58,7 @@ public class PayChannelOrder extends MpCreateEntity implements EntityBaseFunctio private String status; @DbColumn(comment = "支付时间") + @TableField(updateStrategy = FieldStrategy.ALWAYS) private LocalDateTime payTime; diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/order/pay/entity/PayOrder.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/order/pay/entity/PayOrder.java index b5e5f5ee..dcbfe8b8 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/order/pay/entity/PayOrder.java +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/order/pay/entity/PayOrder.java @@ -10,6 +10,8 @@ import cn.bootx.table.modify.annotation.DbColumn; import cn.bootx.table.modify.annotation.DbTable; import cn.bootx.table.modify.mysql.annotation.DbMySqlIndex; import cn.bootx.table.modify.mysql.constants.MySqlIndexType; +import com.baomidou.mybatisplus.annotation.FieldStrategy; +import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableName; import lombok.Data; import lombok.EqualsAndHashCode; @@ -76,10 +78,12 @@ public class PayOrder extends MpBaseEntity implements EntityBaseFunction { + + /** + * 根据订单id查询 + */ + public List findAllByOrderId(Long orderId){ + return this.findAllByField(PayReconcileDetail::getRecordOrderId, orderId); + } + /** * 分页 */ diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/order/reconcile/entity/PayReconcileDetail.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/order/reconcile/entity/PayReconcileDetail.java index 44dc550f..b134a90e 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/order/reconcile/entity/PayReconcileDetail.java +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/order/reconcile/entity/PayReconcileDetail.java @@ -45,6 +45,10 @@ public class PayReconcileDetail extends MpCreateEntity implements EntityBaseFunc /** 本地订单ID */ @DbColumn(comment = "本地订单ID") + private String orderId; + + /** 支付订单ID */ + @DbColumn(comment = "本地订单ID") private String paymentId; /** 本地退款ID */ diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/order/reconcile/entity/PayReconcileOrder.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/order/reconcile/entity/PayReconcileOrder.java index 2f20326e..33aa0616 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/order/reconcile/entity/PayReconcileOrder.java +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/order/reconcile/entity/PayReconcileOrder.java @@ -55,9 +55,6 @@ public class PayReconcileOrder extends MpCreateEntity implements EntityBaseFunct @DbColumn(comment = "错误信息") private String errorMsg; - /** - * @return - */ @Override public PayReconcileOrderDto toDto() { return PayReconcileConvert.CONVERT.convert(this); diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/order/reconcile/service/PayReconcileOrderService.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/order/reconcile/service/PayReconcileOrderService.java index 31ef1a73..915f789c 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/order/reconcile/service/PayReconcileOrderService.java +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/order/reconcile/service/PayReconcileOrderService.java @@ -1,19 +1,14 @@ package cn.bootx.platform.daxpay.service.core.order.reconcile.service; -import cn.bootx.platform.common.core.util.LocalDateTimeUtil; import cn.bootx.platform.common.sequence.func.Sequence; -import cn.bootx.platform.daxpay.code.PayChannelEnum; -import cn.bootx.platform.daxpay.exception.pay.PayFailureException; import cn.bootx.platform.daxpay.service.core.order.reconcile.dao.PayReconcileOrderManager; import cn.bootx.platform.daxpay.service.core.order.reconcile.entity.PayReconcileOrder; -import cn.hutool.core.date.DatePattern; 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.time.LocalDate; import java.util.Optional; /** @@ -43,37 +38,4 @@ public class PayReconcileOrderService { return reconcileOrderManager.findById(id); } - /** - * 创建对账订单 - */ - public PayReconcileOrder create(LocalDate date,String channel) { - // 获取通道枚举 - PayChannelEnum channelEnum = PayChannelEnum.findByCode(channel); - // 判断是否为为异步通道 - if (!PayChannelEnum.ASYNC_TYPE.contains(channelEnum)){ - throw new PayFailureException("不支持对账的通道, 请检查"); - } - // 生成批次号 - String format = LocalDateTimeUtil.format(date, DatePattern.PURE_DATE_PATTERN); - String key = channelEnum.getReconcilePrefix()+format; - String seqNo = key + this.genSeqNo(key); - - PayReconcileOrder order = new PayReconcileOrder() - .setBatchNo(seqNo) - .setChannel(channel) - .setDate(date); - reconcileOrderManager.save(order); - return order; - } - - - /** - * 生成批次号 - * 规则:通道简称 + yyyyMMdd + 两位流水号 - * 例子:wx2024012001、ali2024012002 - */ - private String genSeqNo(String key){ - long next = sequence.next(key); - return String.format("%02d",next); - } } diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/reconcile/service/PayReconcileService.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/reconcile/service/PayReconcileService.java index bbffcde7..565236fc 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/reconcile/service/PayReconcileService.java +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/reconcile/service/PayReconcileService.java @@ -1,8 +1,11 @@ package cn.bootx.platform.daxpay.service.core.payment.reconcile.service; import cn.bootx.platform.common.core.exception.DataNotExistException; +import cn.bootx.platform.daxpay.code.PayChannelEnum; +import cn.bootx.platform.daxpay.exception.pay.PayFailureException; import cn.bootx.platform.daxpay.service.common.local.PaymentContextLocal; import cn.bootx.platform.daxpay.service.core.order.reconcile.dao.PayReconcileDetailManager; +import cn.bootx.platform.daxpay.service.core.order.reconcile.dao.PayReconcileOrderManager; import cn.bootx.platform.daxpay.service.core.order.reconcile.entity.PayReconcileDetail; import cn.bootx.platform.daxpay.service.core.order.reconcile.entity.PayReconcileOrder; import cn.bootx.platform.daxpay.service.core.order.reconcile.service.PayReconcileOrderService; @@ -11,7 +14,10 @@ import cn.bootx.platform.daxpay.service.func.AbsReconcileStrategy; 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.time.LocalDate; import java.util.List; /** @@ -23,9 +29,36 @@ import java.util.List; @Service @RequiredArgsConstructor public class PayReconcileService { + private final PayReconcileOrderManager reconcileOrderManager; private final PayReconcileOrderService reconcileOrderService; private final PayReconcileDetailManager reconcileDetailManager; + /** + * 创建对账订单 + */ + @Transactional(propagation = Propagation.REQUIRES_NEW, rollbackFor = Exception.class) + public PayReconcileOrder create(LocalDate date, String channel) { + + // 获取通道枚举 + PayChannelEnum channelEnum = PayChannelEnum.findByCode(channel); + // 判断是否为为异步通道 + if (!PayChannelEnum.ASYNC_TYPE.contains(channelEnum)){ + throw new PayFailureException("不支持对账的通道, 请检查"); + } + // 构建对账策略 + AbsReconcileStrategy reconcileStrategy = PayReconcileStrategyFactory.create(channel); + + // 生成批次号 + String seqNo = reconcileStrategy.generateSequence(date); + + PayReconcileOrder order = new PayReconcileOrder() + .setBatchNo(seqNo) + .setChannel(channel) + .setDate(date); + reconcileOrderManager.save(order); + return order; + } + /** * 下载对账单并进行保存 */ @@ -38,19 +71,19 @@ public class PayReconcileService { /** * 下载对账单并进行保存 */ - public void downAndSave(PayReconcileOrder recordOrder) { + public void downAndSave(PayReconcileOrder reconcileOrder) { // 构建对账策略 - AbsReconcileStrategy absReconcileStrategy = PayReconcileStrategyFactory.create(recordOrder.getChannel()); - absReconcileStrategy.initParam(recordOrder); - absReconcileStrategy.doBeforeHandler(); + AbsReconcileStrategy reconcileStrategy = PayReconcileStrategyFactory.create(reconcileOrder.getChannel()); + reconcileStrategy.setRecordOrder(reconcileOrder); + reconcileStrategy.doBeforeHandler(); try { - absReconcileStrategy.downAndSave(); - recordOrder.setDown(true); - reconcileOrderService.update(recordOrder); + reconcileStrategy.downAndSave(); + reconcileOrder.setDown(true); + reconcileOrderService.update(reconcileOrder); } catch (Exception e) { log.error("下载对账单异常", e); - recordOrder.setErrorMsg("原因: " + e.getMessage()); - reconcileOrderService.update(recordOrder); + reconcileOrder.setErrorMsg("原因: " + e.getMessage()); + reconcileOrderService.update(reconcileOrder); throw new RuntimeException(e); } // 保存转换后的通用结构对账单 @@ -60,4 +93,47 @@ public class PayReconcileService { reconcileDetailManager.saveAll(reconcileDetails); } + /** + * 对账单比对 + */ + public void compare(Long reconcileOrderId){ + PayReconcileOrder payReconcileOrder = reconcileOrderService.findById(reconcileOrderId) + .orElseThrow(() -> new DataNotExistException("未找到对账订单")); + this.compare(payReconcileOrder); + } + + /** + * 对账单比对 + */ + public void compare(PayReconcileOrder reconcileOrder){ + // 判断是否已经下载了对账单明细 + if (!reconcileOrder.isDown()){ + throw new PayFailureException("请先下载对账单"); + } + + // 查询对账单 + List reconcileDetails = reconcileDetailManager.findAllByOrderId(reconcileOrder.getId()); + // 获取通道枚举 + if (!PayChannelEnum.ASYNC_TYPE_CODE.contains(reconcileOrder.getChannel())){ + log.error("不支持对账的通道, 请检查, 对账订单ID: {}", reconcileOrder.getId()); + throw new PayFailureException("不支持对账的通道, 请检查"); + } + // 判断是否为为异步通道 + // 构建对账策略 + AbsReconcileStrategy reconcileStrategy = PayReconcileStrategyFactory.create(reconcileOrder.getChannel()); + // 初始化参数 + reconcileStrategy.setRecordOrder(reconcileOrder); + reconcileStrategy.setReconcileDetails(reconcileDetails); + try { + // 执行比对任务 + reconcileStrategy.compare(); +// reconcileOrder.setCompare(true); +// reconcileOrderService.update(reconcileOrder); + } catch (Exception e) { + log.error("比对对账单异常", e); + reconcileOrder.setErrorMsg("原因: " + e.getMessage()); + reconcileOrderService.update(reconcileOrder); + throw new RuntimeException(e); + } + } } diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/reconcile/strategy/AlipayReconcileStrategy.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/reconcile/strategy/AlipayReconcileStrategy.java index 3a7df688..82e04df4 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/reconcile/strategy/AlipayReconcileStrategy.java +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/reconcile/strategy/AlipayReconcileStrategy.java @@ -1,17 +1,35 @@ package cn.bootx.platform.daxpay.service.core.payment.reconcile.strategy; +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.common.sequence.func.Sequence; import cn.bootx.platform.daxpay.code.PayChannelEnum; +import cn.bootx.platform.daxpay.code.PayReconcileTradeEnum; +import cn.bootx.platform.daxpay.service.code.AliPayRecordTypeEnum; +import cn.bootx.platform.daxpay.service.core.channel.alipay.dao.AliPayRecordManager; import cn.bootx.platform.daxpay.service.core.channel.alipay.entity.AliPayConfig; +import cn.bootx.platform.daxpay.service.core.channel.alipay.entity.AliPayRecord; import cn.bootx.platform.daxpay.service.core.channel.alipay.service.AliPayConfigService; import cn.bootx.platform.daxpay.service.core.channel.alipay.service.AliPayReconcileService; +import cn.bootx.platform.daxpay.service.core.order.reconcile.entity.PayReconcileDetail; import cn.bootx.platform.daxpay.service.func.AbsReconcileStrategy; import cn.hutool.core.date.DatePattern; +import lombok.Getter; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Service; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.function.Function; +import java.util.stream.Collectors; + import static org.springframework.beans.factory.config.BeanDefinition.SCOPE_PROTOTYPE; /** @@ -27,8 +45,14 @@ public class AlipayReconcileStrategy extends AbsReconcileStrategy { private final AliPayReconcileService reconcileService; + private final AliPayRecordManager recordManager; + private final AliPayConfigService configService; + @Getter + @Qualifier("alipayReconcileSequence") + private final Sequence sequence; + private AliPayConfig config; @@ -42,6 +66,19 @@ public class AlipayReconcileStrategy extends AbsReconcileStrategy { return PayChannelEnum.ALI; } + /** + * 生成对账序列号 + * 规则:通道简称 + yyyyMMdd + 两位流水号 + * 例子:wx2024012001、ali2024012002 + */ + @Override + public String generateSequence(LocalDate date) { + String prefix = getChannel().getReconcilePrefix(); + String dateStr = LocalDateTimeUtil.format(date, DatePattern.PURE_DATE_PATTERN); + String key = String.format("%02d", sequence.next()); + return prefix + dateStr + key; + } + /** * 对账前处理, 主要是初始化支付SDK配置 */ @@ -59,4 +96,69 @@ public class AlipayReconcileStrategy extends AbsReconcileStrategy { String date = LocalDateTimeUtil.format(this.getRecordOrder().getDate(), DatePattern.NORM_DATE_PATTERN); reconcileService.downAndSave(date,this.getRecordOrder().getId()); } + + /** + * 比对生成对账差异单 + * 1. 远程有, 本地无 补单(追加回订单/记录差异表) + * 2. 远程无, 本地有 记录差错表 + * 3. 远程有, 本地有, 但状态不一致 记录差错表 + */ + @Override + public void compare() { + List details = this.getReconcileDetails(); + if (CollUtil.isEmpty(details)){ + return; + } + Map detailMap = details.stream() + .collect(Collectors.toMap(PayReconcileDetail::getOrderId, Function.identity(), CollectorsFunction::retainLatest)); + + // 对哪天进行对账 + LocalDate date = this.getRecordOrder().getDate(); + + // 查询流水 + LocalDateTime localDateTime = LocalDateTimeUtil.date2DateTime(date); + LocalDateTime start = LocalDateTimeUtil.beginOfDay(localDateTime); + LocalDateTime end = LocalDateTimeUtil.endOfDay(localDateTime); + List records = recordManager.findByDate(start, end); + Map recordMap = records.stream() + .collect(Collectors.toMap(AliPayRecord::getOrderId, Function.identity(), CollectorsFunction::retainLatest)); + + // 对账与流水比对 + for (PayReconcileDetail detail : details) { + // 判断本地有没有记录 + AliPayRecord record = recordMap.get(Long.valueOf(detail.getOrderId())); + if (Objects.isNull(record)){ + log.info("本地订单不存在: {}", detail.getOrderId()); + continue; + } + System.out.println(detail.getId()); + // 交易类型 支付/退款 + if (Objects.equals(detail.getType(), PayReconcileTradeEnum.PAY.getCode())){ + // 判断类型是否存在差异 + if (!Objects.equals(record.getType(), AliPayRecordTypeEnum.PAY.getCode())){ + log.info("本地订单类型不正常: {}", detail.getOrderId()); + continue; + } + } else { + // 判断类型是否存在差异 + if (!Objects.equals(record.getType(), AliPayRecordTypeEnum.REFUND.getCode())){ + log.info("本地订单类型不正常: {}", detail.getOrderId()); + continue; + } + } + // 判断是否存在差异 金额, 状态 + if (!Objects.equals(record.getAmount(), detail.getAmount())){ + log.info("本地订单金额不正常: {}", detail.getOrderId()); + continue; + } + } + // 流水与对账单比对, 找出本地有, 远程没有的记录 + for (AliPayRecord record : records) { + PayReconcileDetail detail = detailMap.get(String.valueOf(record.getOrderId())); + if (Objects.isNull(detail)){ + log.info("远程订单不存在: {}", record.getOrderId()); + continue; + } + } + } } diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/reconcile/strategy/WechatPayReconcileStrategy.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/reconcile/strategy/WechatPayReconcileStrategy.java index 29730427..84c05e54 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/reconcile/strategy/WechatPayReconcileStrategy.java +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/reconcile/strategy/WechatPayReconcileStrategy.java @@ -1,17 +1,34 @@ package cn.bootx.platform.daxpay.service.core.payment.reconcile.strategy; +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.common.sequence.func.Sequence; import cn.bootx.platform.daxpay.code.PayChannelEnum; +import cn.bootx.platform.daxpay.code.PayReconcileTradeEnum; +import cn.bootx.platform.daxpay.service.code.AliPayRecordTypeEnum; +import cn.bootx.platform.daxpay.service.core.channel.wechat.dao.WeChatPayRecordManager; import cn.bootx.platform.daxpay.service.core.channel.wechat.entity.WeChatPayConfig; +import cn.bootx.platform.daxpay.service.core.channel.wechat.entity.WeChatPayRecord; import cn.bootx.platform.daxpay.service.core.channel.wechat.service.WeChatPayConfigService; import cn.bootx.platform.daxpay.service.core.channel.wechat.service.WechatPayReconcileService; +import cn.bootx.platform.daxpay.service.core.order.reconcile.entity.PayReconcileDetail; import cn.bootx.platform.daxpay.service.func.AbsReconcileStrategy; import cn.hutool.core.date.DatePattern; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Service; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.function.Function; +import java.util.stream.Collectors; + import static org.springframework.beans.factory.config.BeanDefinition.SCOPE_PROTOTYPE; /** @@ -29,6 +46,11 @@ public class WechatPayReconcileStrategy extends AbsReconcileStrategy { private final WeChatPayConfigService weChatPayConfigService; + private final WeChatPayRecordManager recordManager; + + @Qualifier("wechatReconcileSequence") + private final Sequence sequence; + private WeChatPayConfig config; /** @@ -41,6 +63,20 @@ public class WechatPayReconcileStrategy extends AbsReconcileStrategy { return PayChannelEnum.WECHAT; } + /** + * 生成对账序列号 + * 生成批次号 + * 规则:通道简称 + yyyyMMdd + 两位流水号 + * 例子:wx2024012001、ali2024012002 + */ + @Override + public String generateSequence(LocalDate date) { + String prefix = getChannel().getReconcilePrefix(); + String dateStr = LocalDateTimeUtil.format(date, DatePattern.PURE_DATE_PATTERN); + String key = String.format("%02d", sequence.next()); + return prefix + dateStr + key; + } + /** * 对账前处理, 主要是初始化支付SDK配置 */ @@ -57,4 +93,68 @@ public class WechatPayReconcileStrategy extends AbsReconcileStrategy { String format = LocalDateTimeUtil.format(this.getRecordOrder().getDate(), DatePattern.PURE_DATE_PATTERN); reconcileService.downAndSave(format,this.getRecordOrder().getId(), this.config); } + + /** + * 比对生成对账差异单 + * 1. 远程有, 本地无 补单(追加回订单/记录差异表) + * 2. 远程无, 本地有 记录差错表 + * 3. 远程有, 本地有, 但状态不一致 记录差错表 + */ + @Override + public void compare() { + List details = this.getReconcileDetails(); + if (CollUtil.isEmpty(details)){ + return; + } + Map detailMap = details.stream() + .collect(Collectors.toMap(PayReconcileDetail::getOrderId, Function.identity(), CollectorsFunction::retainLatest)); + + // 对哪天进行对账 + LocalDate date = this.getRecordOrder().getDate(); + + // 查询流水 + LocalDateTime localDateTime = LocalDateTimeUtil.date2DateTime(date); + LocalDateTime start = LocalDateTimeUtil.beginOfDay(localDateTime); + LocalDateTime end = LocalDateTimeUtil.endOfDay(localDateTime); + List records = recordManager.findByDate(start, end); + Map recordMap = records.stream() + .collect(Collectors.toMap(WeChatPayRecord::getOrderId, Function.identity(), CollectorsFunction::retainLatest)); + + // 对账与流水比对 + for (PayReconcileDetail detail : details) { + // 判断本地有没有记录 + WeChatPayRecord record = recordMap.get(Long.valueOf(detail.getOrderId())); + if (Objects.isNull(record)){ + log.info("本地订单不存在: {}", detail.getOrderId()); + continue; + } + // 交易类型 支付/退款 + if (Objects.equals(detail.getType(), PayReconcileTradeEnum.PAY.getCode())){ + // 判断类型是否存在差异 + if (!Objects.equals(record.getType(), AliPayRecordTypeEnum.PAY.getCode())){ + log.info("本地订单类型不正常: {}", detail.getOrderId()); + continue; + } + } else { + // 判断类型是否存在差异 + if (!Objects.equals(record.getType(), AliPayRecordTypeEnum.REFUND.getCode())){ + log.info("本地订单类型不正常: {}", detail.getOrderId()); + continue; + } + } + // 判断是否存在差异 金额, 状态 + if (!Objects.equals(record.getAmount(), detail.getAmount())){ + log.info("本地订单金额不正常: {}", detail.getOrderId()); + continue; + } + } + // 流水与对账单比对, 找出本地有, 远程没有的记录 + for (WeChatPayRecord record : records) { + PayReconcileDetail detail = detailMap.get(String.valueOf(record.getOrderId())); + if (Objects.isNull(detail)){ + log.info("远程订单不存在: {}", record.getOrderId()); + continue; + } + } + } } diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/repair/service/PayRepairService.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/repair/service/PayRepairService.java index c2ea358c..d3d3d841 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/repair/service/PayRepairService.java +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/repair/service/PayRepairService.java @@ -98,6 +98,9 @@ public class PayRepairService { List channelOrders = repairStrategies.stream() .map(AbsPayRepairStrategy::getChannelOrder) .collect(Collectors.toList()); + // 更新通道订单 + channelOrderManager.updateAllById(channelOrders); + // 发送通知 clientNoticeService.registerPayNotice(order, null, channelOrders); this.saveRecord(order, repairType, repairResult); return repairResult; @@ -105,13 +108,15 @@ public class PayRepairService { /** * 变更未待支付 - * + * TODO 后期保存为异常订单 */ private void waitPay(PayOrder order, List repairStrategies) { - - repairStrategies.forEach(AbsPayRepairStrategy::doCloseLocalHandler); - // 修改订单支付状态为成功 - order.setStatus(PayStatusEnum.PROGRESS.getCode()); + // 待支付批量处理 + repairStrategies.forEach(AbsPayRepairStrategy::doWaitPayHandler); + // 修改订单支付状态为待支付 + order.setStatus(PayStatusEnum.PROGRESS.getCode()) + .setPayTime(null) + .setCloseTime(null); payOrderService.updateById(order); } @@ -141,7 +146,7 @@ public class PayRepairService { // 执行策略的关闭方法 absPayStrategies.forEach(AbsPayRepairStrategy::doCloseLocalHandler); order.setStatus(PayStatusEnum.CLOSE.getCode()) - // TODO 尝试是否可以使用网关返回的 + // TODO 尝试是否可以使用网关返回的时间 .setCloseTime(LocalDateTime.now()); payOrderService.updateById(order); } diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/repair/strategy/pay/AliPayRepairStrategy.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/repair/strategy/pay/AliPayRepairStrategy.java index 8c17db6b..dae73fba 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/repair/strategy/pay/AliPayRepairStrategy.java +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/repair/strategy/pay/AliPayRepairStrategy.java @@ -7,7 +7,6 @@ import cn.bootx.platform.daxpay.service.core.channel.alipay.entity.AliPayConfig; import cn.bootx.platform.daxpay.service.core.channel.alipay.service.AliPayCloseService; import cn.bootx.platform.daxpay.service.core.channel.alipay.service.AliPayConfigService; import cn.bootx.platform.daxpay.service.core.channel.alipay.service.AliPayRecordService; -import cn.bootx.platform.daxpay.service.core.order.pay.dao.PayChannelOrderManager; import cn.bootx.platform.daxpay.service.func.AbsPayRepairStrategy; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -34,8 +33,6 @@ public class AliPayRepairStrategy extends AbsPayRepairStrategy { private final AliPayRecordService aliRecordService; - private final PayChannelOrderManager payChannelOrderManager; - /** * 策略标识 */ @@ -63,7 +60,6 @@ public class AliPayRepairStrategy extends AbsPayRepairStrategy { .getFinishTime(); this.getChannelOrder().setStatus(PayStatusEnum.SUCCESS.getCode()) .setPayTime(payTime); - payChannelOrderManager.updateById(this.getChannelOrder()); // 支付完成, 保存记录 aliRecordService.pay(this.getOrder(), this.getChannelOrder()); } @@ -72,8 +68,8 @@ public class AliPayRepairStrategy extends AbsPayRepairStrategy { * 等待支付处理 */ @Override - public void doWaitPayHandler() { - super.doWaitPayHandler(); + public void doWaitPayHandler(){ + this.getChannelOrder().setPayTime(null).setStatus(PayStatusEnum.PROGRESS.getCode()); } /** diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/repair/strategy/pay/WeChatPayRepairStrategy.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/repair/strategy/pay/WeChatPayRepairStrategy.java index b5bc6aa1..dc190bde 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/repair/strategy/pay/WeChatPayRepairStrategy.java +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/repair/strategy/pay/WeChatPayRepairStrategy.java @@ -7,7 +7,6 @@ import cn.bootx.platform.daxpay.service.core.channel.wechat.entity.WeChatPayConf import cn.bootx.platform.daxpay.service.core.channel.wechat.service.WeChatPayCloseService; import cn.bootx.platform.daxpay.service.core.channel.wechat.service.WeChatPayConfigService; import cn.bootx.platform.daxpay.service.core.channel.wechat.service.WeChatPayRecordService; -import cn.bootx.platform.daxpay.service.core.order.pay.dao.PayChannelOrderManager; import cn.bootx.platform.daxpay.service.func.AbsPayRepairStrategy; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -32,8 +31,6 @@ public class WeChatPayRepairStrategy extends AbsPayRepairStrategy { private final WeChatPayConfigService weChatPayConfigService; - private final PayChannelOrderManager payChannelOrderManager; - private final WeChatPayRecordService weChatPayRecordService; private WeChatPayConfig weChatPayConfig; @@ -46,6 +43,14 @@ public class WeChatPayRepairStrategy extends AbsPayRepairStrategy { return PayChannelEnum.WECHAT; } + /** + * 等待支付处理 + */ + @Override + public void doWaitPayHandler(){ + this.getChannelOrder().setPayTime(null).setStatus(PayStatusEnum.PROGRESS.getCode()); + } + /** * 修复前处理 */ @@ -64,7 +69,6 @@ public class WeChatPayRepairStrategy extends AbsPayRepairStrategy { .getFinishTime(); this.getChannelOrder().setStatus(PayStatusEnum.SUCCESS.getCode()) .setPayTime(payTime); - payChannelOrderManager.updateById(this.getChannelOrder()); // 保存流水记录 weChatPayRecordService.pay(this.getOrder(), this.getChannelOrder()); } diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/sync/service/PaySyncService.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/sync/service/PaySyncService.java index f7436d18..b2abc2d0 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/sync/service/PaySyncService.java +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/sync/service/PaySyncService.java @@ -104,11 +104,10 @@ public class PaySyncService { if (Objects.equals(syncResult.getSyncStatus(), PaySyncStatusEnum.FAIL)){ // 同步失败, 返回失败响应, 同时记录失败的日志 this.saveRecord(payOrder, syncResult, false, null, syncResult.getErrorMsg()); -// return new SyncResult().setErrorMsg(syncResult.getErrorMsg()); throw new PayFailureException(syncResult.getErrorMsg()); } // 支付订单的网关订单号是否一致, 不一致进行更新 - if (Objects.nonNull(syncResult.getGatewayOrderNo()) && !Objects.equals(syncResult.getGatewayOrderNo(), payOrder.getGatewayOrderNo())){ + if (!Objects.equals(syncResult.getGatewayOrderNo(), payOrder.getGatewayOrderNo())){ payOrder.setGatewayOrderNo(syncResult.getGatewayOrderNo()); payOrderService.updateById(payOrder); } diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/dto/channel/alipay/AliPayRecordDto.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/dto/channel/alipay/AliPayRecordDto.java index 9b84a16d..f89f85da 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/dto/channel/alipay/AliPayRecordDto.java +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/dto/channel/alipay/AliPayRecordDto.java @@ -7,6 +7,8 @@ import lombok.Data; import lombok.EqualsAndHashCode; import lombok.experimental.Accessors; +import java.time.LocalDateTime; + /** * 微信支付记录 * @author xxm @@ -41,4 +43,8 @@ public class AliPayRecordDto extends BaseDto { @Schema(description = "网关订单号") private String gatewayOrderNo; + /** 网关完成时间 */ + @Schema(description = "网关完成时间") + private LocalDateTime gatewayTime; + } diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/dto/channel/wechat/WeChatPayRecordDto.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/dto/channel/wechat/WeChatPayRecordDto.java index cec50114..7d106e92 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/dto/channel/wechat/WeChatPayRecordDto.java +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/dto/channel/wechat/WeChatPayRecordDto.java @@ -7,6 +7,8 @@ import lombok.Data; import lombok.EqualsAndHashCode; import lombok.experimental.Accessors; +import java.time.LocalDateTime; + /** * 微信支付记录 * @author xxm @@ -41,4 +43,8 @@ public class WeChatPayRecordDto extends BaseDto { @Schema(description = "网关订单号") private String gatewayOrderNo; + /** 网关完成时间 */ + @Schema(description = "网关完成时间") + private LocalDateTime gatewayTime; + } diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/func/AbsPayRepairStrategy.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/func/AbsPayRepairStrategy.java index 2148dad2..e2f7a570 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/func/AbsPayRepairStrategy.java +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/func/AbsPayRepairStrategy.java @@ -47,9 +47,7 @@ public abstract class AbsPayRepairStrategy implements PayStrategy{ /** * 等待支付处理 */ - public void doWaitPayHandler(){ - - } + public void doWaitPayHandler(){} /** * 关闭本地支付 diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/func/AbsReconcileStrategy.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/func/AbsReconcileStrategy.java index c3d65fe3..d74805ee 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/func/AbsReconcileStrategy.java +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/func/AbsReconcileStrategy.java @@ -1,32 +1,40 @@ package cn.bootx.platform.daxpay.service.func; +import cn.bootx.platform.daxpay.service.core.order.reconcile.entity.PayReconcileDetail; import cn.bootx.platform.daxpay.service.core.order.reconcile.entity.PayReconcileOrder; import lombok.Getter; +import lombok.Setter; + +import java.time.LocalDate; +import java.util.List; /** * 支付对账策略 * @author xxm * @since 2024/1/18 */ +@Setter @Getter public abstract class AbsReconcileStrategy implements PayStrategy { /** 对账订单 */ private PayReconcileOrder recordOrder; + /** 对账订单明细 */ + private List reconcileDetails; + + + /** + * 生成对账序列号 + */ + public abstract String generateSequence(LocalDate date); + /** * 对账前处理, 主要是初始化支付SDK配置 */ public void doBeforeHandler() { } - /** - * 初始化参数 - */ - public void initParam(PayReconcileOrder recordOrder){ - this.recordOrder = recordOrder; - } - /** * 下载对账单到本地进行保存 */ @@ -36,10 +44,8 @@ public abstract class AbsReconcileStrategy implements PayStrategy { * 比对生成对账差异单 * 1. 远程有, 本地无 补单(追加回订单/记录差异表) * 2. 远程无, 本地有 记录差错表 - * 3. 远程有, 本地有, 但状态不一致 + * 3. 远程有, 本地有, 但状态不一致 记录差错表 */ - public void offsetting(){ - - } + public abstract void compare(); } diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/param/order/RefundOrderQuery.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/param/order/RefundOrderQuery.java index d82dc9a1..0113f423 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/param/order/RefundOrderQuery.java +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/param/order/RefundOrderQuery.java @@ -20,10 +20,13 @@ import lombok.experimental.Accessors; @Schema(title = "支付退款查询参数") public class RefundOrderQuery extends QueryOrder { - @Schema(description = "退款号") + @Schema(description = "退款Id") private Long id; - @Schema(description = "支付号") + @Schema(description = "退款号") + private String refundNo; + + @Schema(description = "支付ID") private Long paymentId; @Schema(description = "关联的业务号") diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/task/PayReconcileTask.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/task/PayReconcileTask.java index 9740205a..bcd4f34e 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/task/PayReconcileTask.java +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/task/PayReconcileTask.java @@ -24,7 +24,7 @@ public class PayReconcileTask implements Job { private final PayReconcileTaskService reconcileTaskService; /** - * 若参数变量名修改 QuartzJobScheduler 中也需对应修改 需要给一个set方法, 让系统设置值 + * 要同步的通道 */ @Setter private String channel; @@ -47,6 +47,6 @@ public class PayReconcileTask implements Job { } else { date = date.minusDays(1); } - reconcileTaskService.x1(date,channel); + reconcileTaskService.reconcileTask(date,channel); } } diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/task/service/PayReconcileTaskService.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/task/service/PayReconcileTaskService.java index b896dbed..9bd94c70 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/task/service/PayReconcileTaskService.java +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/task/service/PayReconcileTaskService.java @@ -1,7 +1,6 @@ package cn.bootx.platform.daxpay.service.task.service; import cn.bootx.platform.daxpay.service.core.order.reconcile.entity.PayReconcileOrder; -import cn.bootx.platform.daxpay.service.core.order.reconcile.service.PayReconcileOrderService; import cn.bootx.platform.daxpay.service.core.payment.reconcile.service.PayReconcileService; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -19,21 +18,20 @@ import java.time.LocalDate; @RequiredArgsConstructor public class PayReconcileTaskService { private final PayReconcileService reconcileService; - private final PayReconcileOrderService reconcileOrderService; /** * 执行任务 */ - public void x1(LocalDate date, String channel){ + public void reconcileTask(LocalDate date, String channel){ // 1. 查询需要定时对账的通道, 创建出来对账订单 - PayReconcileOrder reconcileOrder = reconcileOrderService.create(date, channel); + PayReconcileOrder reconcileOrder = reconcileService.create(date, channel); // 2. 执行对账任务, 下载对账单并解析, 分别存储为原始数据和通用对账数据 reconcileService.downAndSave(reconcileOrder); // 3. 执行账单比对, 生成差异单 - + reconcileService.compare(reconcileOrder); } } diff --git a/lombok.config b/lombok.config index 547f3950..df1e5e5e 100644 --- a/lombok.config +++ b/lombok.config @@ -1,4 +1,5 @@ # 将字段上的注解拷贝到对应构造参数上, 如果要新增别的注解, 需要在下方重新进行定义, lombok.copyableAnnotations += org.springframework.context.annotation.Lazy +lombok.copyableAnnotations += org.springframework.beans.factory.annotation.Qualifier # 默认开启实体类的链式API 会导致一些反射相关类库出问题, 如 easyExcel #lombok.accessors.chain = true diff --git a/pom.xml b/pom.xml index 6cac1e85..33425cb6 100644 --- a/pom.xml +++ b/pom.xml @@ -29,7 +29,7 @@ 1.8 - 1.3.6.1 + 1.3.6.2 2.0.1 1.7.30