From 0fa7b41a206a6c8477cfef7e540fa03bdc932ce9 Mon Sep 17 00:00:00 2001 From: bootx Date: Sun, 5 May 2024 01:37:40 +0800 Subject: [PATCH] =?UTF-8?q?ref=20=E5=AF=B9=E8=B4=A6=E6=94=B9=E9=80=A0?= =?UTF-8?q?=EF=BC=8C=E6=94=AF=E6=8C=81=E5=8E=9F=E5=A7=8B=E5=AF=B9=E8=B4=A6?= =?UTF-8?q?=E5=8D=95=E4=BF=9D=E5=AD=98=E5=92=8C=E4=B8=8B=E8=BD=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- _doc/Task.md | 7 +- .../order/ReconcileOrderController.java | 37 ++- .../service/code/ReconcileFileTypeEnum.java | 15 +- .../common/context/ReconcileLocal.java | 4 +- .../service/AliPayReconcileService.java | 33 +- .../service/UnionPayReconcileService.java | 27 +- .../service/WechatPayReconcileService.java | 48 +-- .../reconcile/conver/ReconcileConvert.java | 12 +- ...Manager.java => ReconcileDiffManager.java} | 10 +- ...rdMapper.java => ReconcileDiffMapper.java} | 4 +- .../reconcile/dao/ReconcileFileManager.java | 9 + ....java => ReconcileTradeDetailManager.java} | 15 +- ...r.java => ReconcileTradeDetailMapper.java} | 4 +- ...cileDiffRecord.java => ReconcileDiff.java} | 25 +- .../order/reconcile/entity/ReconcileFile.java | 4 +- .../reconcile/entity/ReconcileOrder.java | 20 +- ...eDetail.java => ReconcileTradeDetail.java} | 12 +- .../service/ReconcileDiffService.java | 17 +- .../service/ReconcileQueryService.java | 15 +- .../service/ReconcileAssistService.java | 201 +++++++++++++ .../reconcile/service/ReconcileService.java | 284 +++++------------- .../strategy/AlipayReconcileStrategy.java | 3 +- .../strategy/UnionPayReconcileStrategy.java | 5 +- .../strategy/WechatPayReconcileStrategy.java | 10 +- ...ffRecordDto.java => ReconcileDiffDto.java} | 14 +- ...lDto.java => ReconcileTradeDetailDto.java} | 2 +- .../service/func/AbsReconcileStrategy.java | 3 +- .../param/reconcile/ReconcileUploadParam.java | 30 ++ .../task/service/ReconcileTaskService.java | 2 +- 29 files changed, 504 insertions(+), 368 deletions(-) rename daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/order/reconcile/dao/{ReconcileDiffRecordManager.java => ReconcileDiffManager.java} (68%) rename daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/order/reconcile/dao/{ReconcileDiffRecordMapper.java => ReconcileDiffMapper.java} (73%) rename daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/order/reconcile/dao/{ReconcileDetailManager.java => ReconcileTradeDetailManager.java} (62%) rename daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/order/reconcile/dao/{ReconcileDetailMapper.java => ReconcileTradeDetailMapper.java} (71%) rename daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/order/reconcile/entity/{ReconcileDiffRecord.java => ReconcileDiff.java} (80%) rename daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/order/reconcile/entity/{ReconcileDetail.java => ReconcileTradeDetail.java} (82%) create mode 100644 daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/reconcile/service/ReconcileAssistService.java rename daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/dto/order/reconcile/{ReconcileDiffRecordDto.java => ReconcileDiffDto.java} (86%) rename daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/dto/order/reconcile/{ReconcileDetailDto.java => ReconcileTradeDetailDto.java} (95%) create mode 100644 daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/param/reconcile/ReconcileUploadParam.java diff --git a/_doc/Task.md b/_doc/Task.md index 6efa99704..922d62361 100644 --- a/_doc/Task.md +++ b/_doc/Task.md @@ -18,12 +18,13 @@ - [x] 支付接口优化 - [x] 前端查询条件适配 - [x] paymentId替换 +- [ ] 支付订单和退款订单页面添加实时金额汇总展示 - [ ] 对账单改造 - [x] 去除对账单明细按钮 - [x] 增加对账结果计算和显示 - - [ ] 增加下载原始对账单功能 - - [ ] 保存原始的文件 - - [ ] 微信 + - [ ] 增加下载原始对账单功能(保证将明细文件进行储存) + - [x] 保存原始的文件 + - [x] 微信 - [x] 支付宝 - [x] 云闪付 - [ ] 解析原有文件, 可以转换为指定格式进行下载 diff --git a/daxpay-single/daxpay-single-admin/src/main/java/cn/bootx/platform/daxpay/admin/controller/order/ReconcileOrderController.java b/daxpay-single/daxpay-single-admin/src/main/java/cn/bootx/platform/daxpay/admin/controller/order/ReconcileOrderController.java index 6b46d592a..299635b21 100644 --- a/daxpay-single/daxpay-single-admin/src/main/java/cn/bootx/platform/daxpay/admin/controller/order/ReconcileOrderController.java +++ b/daxpay-single/daxpay-single-admin/src/main/java/cn/bootx/platform/daxpay/admin/controller/order/ReconcileOrderController.java @@ -8,16 +8,14 @@ import cn.bootx.platform.common.core.util.ValidationUtil; import cn.bootx.platform.daxpay.service.core.order.reconcile.service.ReconcileDiffService; import cn.bootx.platform.daxpay.service.core.order.reconcile.service.ReconcileQueryService; import cn.bootx.platform.daxpay.service.core.payment.reconcile.service.ReconcileService; -import cn.bootx.platform.daxpay.service.dto.order.reconcile.ReconcileDetailDto; -import cn.bootx.platform.daxpay.service.dto.order.reconcile.ReconcileDiffRecordDto; +import cn.bootx.platform.daxpay.service.dto.order.reconcile.ReconcileTradeDetailDto; +import cn.bootx.platform.daxpay.service.dto.order.reconcile.ReconcileDiffDto; import cn.bootx.platform.daxpay.service.dto.order.reconcile.ReconcileOrderDto; -import cn.bootx.platform.daxpay.service.param.reconcile.ReconcileDetailQuery; -import cn.bootx.platform.daxpay.service.param.reconcile.ReconcileDiffQuery; -import cn.bootx.platform.daxpay.service.param.reconcile.ReconcileOrderCreate; -import cn.bootx.platform.daxpay.service.param.reconcile.ReconcileOrderQuery; +import cn.bootx.platform.daxpay.service.param.reconcile.*; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import lombok.RequiredArgsConstructor; +import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; @@ -50,27 +48,34 @@ public class ReconcileOrderController { return Res.ok(); } - @Operation(summary = "手动上传对账单文件") + @Operation(summary = "手动上传交易对账单文件") @PostMapping("/upload") - public ResResult upload(Long id, MultipartFile file){ - reconcileService.upload(id,file); + public ResResult upload(ReconcileUploadParam param, MultipartFile file){ + ValidationUtil.validateParam(param); + reconcileService.upload(param,file); return Res.ok(); } - @Operation(summary = "手动触发对账单比对") + @Operation(summary = "手动触发交易对账单比对") @PostMapping("/compare") public ResResult compare(Long id){ reconcileService.compare(id); return Res.ok(); } - @Operation(summary = "订单分页") + @Operation(summary = "下载原始交易对账单文件") + @GetMapping("/downOriginal") + public ResponseEntity downOriginal(Long id){ + return reconcileService.downOriginal(id); + } + + @Operation(summary = "对账单分页") @GetMapping("/page") public ResResult> page(PageParam pageParam, ReconcileOrderQuery query){ return Res.ok(reconcileQueryService.page(pageParam, query)); } - @Operation(summary = "订单详情") + @Operation(summary = "对账单详情") @GetMapping("/findById") public ResResult findById(Long id){ return Res.ok(reconcileQueryService.findById(id)); @@ -78,25 +83,25 @@ public class ReconcileOrderController { @Operation(summary = "对账明细分页") @GetMapping("/detail/page") - public ResResult> pageDetail(PageParam pageParam, ReconcileDetailQuery query){ + public ResResult> pageDetail(PageParam pageParam, ReconcileDetailQuery query){ return Res.ok(reconcileQueryService.pageDetail(pageParam, query)); } @Operation(summary = "对账明细详情") @GetMapping("/detail/findById") - public ResResult findDetailById(Long id){ + public ResResult findDetailById(Long id){ return Res.ok(reconcileQueryService.findDetailById(id)); } @Operation(summary = "对账差异分页") @GetMapping("/diff/page") - public ResResult> pageDiff(PageParam pageParam, ReconcileDiffQuery query){ + public ResResult> pageDiff(PageParam pageParam, ReconcileDiffQuery query){ return Res.ok(reconcileDiffService.page(pageParam, query)); } @Operation(summary = "对账差异详情") @GetMapping("/diff/findById") - public ResResult findDiffById(Long id){ + public ResResult findDiffById(Long id){ return Res.ok(reconcileDiffService.findById(id)); } } diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/code/ReconcileFileTypeEnum.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/code/ReconcileFileTypeEnum.java index cbc9509cc..a9fb71c2d 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/code/ReconcileFileTypeEnum.java +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/code/ReconcileFileTypeEnum.java @@ -1,8 +1,12 @@ package cn.bootx.platform.daxpay.service.code; +import cn.bootx.platform.common.core.exception.DataNotExistException; import lombok.AllArgsConstructor; import lombok.Getter; +import java.util.Arrays; +import java.util.Objects; + /** * 对账单文件 * @author xxm @@ -12,11 +16,18 @@ import lombok.Getter; @AllArgsConstructor public enum ReconcileFileTypeEnum { - TOTAL("total", "汇总"), - DETAIL("detail", "明细"), + FUNDS("funds", "资金对账"), + TRADE("trade", "交易对账"), ZIP("zip", "压缩包"), ; private final String code; private final String name; + + public static ReconcileFileTypeEnum findByCode(String code){ + return Arrays.stream(values()) + .filter(value -> Objects.equals(value.getCode(), code)) + .findFirst() + .orElseThrow(() -> new DataNotExistException("未知的对账文件类型")); + } } 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 1384d6d35..e134cff8a 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 @@ -1,6 +1,6 @@ package cn.bootx.platform.daxpay.service.common.context; -import cn.bootx.platform.daxpay.service.core.order.reconcile.entity.ReconcileDetail; +import cn.bootx.platform.daxpay.service.core.order.reconcile.entity.ReconcileTradeDetail; import cn.bootx.platform.daxpay.service.core.order.reconcile.entity.ReconcileOrder; import lombok.Data; import lombok.experimental.Accessors; @@ -20,6 +20,6 @@ public class ReconcileLocal { private ReconcileOrder reconcileOrder; /** 通用支付对账记录 */ - private List reconcileDetails; + private List reconcileTradeDetails; } diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/channel/alipay/service/AliPayReconcileService.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/channel/alipay/service/AliPayReconcileService.java index 2730d38a5..9d4890c82 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/channel/alipay/service/AliPayReconcileService.java +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/channel/alipay/service/AliPayReconcileService.java @@ -12,7 +12,7 @@ import cn.bootx.platform.daxpay.service.core.channel.alipay.dao.AliReconcileBill import cn.bootx.platform.daxpay.service.core.channel.alipay.entity.AliReconcileBillDetail; import cn.bootx.platform.daxpay.service.core.channel.alipay.entity.AliReconcileBillTotal; import cn.bootx.platform.daxpay.service.core.order.reconcile.dao.ReconcileFileManager; -import cn.bootx.platform.daxpay.service.core.order.reconcile.entity.ReconcileDetail; +import cn.bootx.platform.daxpay.service.core.order.reconcile.entity.ReconcileTradeDetail; import cn.bootx.platform.daxpay.service.core.order.reconcile.entity.ReconcileFile; import cn.bootx.platform.daxpay.service.core.order.reconcile.entity.ReconcileOrder; import cn.hutool.core.date.DatePattern; @@ -87,14 +87,15 @@ public class AliPayReconcileService { // 获取对账单下载地址并下载 String url = response.getBillDownloadUrl(); - byte[] bytes = HttpUtil.downloadBytes(url); + byte[] zipBytes = HttpUtil.downloadBytes(url); // 使用 Apache commons-compress 包装流, 读取返回的对账CSV文件 - ZipArchiveInputStream zipArchiveInputStream = new ZipArchiveInputStream(new ByteArrayInputStream(bytes),"GBK"); + ZipArchiveInputStream zipArchiveInputStream = new ZipArchiveInputStream(new ByteArrayInputStream(zipBytes),"GBK"); ZipArchiveEntry entry; List billDetails = new ArrayList<>(); List billTotals = new ArrayList<>(); while ((entry= zipArchiveInputStream.getNextZipEntry()) != null){ - BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(zipArchiveInputStream,"GBK")); + byte[] bytes = IoUtil.readBytes(zipArchiveInputStream); + BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(new ByteArrayInputStream(bytes),"GBK")); List strings = IoUtil.readLines(bufferedReader, new ArrayList<>()); String name = entry.getName(); if (StrUtil.endWith(name,"_业务明细(汇总).csv")){ @@ -104,12 +105,11 @@ public class AliPayReconcileService { // 明细 billDetails = this.parseDetail(strings); } + // 保存原始对账文件 + this.saveOriginalFile(recordOrder, bytes); } - // 保存原始对账文件 - this.saveOriginalFile(recordOrder, bytes); // 保存原始对账记录 this.save(billDetails, billTotals); - // 将原始交易明细对账记录转换通用结构并保存到上下文中 this.convertAndSave(billDetails); @@ -162,25 +162,24 @@ public class AliPayReconcileService { * 转换为通用对账记录对象 */ private void convertAndSave(List billDetails){ - List collect = billDetails.stream() + List collect = billDetails.stream() .map(this::convert) .collect(Collectors.toList()); // 写入到上下文中 - PaymentContextLocal.get().getReconcileInfo().setReconcileDetails(collect); + PaymentContextLocal.get().getReconcileInfo().setReconcileTradeDetails(collect); } /** * 转换为通用对账记录对象 */ - private ReconcileDetail convert(AliReconcileBillDetail billDetail){ + private ReconcileTradeDetail convert(AliReconcileBillDetail billDetail){ // 金额 String orderAmount = billDetail.getOrderAmount(); double v = Double.parseDouble(orderAmount) * 100; int amount = Math.abs(((int) v)); - // 默认为支付对账记录 - ReconcileDetail reconcileDetail = new ReconcileDetail() + ReconcileTradeDetail reconcileTradeDetail = new ReconcileTradeDetail() .setReconcileId(billDetail.getReconcileId()) .setTradeNo(billDetail.getOutTradeNo()) .setType(ReconcileTradeEnum.PAY.getCode()) @@ -192,15 +191,15 @@ public class AliPayReconcileService { String endTime = billDetail.getEndTime(); if (StrUtil.isNotBlank(endTime)) { LocalDateTime time = LocalDateTimeUtil.parse(endTime, DatePattern.NORM_DATETIME_PATTERN); - reconcileDetail.setTradeTime(time); + reconcileTradeDetail.setTradeTime(time); } // 退款覆盖更新对应的字段 if (Objects.equals(billDetail.getTradeType(), "退款")){ - reconcileDetail.setTradeNo(billDetail.getBatchNo()) + reconcileTradeDetail.setTradeNo(billDetail.getBatchNo()) .setType(ReconcileTradeEnum.REFUND.getCode()); } - return reconcileDetail; + return reconcileTradeDetail; } @@ -243,7 +242,7 @@ public class AliPayReconcileService { PayChannelEnum channelEnum = PayChannelEnum.findByCode(reconcileOrder.getChannel()); String date = LocalDateTimeUtil.format(reconcileOrder.getDate(), DatePattern.PURE_DATE_PATTERN); // 将原始文件进行保存 通道-日期 - String fileName = StrUtil.format("{}-{}.zip", channelEnum.getName(),date); + String fileName = StrUtil.format("交易对账单-{}-{}.csv", channelEnum.getName(),date); UploadPretreatment uploadPretreatment = fileStorageService.of(bytes); if (StrUtil.isNotBlank(fileName)) { uploadPretreatment.setOriginalFilename(fileName); @@ -252,7 +251,7 @@ public class AliPayReconcileService { String fileId = upload.getId(); ReconcileFile reconcileFile = new ReconcileFile().setFileId(Long.valueOf(fileId)) .setReconcileId(reconcileOrder.getId()) - .setType(ReconcileFileTypeEnum.ZIP.getCode()); + .setType(ReconcileFileTypeEnum.TRADE.getCode()); reconcileFileManager.save(reconcileFile); } diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/channel/union/service/UnionPayReconcileService.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/channel/union/service/UnionPayReconcileService.java index 2b1cc9272..59c56cbae 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/channel/union/service/UnionPayReconcileService.java +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/channel/union/service/UnionPayReconcileService.java @@ -11,7 +11,7 @@ import cn.bootx.platform.daxpay.service.common.local.PaymentContextLocal; import cn.bootx.platform.daxpay.service.core.channel.union.dao.UnionReconcileBillDetailManager; import cn.bootx.platform.daxpay.service.core.channel.union.entity.UnionReconcileBillDetail; import cn.bootx.platform.daxpay.service.core.order.reconcile.dao.ReconcileFileManager; -import cn.bootx.platform.daxpay.service.core.order.reconcile.entity.ReconcileDetail; +import cn.bootx.platform.daxpay.service.core.order.reconcile.entity.ReconcileTradeDetail; import cn.bootx.platform.daxpay.service.core.order.reconcile.entity.ReconcileFile; import cn.bootx.platform.daxpay.service.core.order.reconcile.entity.ReconcileOrder; import cn.bootx.platform.daxpay.service.sdk.union.api.UnionPayKit; @@ -81,17 +81,18 @@ public class UnionPayReconcileService { ZipArchiveEntry entry; List billDetails = new ArrayList<>(); while ((entry= zipArchiveInputStream.getNextZipEntry()) != null){ - BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(zipArchiveInputStream,"GBK")); if (StrUtil.startWith(entry.getName(), RECONCILE_FILE_PREFIX)){ + byte[] bytes = IoUtil.readBytes(zipArchiveInputStream); + BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(new ByteArrayInputStream(bytes),"GBK")); // 明细解析 List strings = IoUtil.readLines(bufferedReader, new ArrayList<>()); billDetails = this.parseDetail(strings); + // 保存原始对账记录文件 + this.saveOriginalFile(reconcileOrder,bytes); } else { // 汇总目前不进行处理 } } - // 保存原始对账记录文件 - this.saveOriginalFile(reconcileOrder,zipBytes); // 保存原始对账记录 this.save(billDetails); // 转换为通用对账记录对象 @@ -151,19 +152,19 @@ public class UnionPayReconcileService { * 转换为通用对账记录对象 */ private void convertAndSave(List billDetails){ - List collect = billDetails.stream() + List collect = billDetails.stream() .map(this::convert) // 只处理支付和退款的对账记录 .filter(Objects::nonNull) .collect(Collectors.toList()); // 写入到上下文中 - PaymentContextLocal.get().getReconcileInfo().setReconcileDetails(collect); + PaymentContextLocal.get().getReconcileInfo().setReconcileTradeDetails(collect); } /** * 转换为通用对账记录对象 */ - private ReconcileDetail convert(UnionReconcileBillDetail billDetail){ + private ReconcileTradeDetail convert(UnionReconcileBillDetail billDetail){ ReconcileOrder reconcileOrder = PaymentContextLocal.get() .getReconcileInfo() .getReconcileOrder(); @@ -172,7 +173,7 @@ public class UnionPayReconcileService { int amount = Integer.parseInt(orderAmount); // 默认为支付对账记录 - ReconcileDetail reconcileDetail = new ReconcileDetail() + ReconcileTradeDetail reconcileTradeDetail = new ReconcileTradeDetail() .setTitle("未知") .setReconcileId(billDetail.getReconcileId()) .setTradeNo(billDetail.getOrderId()) @@ -187,14 +188,14 @@ public class UnionPayReconcileService { String txnTime = year + billDetail.getTxnTime(); if (StrUtil.isNotBlank(txnTime)) { LocalDateTime time = LocalDateTimeUtil.parse(txnTime, DatePattern.PURE_DATETIME_PATTERN); - reconcileDetail.setTradeTime(time); + reconcileTradeDetail.setTradeTime(time); } // 退款覆盖更新对应的字段 if (Objects.equals(billDetail.getTradeType(), UnionPayCode.RECONCILE_TYPE_REFUND)){ - reconcileDetail.setType(ReconcileTradeEnum.REFUND.getCode()); + reconcileTradeDetail.setType(ReconcileTradeEnum.REFUND.getCode()); } - return reconcileDetail; + return reconcileTradeDetail; } /** @@ -213,7 +214,7 @@ public class UnionPayReconcileService { PayChannelEnum channelEnum = PayChannelEnum.findByCode(reconcileOrder.getChannel()); String date = LocalDateTimeUtil.format(reconcileOrder.getDate(), DatePattern.PURE_DATE_PATTERN); // 将原始文件进行保存 通道-日期 - String fileName = StrUtil.format("{}-{}.zip", channelEnum.getName(),date); + String fileName = StrUtil.format("交易对账单-{}-{}.txt", channelEnum.getName(),date); UploadPretreatment uploadPretreatment = fileStorageService.of(bytes); if (StrUtil.isNotBlank(fileName)) { uploadPretreatment.setOriginalFilename(fileName); @@ -222,7 +223,7 @@ public class UnionPayReconcileService { String fileId = upload.getId(); ReconcileFile reconcileFile = new ReconcileFile().setFileId(Long.valueOf(fileId)) .setReconcileId(reconcileOrder.getId()) - .setType(ReconcileFileTypeEnum.ZIP.getCode()); + .setType(ReconcileFileTypeEnum.TRADE.getCode()); reconcileFileManager.save(reconcileFile); } } 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 119ed106a..d7e719e16 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 @@ -14,7 +14,7 @@ import cn.bootx.platform.daxpay.service.core.channel.wechat.entity.WxReconcileBi import cn.bootx.platform.daxpay.service.core.channel.wechat.entity.WxReconcileBillTotal; import cn.bootx.platform.daxpay.service.core.channel.wechat.entity.WxReconcileFundFlowDetail; import cn.bootx.platform.daxpay.service.core.order.reconcile.dao.ReconcileFileManager; -import cn.bootx.platform.daxpay.service.core.order.reconcile.entity.ReconcileDetail; +import cn.bootx.platform.daxpay.service.core.order.reconcile.entity.ReconcileTradeDetail; import cn.bootx.platform.daxpay.service.core.order.reconcile.entity.ReconcileFile; import cn.bootx.platform.daxpay.service.core.order.reconcile.entity.ReconcileOrder; import cn.hutool.core.codec.Base64; @@ -66,23 +66,24 @@ public class WechatPayReconcileService{ /** * 下载对账单并保存 - * @param date 对账日期 yyyyMMdd 格式 + * + * @param recordOrder 对账订单 + * @param date 对账日期 yyyyMMdd 格式 */ @Transactional(rollbackFor = Exception.class) - public void downAndSave(String date, WeChatPayConfig config) { - // TODO 修改为现将对账单全部下载下来, 然后再进行保存和解析 - - this.downBill(date, config); + public void downAndSave(ReconcileOrder recordOrder, String date, WeChatPayConfig config) { + this.downBill(recordOrder, date, config); // 资金对账单先不启用 - this.downFundFlow(date, config); +// this.downFundFlow(date, config); } /** * 下载交易账单 * - * @param date 对账日期 yyyyMMdd 格式 + * @param recordOrder 对账订单 + * @param date 对账日期 yyyyMMdd 格式 */ - public void downBill(String date, WeChatPayConfig config){ + public void downBill(ReconcileOrder recordOrder, String date, WeChatPayConfig config){ // 下载交易账单 Map params = DownloadBillModel.builder() .mch_id(config.getWxMchId()) @@ -94,6 +95,9 @@ public class WechatPayReconcileService{ .createSign(config.getApiKeyV2(), SignType.HMACSHA256); String result = WxPayApi.downloadBill(config.isSandbox(), params); + // 保存原始对账单文件 + this.saveOriginalFile(recordOrder, result); + // 验证返回数据是否成功 this.verifyBillMsg(result); @@ -153,30 +157,30 @@ public class WechatPayReconcileService{ .collect(Collectors.toList()); billDetails.forEach(o->o.setRecordOrderId(reconcileOrder.getId())); - // 保存原始对账单明细 - reconcileBillDetailManager.saveAll(billDetails); // 将原始交易明细对账记录转换通用结构并保存到上下文中 this.convertAndSave(billDetails); + // 保存原始对账单明细 + reconcileBillDetailManager.saveAll(billDetails); } /** * 转换为通用对账记录对象 */ public void convertAndSave(List billDetails){ - List collect = billDetails.stream() + List collect = billDetails.stream() .map(this::convert) .collect(Collectors.toList()); // 写入到上下文中 - PaymentContextLocal.get().getReconcileInfo().setReconcileDetails(collect); + PaymentContextLocal.get().getReconcileInfo().setReconcileTradeDetails(collect); } /** * 转换为通用对账记录对象 */ - public ReconcileDetail convert(WxReconcileBillDetail billDetail){ + public ReconcileTradeDetail convert(WxReconcileBillDetail billDetail){ // 默认为支付对账记录 - ReconcileDetail reconcileDetail = new ReconcileDetail() + ReconcileTradeDetail reconcileTradeDetail = new ReconcileTradeDetail() .setReconcileId(billDetail.getRecordOrderId()) .setTradeNo(billDetail.getMchOrderNo()) .setTitle(billDetail.getSubject()) @@ -185,7 +189,7 @@ public class WechatPayReconcileService{ String transactionTime = billDetail.getTransactionTime(); if (StrUtil.isNotBlank(transactionTime)) { LocalDateTime time = LocalDateTimeUtil.parse(transactionTime, DatePattern.NORM_DATETIME_PATTERN); - reconcileDetail.setTradeTime(time); + reconcileTradeDetail.setTradeTime(time); } // 支付 @@ -194,7 +198,7 @@ public class WechatPayReconcileService{ String orderAmount = billDetail.getOrderAmount(); double v = Double.parseDouble(orderAmount) * 100; int amount = Math.abs(((int) v)); - reconcileDetail.setType(ReconcileTradeEnum.PAY.getCode()) + reconcileTradeDetail.setType(ReconcileTradeEnum.PAY.getCode()) .setAmount(amount); } // 退款 @@ -203,7 +207,7 @@ public class WechatPayReconcileService{ String refundAmount = billDetail.getApplyRefundAmount(); double v = Double.parseDouble(refundAmount) * 100; int amount = Math.abs(((int) v)); - reconcileDetail.setType(ReconcileTradeEnum.REFUND.getCode()) + reconcileTradeDetail.setType(ReconcileTradeEnum.REFUND.getCode()) .setAmount(amount) .setTradeNo(billDetail.getMchRefundNo()); } @@ -211,7 +215,7 @@ public class WechatPayReconcileService{ if (Objects.equals(billDetail.getStatus(), "REVOKED")){ log.warn("对账出现已撤销记录, 后续进行处理"); } - return reconcileDetail; + return reconcileTradeDetail; } @@ -314,12 +318,12 @@ public class WechatPayReconcileService{ /** * 保存下载的原始对账文件 */ - private void saveOriginalFile(ReconcileOrder reconcileOrder,String text, ReconcileFileTypeEnum fileType) { + private void saveOriginalFile(ReconcileOrder reconcileOrder, String text) { // 微信接收结果转换为 byte[] PayChannelEnum channelEnum = PayChannelEnum.findByCode(reconcileOrder.getChannel()); String date = LocalDateTimeUtil.format(reconcileOrder.getDate(), DatePattern.PURE_DATE_PATTERN); // 将原始文件进行保存 通道-日期 - String fileName = StrUtil.format("{}-{}-{}.text", channelEnum.getName(),date,fileType.getName()); + String fileName = StrUtil.format("交易对账单-{}-{}.txt", channelEnum.getName(),date); byte[] bytes = StrUtil.bytes(text, CharsetUtil.CHARSET_UTF_8); UploadPretreatment uploadPretreatment = fileStorageService.of(bytes); if (StrUtil.isNotBlank(fileName)) { @@ -329,7 +333,7 @@ public class WechatPayReconcileService{ String fileId = upload.getId(); ReconcileFile reconcileFile = new ReconcileFile().setFileId(Long.valueOf(fileId)) .setReconcileId(reconcileOrder.getId()) - .setType(fileType.getCode()); + .setType(ReconcileFileTypeEnum.TRADE.getCode()); reconcileFileManager.save(reconcileFile); } } diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/order/reconcile/conver/ReconcileConvert.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/order/reconcile/conver/ReconcileConvert.java index bfe5a0efe..9550dee47 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/order/reconcile/conver/ReconcileConvert.java +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/order/reconcile/conver/ReconcileConvert.java @@ -1,10 +1,10 @@ package cn.bootx.platform.daxpay.service.core.order.reconcile.conver; -import cn.bootx.platform.daxpay.service.core.order.reconcile.entity.ReconcileDetail; -import cn.bootx.platform.daxpay.service.core.order.reconcile.entity.ReconcileDiffRecord; +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.dto.order.reconcile.ReconcileDetailDto; -import cn.bootx.platform.daxpay.service.dto.order.reconcile.ReconcileDiffRecordDto; +import cn.bootx.platform.daxpay.service.dto.order.reconcile.ReconcileTradeDetailDto; +import cn.bootx.platform.daxpay.service.dto.order.reconcile.ReconcileDiffDto; import cn.bootx.platform.daxpay.service.dto.order.reconcile.ReconcileOrderDto; import org.mapstruct.Mapper; import org.mapstruct.factory.Mappers; @@ -18,9 +18,9 @@ import org.mapstruct.factory.Mappers; public interface ReconcileConvert { ReconcileConvert CONVERT = Mappers.getMapper(ReconcileConvert.class); - ReconcileDetailDto convert(ReconcileDetail in); + ReconcileTradeDetailDto convert(ReconcileTradeDetail in); - ReconcileDiffRecordDto convert(ReconcileDiffRecord in); + ReconcileDiffDto convert(ReconcileDiff in); ReconcileOrderDto convert(ReconcileOrder in); } diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/order/reconcile/dao/ReconcileDiffRecordManager.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/order/reconcile/dao/ReconcileDiffManager.java similarity index 68% rename from daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/order/reconcile/dao/ReconcileDiffRecordManager.java rename to daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/order/reconcile/dao/ReconcileDiffManager.java index 972e6f11b..694b39f81 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/order/reconcile/dao/ReconcileDiffRecordManager.java +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/order/reconcile/dao/ReconcileDiffManager.java @@ -4,7 +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.service.core.order.reconcile.entity.ReconcileDiffRecord; +import cn.bootx.platform.daxpay.service.core.order.reconcile.entity.ReconcileDiff; import cn.bootx.platform.daxpay.service.param.reconcile.ReconcileDiffQuery; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; @@ -20,14 +20,14 @@ import org.springframework.stereotype.Repository; @Slf4j @Repository @RequiredArgsConstructor -public class ReconcileDiffRecordManager extends BaseManager { +public class ReconcileDiffManager extends BaseManager { /** * 分页 */ - public Page page(PageParam pageParam, ReconcileDiffQuery query){ - Page mpPage = MpUtil.getMpPage(pageParam, ReconcileDiffRecord.class); - QueryWrapper generator = QueryGenerator.generator(query); + public Page page(PageParam pageParam, ReconcileDiffQuery query){ + Page mpPage = MpUtil.getMpPage(pageParam, ReconcileDiff.class); + QueryWrapper generator = QueryGenerator.generator(query); return this.page(mpPage,generator); } } diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/order/reconcile/dao/ReconcileDiffRecordMapper.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/order/reconcile/dao/ReconcileDiffMapper.java similarity index 73% rename from daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/order/reconcile/dao/ReconcileDiffRecordMapper.java rename to daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/order/reconcile/dao/ReconcileDiffMapper.java index 6a86148d7..89beec955 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/order/reconcile/dao/ReconcileDiffRecordMapper.java +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/order/reconcile/dao/ReconcileDiffMapper.java @@ -1,6 +1,6 @@ package cn.bootx.platform.daxpay.service.core.order.reconcile.dao; -import cn.bootx.platform.daxpay.service.core.order.reconcile.entity.ReconcileDiffRecord; +import cn.bootx.platform.daxpay.service.core.order.reconcile.entity.ReconcileDiff; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import org.apache.ibatis.annotations.Mapper; @@ -10,5 +10,5 @@ import org.apache.ibatis.annotations.Mapper; * @since 2024/2/28 */ @Mapper -public interface ReconcileDiffRecordMapper extends BaseMapper { +public interface ReconcileDiffMapper extends BaseMapper { } diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/order/reconcile/dao/ReconcileFileManager.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/order/reconcile/dao/ReconcileFileManager.java index 1a88a3ec9..1c946c3c3 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/order/reconcile/dao/ReconcileFileManager.java +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/order/reconcile/dao/ReconcileFileManager.java @@ -5,6 +5,8 @@ import cn.bootx.platform.daxpay.service.core.order.reconcile.entity.ReconcileFil import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Repository; +import java.util.List; + /** * * @author xxm @@ -13,4 +15,11 @@ import org.springframework.stereotype.Repository; @Slf4j @Repository public class ReconcileFileManager extends BaseManager { + + /** + * 根据对账单ID查询对账单文件 + */ + public List findAllByReconcileId(Long reconcileId) { + return findAllByField(ReconcileFile::getReconcileId, reconcileId); + } } diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/order/reconcile/dao/ReconcileDetailManager.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/order/reconcile/dao/ReconcileTradeDetailManager.java similarity index 62% rename from daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/order/reconcile/dao/ReconcileDetailManager.java rename to daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/order/reconcile/dao/ReconcileTradeDetailManager.java index 3d67ef47a..666f91bf6 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/order/reconcile/dao/ReconcileDetailManager.java +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/order/reconcile/dao/ReconcileTradeDetailManager.java @@ -4,7 +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.service.core.order.reconcile.entity.ReconcileDetail; +import cn.bootx.platform.daxpay.service.core.order.reconcile.entity.ReconcileTradeDetail; import cn.bootx.platform.daxpay.service.param.reconcile.ReconcileDetailQuery; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; @@ -22,22 +22,23 @@ import java.util.List; @Slf4j @Repository @RequiredArgsConstructor -public class ReconcileDetailManager extends BaseManager { +public class ReconcileTradeDetailManager extends BaseManager { /** * 根据订单id查询 */ - public List findAllByReconcileId(Long reconcileId){ - return this.findAllByField(ReconcileDetail::getReconcileId, reconcileId); + public List findAllByReconcileId(Long reconcileId){ + return this.findAllByField(ReconcileTradeDetail::getReconcileId, reconcileId); } /** * 分页 */ - public Page page(PageParam pageParam, ReconcileDetailQuery query){ - Page mpPage = MpUtil.getMpPage(pageParam, ReconcileDetail.class); - QueryWrapper generator = QueryGenerator.generator(query); + public Page page(PageParam pageParam, ReconcileDetailQuery query){ + Page mpPage = MpUtil.getMpPage(pageParam, ReconcileTradeDetail.class); + QueryWrapper generator = QueryGenerator.generator(query); return this.page(mpPage,generator); } + } diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/order/reconcile/dao/ReconcileDetailMapper.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/order/reconcile/dao/ReconcileTradeDetailMapper.java similarity index 71% rename from daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/order/reconcile/dao/ReconcileDetailMapper.java rename to daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/order/reconcile/dao/ReconcileTradeDetailMapper.java index 5b4860ce9..036992d64 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/order/reconcile/dao/ReconcileDetailMapper.java +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/order/reconcile/dao/ReconcileTradeDetailMapper.java @@ -1,6 +1,6 @@ package cn.bootx.platform.daxpay.service.core.order.reconcile.dao; -import cn.bootx.platform.daxpay.service.core.order.reconcile.entity.ReconcileDetail; +import cn.bootx.platform.daxpay.service.core.order.reconcile.entity.ReconcileTradeDetail; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import org.apache.ibatis.annotations.Mapper; @@ -10,5 +10,5 @@ import org.apache.ibatis.annotations.Mapper; * @since 2024/1/20 */ @Mapper -public interface ReconcileDetailMapper extends BaseMapper { +public interface ReconcileTradeDetailMapper extends BaseMapper { } diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/order/reconcile/entity/ReconcileDiffRecord.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/order/reconcile/entity/ReconcileDiff.java similarity index 80% rename from daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/order/reconcile/entity/ReconcileDiffRecord.java rename to daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/order/reconcile/entity/ReconcileDiff.java index d88083060..a7b9a6699 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/order/reconcile/entity/ReconcileDiffRecord.java +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/order/reconcile/entity/ReconcileDiff.java @@ -6,8 +6,7 @@ import cn.bootx.platform.daxpay.code.ReconcileTradeEnum; import cn.bootx.platform.daxpay.service.code.ReconcileDiffTypeEnum; import cn.bootx.platform.daxpay.service.common.typehandler.ReconcileDiffTypeHandler; import cn.bootx.platform.daxpay.service.core.order.reconcile.conver.ReconcileConvert; -import cn.bootx.platform.daxpay.service.core.payment.reconcile.domain.ReconcileDiff; -import cn.bootx.platform.daxpay.service.dto.order.reconcile.ReconcileDiffRecordDto; +import cn.bootx.platform.daxpay.service.dto.order.reconcile.ReconcileDiffDto; import cn.bootx.table.modify.annotation.DbColumn; import cn.bootx.table.modify.annotation.DbTable; import cn.bootx.table.modify.mysql.annotation.DbMySqlFieldType; @@ -31,16 +30,24 @@ import java.util.List; @Accessors(chain = true) @DbTable(comment = "对账差异单") @TableName(value = "pay_reconcile_diff_record",autoResultMap = true) -public class ReconcileDiffRecord extends MpBaseEntity implements EntityBaseFunction { +public class ReconcileDiff extends MpBaseEntity implements EntityBaseFunction { /** 对账单ID */ @DbColumn(comment = "对账单ID") private Long reconcileId; + /** 对账号 */ + @DbColumn(comment = "对账号") + private String reconcileNo; + /** 对账单明细ID */ @DbColumn(comment = "对账单明细ID") private Long detailId; + /** 对账日期 */ + @DbColumn(comment = "对账日期") + private LocalDateTime reconcileDate; + /** 本地交易号 */ @DbColumn(comment = "本地交易号") private String tradeNo; @@ -67,11 +74,11 @@ public class ReconcileDiffRecord extends MpBaseEntity implements EntityBaseFunct private Integer outAmount; /** - * 订单类型 + * 交易类型 * @see ReconcileTradeEnum */ - @DbColumn(comment = "订单类型") - private String orderType; + @DbColumn(comment = "交易类型") + private String tradeType; /** * 差异类型 @@ -83,15 +90,15 @@ public class ReconcileDiffRecord extends MpBaseEntity implements EntityBaseFunct /** * 差异内容, 存储json字符串, 格式为 * {属性: '标题', 本地字段值:'标题1', 网关字段值: '标题2'} - * @see ReconcileDiff + * @see cn.bootx.platform.daxpay.service.core.payment.reconcile.domain.ReconcileDiff */ @DbColumn(comment = "差异内容") @TableField(typeHandler = ReconcileDiffTypeHandler.class) @DbMySqlFieldType(MySqlFieldTypeEnum.LONGTEXT) - private List diffs; + private List diffs; @Override - public ReconcileDiffRecordDto toDto() { + public ReconcileDiffDto toDto() { return ReconcileConvert.CONVERT.convert(this); } } diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/order/reconcile/entity/ReconcileFile.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/order/reconcile/entity/ReconcileFile.java index c3fcae0d5..2804597a0 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/order/reconcile/entity/ReconcileFile.java +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/order/reconcile/entity/ReconcileFile.java @@ -10,14 +10,14 @@ import lombok.EqualsAndHashCode; import lombok.experimental.Accessors; /** - * + * 原始对账单文件 * @author xxm * @since 2024/5/3 */ @EqualsAndHashCode(callSuper = true) @Data @Accessors(chain = true) -@DbTable(comment = "对账单文件") +@DbTable(comment = "原始对账单文件") @TableName("pay_reconcile_file") public class ReconcileFile extends MpIdEntity { diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/order/reconcile/entity/ReconcileOrder.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/order/reconcile/entity/ReconcileOrder.java index 20b2852a2..58232835c 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/order/reconcile/entity/ReconcileOrder.java +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/order/reconcile/entity/ReconcileOrder.java @@ -18,7 +18,7 @@ import lombok.experimental.Accessors; import java.time.LocalDate; /** - * 支付对账单订单 + * 支付对账单订单(交易对账单, 不包括资金对账) * @author xxm * @since 2024/1/18 */ @@ -44,24 +44,16 @@ public class ReconcileOrder extends MpCreateEntity implements EntityBaseFunction @DbColumn(comment = "通道") private String channel; - /** 明细对账文件是否下载成功 */ + /** 交易对账文件是否下载成功 */ @DbColumn(comment = "明细对账单下载") - private boolean detailDown; + private boolean downOrUpload; - /** 明细是否比对完成 */ + /** 交易对账文件是否比对完成 */ @DbColumn(comment = "明细对账单比对") - private boolean detailCompare; - - /** 汇总对账文件是否下载成功 */ - @DbColumn(comment = "汇总对账单下载") - private boolean totalDown; - - /** 汇总是否比对完成 */ - @DbColumn(comment = "汇总对账单比对") - private boolean totalCompare; + private boolean compare; /** - * 对账结果 + * 交易对账结果 * @see ReconcileResultEnum */ @DbColumn(comment = "对账结果") diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/order/reconcile/entity/ReconcileDetail.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/order/reconcile/entity/ReconcileTradeDetail.java similarity index 82% rename from daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/order/reconcile/entity/ReconcileDetail.java rename to daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/order/reconcile/entity/ReconcileTradeDetail.java index ce0120561..4c580c60c 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/order/reconcile/entity/ReconcileDetail.java +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/order/reconcile/entity/ReconcileTradeDetail.java @@ -4,7 +4,7 @@ import cn.bootx.platform.common.core.function.EntityBaseFunction; import cn.bootx.platform.common.mybatisplus.base.MpCreateEntity; import cn.bootx.platform.daxpay.service.code.PaymentTypeEnum; import cn.bootx.platform.daxpay.service.core.order.reconcile.conver.ReconcileConvert; -import cn.bootx.platform.daxpay.service.dto.order.reconcile.ReconcileDetailDto; +import cn.bootx.platform.daxpay.service.dto.order.reconcile.ReconcileTradeDetailDto; import cn.bootx.table.modify.annotation.DbColumn; import cn.bootx.table.modify.annotation.DbTable; import com.baomidou.mybatisplus.annotation.TableName; @@ -15,16 +15,16 @@ import lombok.experimental.Accessors; import java.time.LocalDateTime; /** - * 通用支付对账记录, 从三方系统下载的交易记录 + * 对账-第三方交易明细, 从三方系统下载的交易记录 * @author xxm * @since 2024/1/18 */ @EqualsAndHashCode(callSuper = true) @Data @Accessors(chain = true) -@DbTable(comment = "支付对账记录") -@TableName("pay_reconcile_detail") -public class ReconcileDetail extends MpCreateEntity implements EntityBaseFunction { +@DbTable(comment = "对账-第三方交易明细") +@TableName("pay_reconcile_trade_detail") +public class ReconcileTradeDetail extends MpCreateEntity implements EntityBaseFunction { /** 关联对账订单ID */ @DbColumn(comment = "关联对账订单ID") @@ -59,7 +59,7 @@ public class ReconcileDetail extends MpCreateEntity implements EntityBaseFunctio @Override - public ReconcileDetailDto toDto() { + public ReconcileTradeDetailDto toDto() { return ReconcileConvert.CONVERT.convert(this); } } diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/order/reconcile/service/ReconcileDiffService.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/order/reconcile/service/ReconcileDiffService.java index ff1a96f9e..087f44363 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/order/reconcile/service/ReconcileDiffService.java +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/order/reconcile/service/ReconcileDiffService.java @@ -4,9 +4,9 @@ import cn.bootx.platform.common.core.exception.DataNotExistException; import cn.bootx.platform.common.core.rest.PageResult; import cn.bootx.platform.common.core.rest.param.PageParam; import cn.bootx.platform.common.mybatisplus.util.MpUtil; -import cn.bootx.platform.daxpay.service.core.order.reconcile.dao.ReconcileDiffRecordManager; -import cn.bootx.platform.daxpay.service.core.order.reconcile.entity.ReconcileDiffRecord; -import cn.bootx.platform.daxpay.service.dto.order.reconcile.ReconcileDiffRecordDto; +import cn.bootx.platform.daxpay.service.core.order.reconcile.dao.ReconcileDiffManager; +import cn.bootx.platform.daxpay.service.core.order.reconcile.entity.ReconcileDiff; +import cn.bootx.platform.daxpay.service.dto.order.reconcile.ReconcileDiffDto; import cn.bootx.platform.daxpay.service.param.reconcile.ReconcileDiffQuery; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -23,27 +23,26 @@ import java.util.List; @Service @RequiredArgsConstructor public class ReconcileDiffService { - private final ReconcileDiffRecordManager recordManager; - + private final ReconcileDiffManager recordManager; /** * 批量保存 */ - public void saveAll(List diffRecords) { + public void saveAll(List diffRecords) { recordManager.saveAll(diffRecords); } /** * 分页查询 */ - public PageResult page(PageParam pageParam, ReconcileDiffQuery query) { + public PageResult page(PageParam pageParam, ReconcileDiffQuery query) { return MpUtil.convert2DtoPageResult(recordManager.page(pageParam, query)); } /** * 详情查询 */ - public ReconcileDiffRecordDto findById(Long id) { - return recordManager.findById(id).map(ReconcileDiffRecord::toDto).orElseThrow(() -> new DataNotExistException("不存在的对账差异单")); + public ReconcileDiffDto findById(Long id) { + return recordManager.findById(id).map(ReconcileDiff::toDto).orElseThrow(() -> new DataNotExistException("不存在的对账差异单")); } } diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/order/reconcile/service/ReconcileQueryService.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/order/reconcile/service/ReconcileQueryService.java index d435dcce2..c22e64f02 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/order/reconcile/service/ReconcileQueryService.java +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/order/reconcile/service/ReconcileQueryService.java @@ -4,12 +4,12 @@ import cn.bootx.platform.common.core.exception.DataNotExistException; import cn.bootx.platform.common.core.rest.PageResult; import cn.bootx.platform.common.core.rest.param.PageParam; import cn.bootx.platform.common.mybatisplus.util.MpUtil; -import cn.bootx.platform.daxpay.service.core.order.reconcile.dao.ReconcileDetailManager; import cn.bootx.platform.daxpay.service.core.order.reconcile.dao.ReconcileOrderManager; -import cn.bootx.platform.daxpay.service.core.order.reconcile.entity.ReconcileDetail; +import cn.bootx.platform.daxpay.service.core.order.reconcile.dao.ReconcileTradeDetailManager; import cn.bootx.platform.daxpay.service.core.order.reconcile.entity.ReconcileOrder; -import cn.bootx.platform.daxpay.service.dto.order.reconcile.ReconcileDetailDto; +import cn.bootx.platform.daxpay.service.core.order.reconcile.entity.ReconcileTradeDetail; import cn.bootx.platform.daxpay.service.dto.order.reconcile.ReconcileOrderDto; +import cn.bootx.platform.daxpay.service.dto.order.reconcile.ReconcileTradeDetailDto; import cn.bootx.platform.daxpay.service.param.reconcile.ReconcileDetailQuery; import cn.bootx.platform.daxpay.service.param.reconcile.ReconcileOrderQuery; import lombok.RequiredArgsConstructor; @@ -26,7 +26,7 @@ import org.springframework.stereotype.Service; @RequiredArgsConstructor public class ReconcileQueryService { private final ReconcileOrderManager orderManager; - private final ReconcileDetailManager detailManager; + private final ReconcileTradeDetailManager detailManager; /** * 分页 @@ -46,16 +46,15 @@ public class ReconcileQueryService { /** * 明细分页 */ - public PageResult pageDetail(PageParam pageParam, ReconcileDetailQuery query){ + public PageResult pageDetail(PageParam pageParam, ReconcileDetailQuery query){ return MpUtil.convert2DtoPageResult(detailManager.page(pageParam, query)); } /** * 明细详情 */ - public ReconcileDetailDto findDetailById(Long id){ - return detailManager.findById(id).map(ReconcileDetail::toDto) + public ReconcileTradeDetailDto findDetailById(Long id){ + return detailManager.findById(id).map(ReconcileTradeDetail::toDto) .orElseThrow(()->new DataNotExistException("对账详情不存在")); } - } 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 new file mode 100644 index 000000000..dc4746de5 --- /dev/null +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/reconcile/service/ReconcileAssistService.java @@ -0,0 +1,201 @@ +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.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; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.function.Function; +import java.util.stream.Collectors; + +/** + * 对账支撑服务 + * @author xxm + * @since 2024/5/4 + */ +@Slf4j +@Service +@RequiredArgsConstructor +public class ReconcileAssistService { + + private final PayOrderManager payOrderManager; + + private final RefundOrderManager refundOrderManager; + + + /** + * 获取通用对账对象, 将支付/退款订单转换为对账对象 + */ + public List getGeneralTradeInfoList(ReconcileOrder reconcileOrder){ + List generalTradeInfoList = new ArrayList<>(); + // 查询流水 + LocalDateTime localDateTime = LocalDateTimeUtil.date2DateTime(reconcileOrder.getDate()); + LocalDateTime start = LocalDateTimeUtil.beginOfDay(localDateTime); + 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); + for (PayOrder payOrder : payOrders) { + generalTradeInfoList.add(new GeneralTradeInfo() + .setTitle(payOrder.getTitle()) + .setTradeNo(payOrder.getOrderNo()) + .setOutTradeNo(payOrder.getOutOrderNo()) + .setFinishTime(payOrder.getPayTime()) + .setType(PaymentTypeEnum.PAY.getCode()) + .setAmount(payOrder.getAmount()) + ); + } + for (RefundOrder refundOrder : refundOrders) { + generalTradeInfoList.add(new GeneralTradeInfo() + .setTitle(refundOrder.getTitle()) + .setTradeNo(refundOrder.getOrderNo()) + .setOutTradeNo(refundOrder.getOutOrderNo()) + .setFinishTime(refundOrder.getFinishTime()) + .setType(PaymentTypeEnum.REFUND.getCode()) + .setAmount(refundOrder.getAmount())); + } + return generalTradeInfoList; + } + + /** + * 比对生成对账差异单 + * 1. 远程有, 本地无 + * 2. 远程无, 本地有 + * 3. 远程有, 本地有, 但状态不一致 + * + * @param reconcileOrder 对账单 + * @param localTrades 本地交易订单 + * @param outDetails 远程对账明细 + */ + public List generateDiffRecord(ReconcileOrder reconcileOrder, + List localTrades, + List outDetails){ + if (CollUtil.isEmpty(outDetails) || CollUtil.isEmpty(localTrades)){ + return new ArrayList<>(); + } + // 差异内容 + List diffRecords = new ArrayList<>(); + + // 三方对账订单 + Map outDetailMap = outDetails.stream() + .collect(Collectors.toMap(ReconcileTradeDetail::getTradeNo, Function.identity(), CollectorsFunction::retainLatest)); + // 本地订单记录 + Map localTradeMap = localTrades.stream() + .collect(Collectors.toMap(GeneralTradeInfo::getTradeNo, Function.identity(), CollectorsFunction::retainLatest)); + // 对账与比对 + for (ReconcileTradeDetail outDetail : outDetails) { + // 判断本地有没有记录, 流水没有记录查询本地订单 + GeneralTradeInfo localTrade = localTradeMap.get(outDetail.getTradeNo()); + if (Objects.isNull(localTrade)){ + log.info("本地订单不存在: {}", outDetail.getTradeNo()); + ReconcileDiff diffRecord = new ReconcileDiff() + .setDiffType(ReconcileDiffTypeEnum.LOCAL_NOT_EXISTS.getCode()) + .setTradeNo(outDetail.getTradeNo()) + .setDetailId(outDetail.getId()) + .setReconcileId(reconcileOrder.getId()) + .setTitle(outDetail.getTitle()) + .setOrderType(outDetail.getType()) + .setOutOrderNo(outDetail.getOutTradeNo()) + .setOutAmount(outDetail.getAmount()) + .setTradeTime(outDetail.getTradeTime()); + diffRecords.add(diffRecord); + continue; + } + // 如果远程和本地都存在, 比对差异 + List reconcileDiffs = this.reconcileDiff(outDetail, localTrade); + if (CollUtil.isNotEmpty(reconcileDiffs)) { + ReconcileDiff diffRecord = new ReconcileDiff() + .setReconcileId(reconcileOrder.getId()) + .setDetailId(outDetail.getId()) + .setDiffType(ReconcileDiffTypeEnum.NOT_MATCH.getCode()) + .setTradeNo(outDetail.getTradeNo()) + .setTitle(outDetail.getTitle()) + .setOrderType(outDetail.getType()) + .setOutOrderNo(outDetail.getOutTradeNo()) + .setOutAmount(outDetail.getAmount()) + .setAmount(localTrade.getAmount()) + .setDiffs(reconcileDiffs) + .setTradeTime(outDetail.getTradeTime()); + diffRecords.add(diffRecord); + } + } + // 本地与对账单比对, 找出本地有, 远程没有的记录 + for (GeneralTradeInfo localTrade : localTrades) { + ReconcileTradeDetail outDetail = outDetailMap.get(localTrade.getTradeNo()); + if (Objects.isNull(outDetail)){ + ReconcileDiff diffRecord = new ReconcileDiff() + .setDiffType(ReconcileDiffTypeEnum.LOCAL_NOT_EXISTS.getCode()) + .setTradeNo(localTrade.getTradeNo()) + .setReconcileId(reconcileOrder.getId()) + .setDetailId(null) + .setTitle(localTrade.getTitle()) + .setOrderType(localTrade.getType()) + .setOutOrderNo(localTrade.getOutTradeNo()) + .setAmount(localTrade.getAmount()) + .setTradeTime(localTrade.getFinishTime()); + diffRecords.add(diffRecord); + log.info("远程订单不存在: {}", localTrade.getTradeNo()); + continue; + } + } + return diffRecords; + } + + /** + * 判断订单之间存在哪些差异 + * @param outDetail 下载的对账订单 + * @param localTrade 本地交易订单 + */ + private List reconcileDiff(ReconcileTradeDetail outDetail, GeneralTradeInfo localTrade){ + List diffs = new ArrayList<>(); + + // 判断类型是否相同 + if (Objects.equals(outDetail.getType(), ReconcileTradeEnum.PAY.getCode()) + && !Objects.equals(localTrade.getType(), PaymentTypeEnum.PAY.getCode())){ + log.warn("订单类型不一致: {},{}", outDetail.getType(), localTrade.getType()); + diffs.add(new cn.bootx.platform.daxpay.service.core.payment.reconcile.domain.ReconcileDiff().setFieldName("订单类型").setLocalValue(outDetail.getType()).setOutValue(localTrade.getType())); + } + if (Objects.equals(outDetail.getType(), ReconcileTradeEnum.REFUND.getCode()) + && !Objects.equals(localTrade.getType(), PaymentTypeEnum.REFUND.getCode())){ + log.warn("订单类型不一致: {},{}", outDetail.getType(), localTrade.getType()); + diffs.add(new cn.bootx.platform.daxpay.service.core.payment.reconcile.domain.ReconcileDiff().setFieldName("订单类型").setLocalValue(outDetail.getType()).setOutValue(localTrade.getType())); + } + + // 判断名称是否一致 + if (!Objects.equals(outDetail.getTitle(), localTrade.getTitle())){ + log.warn("订单名称不一致: {},{}", outDetail.getTitle(), localTrade.getTitle()); + diffs.add(new cn.bootx.platform.daxpay.service.core.payment.reconcile.domain.ReconcileDiff().setFieldName("订单名称").setLocalValue(outDetail.getTitle()).setOutValue(localTrade.getTitle())); + } + + // 判断金额是否一致 + if (!Objects.equals(outDetail.getAmount(), localTrade.getAmount())){ + log.warn("订单金额不一致: {},{}", outDetail.getAmount(), localTrade.getAmount()); + diffs.add(new cn.bootx.platform.daxpay.service.core.payment.reconcile.domain.ReconcileDiff().setFieldName("订单金额") + .setLocalValue(String.valueOf(outDetail.getAmount())) + .setOutValue(String.valueOf(localTrade.getAmount()))); + } + return diffs; + } + +} diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/reconcile/service/ReconcileService.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/reconcile/service/ReconcileService.java index 71ec68b76..47ea2fbb7 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/reconcile/service/ReconcileService.java +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/reconcile/service/ReconcileService.java @@ -1,51 +1,46 @@ package cn.bootx.platform.daxpay.service.core.payment.reconcile.service; import cn.bootx.platform.common.core.exception.DataNotExistException; -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.exception.pay.PayFailureException; -import cn.bootx.platform.daxpay.service.code.PaymentTypeEnum; -import cn.bootx.platform.daxpay.service.code.ReconcileDiffTypeEnum; +import cn.bootx.platform.daxpay.service.code.ReconcileFileTypeEnum; import cn.bootx.platform.daxpay.service.code.ReconcileResultEnum; import cn.bootx.platform.daxpay.service.common.local.PaymentContextLocal; -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.dao.ReconcileDetailManager; +import cn.bootx.platform.daxpay.service.core.order.reconcile.dao.ReconcileFileManager; +import cn.bootx.platform.daxpay.service.core.order.reconcile.dao.ReconcileTradeDetailManager; import cn.bootx.platform.daxpay.service.core.order.reconcile.dao.ReconcileOrderManager; -import cn.bootx.platform.daxpay.service.core.order.reconcile.entity.ReconcileDetail; -import cn.bootx.platform.daxpay.service.core.order.reconcile.entity.ReconcileDiffRecord; +import cn.bootx.platform.daxpay.service.core.order.reconcile.entity.ReconcileFile; +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.service.ReconcileDiffService; import cn.bootx.platform.daxpay.service.core.order.reconcile.service.ReconcileOrderService; -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; -import cn.bootx.platform.daxpay.service.core.payment.reconcile.domain.ReconcileDiff; import cn.bootx.platform.daxpay.service.core.payment.reconcile.factory.ReconcileStrategyFactory; import cn.bootx.platform.daxpay.service.func.AbsReconcileStrategy; +import cn.bootx.platform.daxpay.service.param.reconcile.ReconcileUploadParam; import cn.bootx.platform.daxpay.util.OrderNoGenerateUtil; +import cn.hutool.core.util.CharsetUtil; import lombok.RequiredArgsConstructor; +import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j; +import org.dromara.x.file.storage.core.FileInfo; +import org.dromara.x.file.storage.core.FileStorageService; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Propagation; import org.springframework.transaction.annotation.Transactional; import org.springframework.web.multipart.MultipartFile; +import java.net.URLEncoder; import java.time.LocalDate; -import java.time.LocalDateTime; -import java.util.ArrayList; import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.function.Function; -import java.util.stream.Collectors; /** - * 对账服务 + * 对账服务, * @author xxm * @since 2024/1/17 */ @@ -59,11 +54,13 @@ public class ReconcileService { private final ReconcileOrderManager reconcileOrderManager; - private final ReconcileDetailManager reconcileDetailManager; + private final ReconcileTradeDetailManager reconcileTradeDetailManager; - private final PayOrderManager payOrderManager; + private final ReconcileAssistService reconcileAssistService; - private final RefundOrderManager refundOrderManager; + private final ReconcileFileManager reconcileFileManager; + + private final FileStorageService fileStorageService; /** * 创建对账订单 @@ -88,11 +85,11 @@ public class ReconcileService { } /** - * 下载对账单并进行保存 + * 下载交易对账单并进行保存 */ public void downAndSave(ReconcileOrder reconcileOrder) { // 如果对账单已经存在 - if (reconcileOrder.isDetailDown() && reconcileOrder.isTotalDown()){ + if (reconcileOrder.isDownOrUpload()){ throw new PayFailureException("对账单文件已经下载或上传"); } // 将对账订单写入到上下文中 @@ -103,8 +100,7 @@ public class ReconcileService { reconcileStrategy.doBeforeHandler(); try { reconcileStrategy.downAndSave(); - reconcileOrder.setDetailDown(true) - .setTotalDown(true) + reconcileOrder.setDownOrUpload(true) .setErrorMsg(null); reconcileOrderService.update(reconcileOrder); } catch (Exception e) { @@ -115,29 +111,29 @@ public class ReconcileService { throw new RuntimeException(e); } // 保存转换后的通用结构对账单 - List reconcileDetails = PaymentContextLocal.get() + List reconcileTradeDetails = PaymentContextLocal.get() .getReconcileInfo() - .getReconcileDetails(); - reconcileDetailManager.saveAll(reconcileDetails); + .getReconcileTradeDetails(); + reconcileTradeDetailManager.saveAll(reconcileTradeDetails); } /** - * 手动传输对账单 - * @param id 对账单ID - * @param file 文件 + * 手动传输交易对账单 */ - public void upload(Long id, MultipartFile file) { - ReconcileOrder reconcileOrder = reconcileOrderService.findById(id) + public void upload(ReconcileUploadParam param, MultipartFile file) { + ReconcileOrder reconcileOrder = reconcileOrderService.findById(param.getId()) .orElseThrow(() -> new DataNotExistException("未找到对账订单")); // 将对账订单写入到上下文中 PaymentContextLocal.get().getReconcileInfo().setReconcileOrder(reconcileOrder); AbsReconcileStrategy reconcileStrategy = ReconcileStrategyFactory.create(reconcileOrder.getChannel()); reconcileStrategy.setRecordOrder(reconcileOrder); reconcileStrategy.doBeforeHandler(); + + // 上传类型 + ReconcileFileTypeEnum fileType = ReconcileFileTypeEnum.findByCode(param.getFileType()); try { - reconcileStrategy.upload(file); - reconcileOrder.setDownOrUpload(true) - .setErrorMsg(null); + reconcileStrategy.upload(file, fileType); + reconcileOrder.setErrorMsg(null); reconcileOrderService.update(reconcileOrder); } catch (Exception e) { log.error("上传对账单异常", e); @@ -146,25 +142,25 @@ public class ReconcileService { throw new RuntimeException(e); } // 保存转换后的通用结构对账单 - List reconcileDetails = PaymentContextLocal.get() + List reconcileTradeDetails = PaymentContextLocal.get() .getReconcileInfo() - .getReconcileDetails(); - reconcileDetailManager.saveAll(reconcileDetails); + .getReconcileTradeDetails(); + reconcileTradeDetailManager.saveAll(reconcileTradeDetails); } /** - * 对账单比对 + * 对账单明细比对 */ @Transactional(rollbackFor = Exception.class) - public void compareDetail(Long reconcileOrderId){ + public void compare(Long reconcileOrderId){ ReconcileOrder reconcileOrder = reconcileOrderService.findById(reconcileOrderId) .orElseThrow(() -> new DataNotExistException("未找到对账订单")); - this.compareDetail(reconcileOrder); + this.compare(reconcileOrder); } /** - * 对账单比对 + * 交易对账比对 */ - public void compareDetail(ReconcileOrder reconcileOrder){ + public void compare(ReconcileOrder reconcileOrder){ // 判断是否已经下载了对账单明细 if (!reconcileOrder.isDownOrUpload()){ throw new PayFailureException("请先下载对账单"); @@ -174,7 +170,7 @@ public class ReconcileService { throw new PayFailureException("对账单比对已经完成"); } // 查询对账单 - List reconcileDetails = reconcileDetailManager.findAllByReconcileId(reconcileOrder.getId()); + List reconcileTradeDetails = reconcileTradeDetailManager.findAllByReconcileId(reconcileOrder.getId()); // 构建对账策略 AbsReconcileStrategy reconcileStrategy = ReconcileStrategyFactory.create(reconcileOrder.getChannel()); // 初始化参数 @@ -182,8 +178,8 @@ public class ReconcileService { try { // 执行比对任务, 获取对账差异记录并保存 - List generalTradeInfo = this.getGeneralTradeInfoList(reconcileOrder); - List diffRecords = this.generateDiffRecord(reconcileOrder, generalTradeInfo,reconcileDetails); + List generalTradeInfo = reconcileAssistService.getGeneralTradeInfoList(reconcileOrder); + List diffRecords = reconcileAssistService.generateDiffRecord(reconcileOrder, generalTradeInfo, reconcileTradeDetails); // 判断是否有差异 if (CollUtil.isNotEmpty(diffRecords)){ reconcileOrder.setResult(ReconcileResultEnum.INCONSISTENT.getCode()); @@ -200,174 +196,46 @@ public class ReconcileService { } /** - * 下载原始对账单文件 + * 下载原始对交易对账单文件 */ - public void downOriginal(Long id){ + @SneakyThrows + public ResponseEntity downOriginal(Long id){ + if (!reconcileOrderManager.existedById(id)) { + throw new DataNotExistException("未找到对账订单"); + } + // 获取对账单文件ID + List reconcileFiles = reconcileFileManager.findAllByReconcileId(id); + if (CollUtil.isEmpty(reconcileFiles)){ + throw new DataNotExistException("未找到对账文件"); + } + // 查询文件 + FileInfo fileInfo = fileStorageService.getFileInfoByUrl(String.valueOf(reconcileFiles.get(0).getFileId())); + byte[] bytes = fileStorageService.download(fileInfo).bytes(); + // 设置header信息 + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.APPLICATION_OCTET_STREAM); + String fileName = fileInfo.getOriginalFilename(); + headers.setContentDispositionFormData("attachment", URLEncoder.encode(fileName, CharsetUtil.UTF_8)); + return new ResponseEntity<>(bytes,headers, HttpStatus.OK); } /** - * 下载基于原始对账单数据转换的对账单文件, 例如csv, json方式 + * 下载基于原始交易对账单数据转换的对账单文件, 例如csv, json方式 */ - public void downTransfer(Long id){ - ReconcileOrder reconcileOrderOriginal = reconcileOrderService.findById(id) + public void downOriginal2Csv(Long id){ + ReconcileOrder reconcileOrder = reconcileOrderService.findById(id) .orElseThrow(() -> new DataNotExistException("未找到对账订单")); - // 获取 + // 查询对账-第三方交易明细 + List reconcileTradeDetails = reconcileTradeDetailManager.findAllByReconcileId(reconcileOrder.getId()); + + // 转换为csv文件 } /** - * 获取通用对账对象, 将支付/退款订单转换为对账对象 + * 下载对账单(本系统中的订单) */ - private List getGeneralTradeInfoList(ReconcileOrder reconcileOrder){ - List generalTradeInfoList = new ArrayList<>(); - // 查询流水 - LocalDateTime localDateTime = LocalDateTimeUtil.date2DateTime(reconcileOrder.getDate()); - LocalDateTime start = LocalDateTimeUtil.beginOfDay(localDateTime); - 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); - for (PayOrder payOrder : payOrders) { - generalTradeInfoList.add(new GeneralTradeInfo() - .setTitle(payOrder.getTitle()) - .setTradeNo(payOrder.getOrderNo()) - .setOutTradeNo(payOrder.getOutOrderNo()) - .setFinishTime(payOrder.getPayTime()) - .setType(PaymentTypeEnum.PAY.getCode()) - .setAmount(payOrder.getAmount()) - ); - } - for (RefundOrder refundOrder : refundOrders) { - generalTradeInfoList.add(new GeneralTradeInfo() - .setTitle(refundOrder.getTitle()) - .setTradeNo(refundOrder.getOrderNo()) - .setOutTradeNo(refundOrder.getOutOrderNo()) - .setFinishTime(refundOrder.getFinishTime()) - .setType(PaymentTypeEnum.REFUND.getCode()) - .setAmount(refundOrder.getAmount())); - } - return generalTradeInfoList; - } - - /** - * 比对生成对账差异单 - * 1. 远程有, 本地无 - * 2. 远程无, 本地有 - * 3. 远程有, 本地有, 但状态不一致 - * - * @param reconcileOrder 对账单 - * @param localTrades 本地交易订单 - * @param outDetails 远程对账明细 - */ - private List generateDiffRecord(ReconcileOrder reconcileOrder, - List localTrades, - List outDetails){ - if (CollUtil.isEmpty(outDetails) || CollUtil.isEmpty(localTrades)){ - return new ArrayList<>(); - } - // 差异内容 - List diffRecords = new ArrayList<>(); - - // 三方对账订单 - Map outDetailMap = outDetails.stream() - .collect(Collectors.toMap(ReconcileDetail::getTradeNo, Function.identity(), CollectorsFunction::retainLatest)); - // 本地订单记录 - Map localTradeMap = localTrades.stream() - .collect(Collectors.toMap(GeneralTradeInfo::getTradeNo, Function.identity(), CollectorsFunction::retainLatest)); - // 对账与比对 - for (ReconcileDetail outDetail : outDetails) { - // 判断本地有没有记录, 流水没有记录查询本地订单 - GeneralTradeInfo localTrade = localTradeMap.get(outDetail.getTradeNo()); - if (Objects.isNull(localTrade)){ - log.info("本地订单不存在: {}", outDetail.getTradeNo()); - ReconcileDiffRecord diffRecord = new ReconcileDiffRecord() - .setDiffType(ReconcileDiffTypeEnum.LOCAL_NOT_EXISTS.getCode()) - .setTradeNo(outDetail.getTradeNo()) - .setDetailId(outDetail.getId()) - .setReconcileId(reconcileOrder.getId()) - .setTitle(outDetail.getTitle()) - .setOrderType(outDetail.getType()) - .setOutOrderNo(outDetail.getOutTradeNo()) - .setOutAmount(outDetail.getAmount()) - .setTradeTime(outDetail.getTradeTime()); - diffRecords.add(diffRecord); - continue; - } - // 如果远程和本地都存在, 比对差异 - List reconcileDiffs = this.reconcileDiff(outDetail, localTrade); - if (CollUtil.isNotEmpty(reconcileDiffs)) { - ReconcileDiffRecord diffRecord = new ReconcileDiffRecord() - .setReconcileId(reconcileOrder.getId()) - .setDetailId(outDetail.getId()) - .setDiffType(ReconcileDiffTypeEnum.NOT_MATCH.getCode()) - .setTradeNo(outDetail.getTradeNo()) - .setTitle(outDetail.getTitle()) - .setOrderType(outDetail.getType()) - .setOutOrderNo(outDetail.getOutTradeNo()) - .setOutAmount(outDetail.getAmount()) - .setAmount(localTrade.getAmount()) - .setDiffs(reconcileDiffs) - .setTradeTime(outDetail.getTradeTime()); - diffRecords.add(diffRecord); - } - } - // 本地与对账单比对, 找出本地有, 远程没有的记录 - for (GeneralTradeInfo localTrade : localTrades) { - ReconcileDetail outDetail = outDetailMap.get(localTrade.getTradeNo()); - if (Objects.isNull(outDetail)){ - ReconcileDiffRecord diffRecord = new ReconcileDiffRecord() - .setDiffType(ReconcileDiffTypeEnum.LOCAL_NOT_EXISTS.getCode()) - .setTradeNo(localTrade.getTradeNo()) - .setReconcileId(reconcileOrder.getId()) - .setDetailId(null) - .setTitle(localTrade.getTitle()) - .setOrderType(localTrade.getType()) - .setOutOrderNo(localTrade.getOutTradeNo()) - .setAmount(localTrade.getAmount()) - .setTradeTime(localTrade.getFinishTime()); - diffRecords.add(diffRecord); - log.info("远程订单不存在: {}", localTrade.getTradeNo()); - continue; - } - } - return diffRecords; - } - - /** - * 判断订单之间存在哪些差异 - * @param outDetail 下载的对账订单 - * @param localTrade 本地交易订单 - */ - private List reconcileDiff(ReconcileDetail outDetail, GeneralTradeInfo localTrade){ - List diffs = new ArrayList<>(); - - // 判断类型是否相同 - if (Objects.equals(outDetail.getType(), ReconcileTradeEnum.PAY.getCode()) - && !Objects.equals(localTrade.getType(), PaymentTypeEnum.PAY.getCode())){ - log.warn("订单类型不一致: {},{}", outDetail.getType(), localTrade.getType()); - diffs.add(new ReconcileDiff().setFieldName("订单类型").setLocalValue(outDetail.getType()).setOutValue(localTrade.getType())); - } - if (Objects.equals(outDetail.getType(), ReconcileTradeEnum.REFUND.getCode()) - && !Objects.equals(localTrade.getType(), PaymentTypeEnum.REFUND.getCode())){ - log.warn("订单类型不一致: {},{}", outDetail.getType(), localTrade.getType()); - diffs.add(new ReconcileDiff().setFieldName("订单类型").setLocalValue(outDetail.getType()).setOutValue(localTrade.getType())); - } - - // 判断名称是否一致 - if (!Objects.equals(outDetail.getTitle(), localTrade.getTitle())){ - log.warn("订单名称不一致: {},{}", outDetail.getTitle(), localTrade.getTitle()); - diffs.add(new ReconcileDiff().setFieldName("订单名称").setLocalValue(outDetail.getTitle()).setOutValue(localTrade.getTitle())); - } - - // 判断金额是否一致 - if (!Objects.equals(outDetail.getAmount(), localTrade.getAmount())){ - log.warn("订单金额不一致: {},{}", outDetail.getAmount(), localTrade.getAmount()); - diffs.add(new ReconcileDiff().setFieldName("订单金额") - .setLocalValue(String.valueOf(outDetail.getAmount())) - .setOutValue(String.valueOf(localTrade.getAmount()))); - } - return diffs; + public void downLocal(Long id){ } } 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 e821ec687..47db08151 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 @@ -2,6 +2,7 @@ package cn.bootx.platform.daxpay.service.core.payment.reconcile.strategy; import cn.bootx.platform.common.core.util.LocalDateTimeUtil; import cn.bootx.platform.daxpay.code.PayChannelEnum; +import cn.bootx.platform.daxpay.service.code.ReconcileFileTypeEnum; import cn.bootx.platform.daxpay.service.core.channel.alipay.entity.AliPayConfig; import cn.bootx.platform.daxpay.service.core.channel.alipay.service.AliPayConfigService; import cn.bootx.platform.daxpay.service.core.channel.alipay.service.AliPayReconcileService; @@ -55,7 +56,7 @@ public class AlipayReconcileStrategy extends AbsReconcileStrategy { */ @SneakyThrows @Override - public void upload(MultipartFile file) { + public void upload(MultipartFile file, ReconcileFileTypeEnum fileType) { reconcileService.upload(file.getBytes()); } diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/reconcile/strategy/UnionPayReconcileStrategy.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/reconcile/strategy/UnionPayReconcileStrategy.java index 9ae3030fb..19cfbdef7 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/reconcile/strategy/UnionPayReconcileStrategy.java +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/core/payment/reconcile/strategy/UnionPayReconcileStrategy.java @@ -1,6 +1,7 @@ package cn.bootx.platform.daxpay.service.core.payment.reconcile.strategy; import cn.bootx.platform.daxpay.code.PayChannelEnum; +import cn.bootx.platform.daxpay.service.code.ReconcileFileTypeEnum; import cn.bootx.platform.daxpay.service.core.channel.union.entity.UnionPayConfig; import cn.bootx.platform.daxpay.service.core.channel.union.service.UnionPayConfigService; import cn.bootx.platform.daxpay.service.core.channel.union.service.UnionPayReconcileService; @@ -61,7 +62,7 @@ public class UnionPayReconcileStrategy extends AbsReconcileStrategy { */ @SneakyThrows @Override - public void upload(MultipartFile file) { + public void upload(MultipartFile file, ReconcileFileTypeEnum fileType) { reconcileService.upload(file.getBytes()); } @@ -71,6 +72,6 @@ public class UnionPayReconcileStrategy extends AbsReconcileStrategy { @Override public void downAndSave() { Date date = DateUtil.date(this.getRecordOrder().getDate()); - reconcileService.downAndSave(this.getRecordOrder(),date, this.unionPayKit); + reconcileService.downAndSave(this.getRecordOrder(), date, this.unionPayKit); } } 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 85aad30cb..fe03093f3 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 @@ -2,10 +2,10 @@ package cn.bootx.platform.daxpay.service.core.payment.reconcile.strategy; import cn.bootx.platform.common.core.util.LocalDateTimeUtil; import cn.bootx.platform.daxpay.code.PayChannelEnum; +import cn.bootx.platform.daxpay.service.code.ReconcileFileTypeEnum; import cn.bootx.platform.daxpay.service.core.channel.wechat.entity.WeChatPayConfig; 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.pay.dao.PayOrderManager; import cn.bootx.platform.daxpay.service.func.AbsReconcileStrategy; import cn.hutool.core.date.DatePattern; import lombok.RequiredArgsConstructor; @@ -32,8 +32,6 @@ public class WechatPayReconcileStrategy extends AbsReconcileStrategy { private final WeChatPayConfigService weChatPayConfigService; - private final PayOrderManager payOrderManager; - private WeChatPayConfig config; /** @@ -59,7 +57,7 @@ public class WechatPayReconcileStrategy extends AbsReconcileStrategy { */ @SneakyThrows @Override - public void upload(MultipartFile file) { + public void upload(MultipartFile file, ReconcileFileTypeEnum fileType) { reconcileService.uploadBill(file.getBytes(),this.config); } @@ -68,8 +66,8 @@ public class WechatPayReconcileStrategy extends AbsReconcileStrategy { */ @Override public void downAndSave() { - String format = LocalDateTimeUtil.format(this.getRecordOrder().getDate(), DatePattern.PURE_DATE_PATTERN); - reconcileService.downAndSave(format, this.config); + String date = LocalDateTimeUtil.format(this.getRecordOrder().getDate(), DatePattern.PURE_DATE_PATTERN); + reconcileService.downAndSave(this.getRecordOrder(), date, this.config); } } diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/dto/order/reconcile/ReconcileDiffRecordDto.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/dto/order/reconcile/ReconcileDiffDto.java similarity index 86% rename from daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/dto/order/reconcile/ReconcileDiffRecordDto.java rename to daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/dto/order/reconcile/ReconcileDiffDto.java index dd2aeddff..68aa0fbf4 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/dto/order/reconcile/ReconcileDiffRecordDto.java +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/dto/order/reconcile/ReconcileDiffDto.java @@ -22,16 +22,24 @@ import java.util.List; @Data @Accessors(chain = true) @Schema(title = "对账差异单") -public class ReconcileDiffRecordDto extends BaseDto { +public class ReconcileDiffDto extends BaseDto { /** 对账单ID */ @Schema(description = "对账单ID") - private Long ReconcileId; + private Long reconcileId; + + /** 对账号 */ + @Schema(description = "对账号") + private String reconcileNo; /** 对账单明细ID */ @Schema(description = "对账单明细ID") private Long detailId; + /** 对账日期 */ + @Schema(description = "对账日期") + private LocalDateTime reconcileDate; + /** 本地交易号 */ @Schema(description = "本地交易号") private String tradeNo; @@ -61,7 +69,7 @@ public class ReconcileDiffRecordDto extends BaseDto { * @see ReconcileTradeEnum */ @Schema(description = "订单类型") - private String orderType; + private String tradeType; /** * 差异类型 diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/dto/order/reconcile/ReconcileDetailDto.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/dto/order/reconcile/ReconcileTradeDetailDto.java similarity index 95% rename from daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/dto/order/reconcile/ReconcileDetailDto.java rename to daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/dto/order/reconcile/ReconcileTradeDetailDto.java index 75113fa77..b16e6ea18 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/dto/order/reconcile/ReconcileDetailDto.java +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/dto/order/reconcile/ReconcileTradeDetailDto.java @@ -18,7 +18,7 @@ import java.time.LocalDateTime; @Data @Accessors(chain = true) @Schema(title = "对账订单详情") -public class ReconcileDetailDto extends BaseDto { +public class ReconcileTradeDetailDto extends BaseDto { /** 关联对账订单ID */ @Schema(description = "关联对账订单ID") 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 18bb249a3..74692c799 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,5 +1,6 @@ package cn.bootx.platform.daxpay.service.func; +import cn.bootx.platform.daxpay.service.code.ReconcileFileTypeEnum; import cn.bootx.platform.daxpay.service.core.order.reconcile.entity.ReconcileOrder; import lombok.Getter; import lombok.Setter; @@ -26,7 +27,7 @@ public abstract class AbsReconcileStrategy implements PayStrategy { /** * 上传对账单解析并保存 */ - public abstract void upload(MultipartFile file); + public abstract void upload(MultipartFile file, ReconcileFileTypeEnum fileType); /** * 下载对账单到本地进行保存 diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/param/reconcile/ReconcileUploadParam.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/param/reconcile/ReconcileUploadParam.java new file mode 100644 index 000000000..33c253087 --- /dev/null +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/param/reconcile/ReconcileUploadParam.java @@ -0,0 +1,30 @@ +package cn.bootx.platform.daxpay.service.param.reconcile; + +import cn.bootx.platform.daxpay.service.code.ReconcileFileTypeEnum; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.experimental.Accessors; + +import javax.validation.constraints.NotNull; + +/** + * 对账文件上传参数 + * @author xxm + * @since 2024/5/4 + */ +@Data +@Accessors(chain = true) +@Schema(title = "对账文件上传参数") +public class ReconcileUploadParam { + + @Schema(description = "对账订单ID") + @NotNull(message = "对账订单ID不能为空") + private Long id; + + /** + * @see ReconcileFileTypeEnum + */ + @Schema(description = "文件类型") + @NotNull(message = "文件类型不能为空") + private String fileType; +} diff --git a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/task/service/ReconcileTaskService.java b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/task/service/ReconcileTaskService.java index 017a2448e..e66e0d6e4 100644 --- a/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/task/service/ReconcileTaskService.java +++ b/daxpay-single/daxpay-single-service/src/main/java/cn/bootx/platform/daxpay/service/task/service/ReconcileTaskService.java @@ -30,7 +30,7 @@ public class ReconcileTaskService { // 2. 执行对账任务, 下载对账单并解析, 分别存储为原始数据和通用对账数据 reconcileService.downAndSave(reconcileOrder); - // 3. 执行账单比对, 生成差异单 + // 3. 执行账单明细比对, 生成差异单 reconcileService.compare(reconcileOrder); }