feat 支付对账单订单创建和一些转换处理

This commit is contained in:
bootx
2024-01-22 09:19:02 +08:00
parent 97ed6b7e25
commit 22a81487f6
29 changed files with 501 additions and 60 deletions

View File

@@ -63,13 +63,15 @@
- 2024-01-16: - 2024-01-16:
- [x] 支付单涉及退款状态同步逻辑 - [x] 支付单涉及退款状态同步逻辑
- 2024-01-17: - 2024-01-17:
- [x] 支付宝和微信支付对账下载接口 - [x] 支付宝和微信支付对账下载接口
- 2024-01-18: - 2024-01-21:
- [x] (对账) 微信对账文件解析 - [x] (对账) 微信对账文件解析
- [ ] (对账) 支付宝对账文件解析 - [x] (对账) 支付宝对账文件解析
- [ ] (对账) 对账策略类和定时任务 - [x] (对账) 对账策略类和定时任务
- [ ] (对账) 对账记录和明细保存 - [x] (对账) 对账记录和明细保存
- 2024-01-22:
- [ ] (对账) 通用结构对账结构转换
- [ ] (对账) 对账列表页、操作按钮(手动创建、执行、重试)
- **任务池** - **任务池**
- [ ] 微信退款状态不一致补偿 - [ ] 微信退款状态不一致补偿
- [ ] 接入支付网关的演示项目 - [ ] 接入支付网关的演示项目

View File

@@ -18,9 +18,9 @@ public enum PayStatusEnum {
PROGRESS("progress","支付中"), PROGRESS("progress","支付中"),
SUCCESS("success","成功"), SUCCESS("success","成功"),
CLOSE("close","支付关闭"), CLOSE("close","支付关闭"),
FAIL("fail","失败"),
PARTIAL_REFUND("partial_refund","部分退款"), PARTIAL_REFUND("partial_refund","部分退款"),
REFUNDED("refunded","全部退款"); REFUNDED("refunded","全部退款"),
FAIL("fail","失败");
/** 编码 */ /** 编码 */
private final String code; private final String code;

View File

@@ -70,17 +70,4 @@ public class TestController {
return Res.ok(name); return Res.ok(name);
} }
@Operation(summary = "下载支付宝对账单")
@GetMapping("/aliDownReconcile")
public ResResult<String> aliDownReconcile(String date){
alipayReconcileService.downAndSave(date);
return Res.ok();
}
@Operation(summary = "下载微信对账单")
@GetMapping("/wxDownReconcile")
public ResResult<Void> wxDownReconcile(String date){
wechatPayReconcileService.downAndSave(date,null);
return Res.ok();
}
} }

View File

@@ -36,4 +36,7 @@ public class PaymentContext {
/** 支付请求相关信息 */ /** 支付请求相关信息 */
private final RequestLocal request = new RequestLocal(); private final RequestLocal request = new RequestLocal();
/** 支付对账相关信息 */
private final ReconcileLocal reconcile = new ReconcileLocal();
} }

View File

@@ -0,0 +1,22 @@
package cn.bootx.platform.daxpay.service.common.context;
import cn.bootx.platform.daxpay.service.core.order.reconcile.entity.PayReconcileDetail;
import lombok.Data;
import lombok.experimental.Accessors;
import java.util.List;
/**
* 支付对账上下文信息
* @author xxm
* @since 2024/1/21
*/
@Data
@Accessors(chain = true)
public class ReconcileLocal {
/** */
private List<PayReconcileDetail> reconcileDetails;
}

View File

@@ -23,6 +23,18 @@ public final class PaymentContextLocal {
THREAD_LOCAL.set(paymentContext); THREAD_LOCAL.set(paymentContext);
} }
/**
* 不存在则进行赋值
*/
public static boolean setIfAbsent(PaymentContext paymentContext){
if (THREAD_LOCAL.get() == null){
set(paymentContext);
return true;
}
return false;
}
/** /**
* 获取 * 获取
*/ */

View File

@@ -0,0 +1,18 @@
package cn.bootx.platform.daxpay.service.core.channel.alipay.dao;
import cn.bootx.platform.common.mybatisplus.impl.BaseManager;
import cn.bootx.platform.daxpay.service.core.channel.alipay.entity.AliReconcileBillDetail;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Repository;
/**
*
* @author xxm
* @since 2024/1/21
*/
@Slf4j
@Repository
@RequiredArgsConstructor
public class AliReconcileBillDetailManager extends BaseManager<AliReconcileBillDetailMapper, AliReconcileBillDetail> {
}

View File

@@ -0,0 +1,14 @@
package cn.bootx.platform.daxpay.service.core.channel.alipay.dao;
import cn.bootx.platform.daxpay.service.core.channel.alipay.entity.AliReconcileBillDetail;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
/**
*
* @author xxm
* @since 2024/1/21
*/
@Mapper
public interface AliReconcileBillDetailMapper extends BaseMapper<AliReconcileBillDetail> {
}

View File

@@ -0,0 +1,18 @@
package cn.bootx.platform.daxpay.service.core.channel.alipay.dao;
import cn.bootx.platform.common.mybatisplus.impl.BaseManager;
import cn.bootx.platform.daxpay.service.core.channel.alipay.entity.AliReconcileBillTotal;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Repository;
/**
*
* @author xxm
* @since 2024/1/21
*/
@Slf4j
@Repository
@RequiredArgsConstructor
public class AliReconcileBillTotalManager extends BaseManager<AliReconcileBillTotalMapper,AliReconcileBillTotal> {
}

View File

@@ -0,0 +1,14 @@
package cn.bootx.platform.daxpay.service.core.channel.alipay.dao;
import cn.bootx.platform.daxpay.service.core.channel.alipay.entity.AliReconcileBillTotal;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
/**
*
* @author xxm
* @since 2024/1/21
*/
@Mapper
public interface AliReconcileBillTotalMapper extends BaseMapper<AliReconcileBillTotal> {
}

View File

@@ -1,61 +1,96 @@
package cn.bootx.platform.daxpay.service.core.channel.alipay.entity; package cn.bootx.platform.daxpay.service.core.channel.alipay.entity;
import cn.bootx.platform.common.mybatisplus.base.MpIdEntity;
import cn.bootx.table.modify.annotation.DbColumn;
import cn.bootx.table.modify.annotation.DbTable;
import cn.hutool.core.annotation.Alias; import cn.hutool.core.annotation.Alias;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data; import lombok.Data;
import lombok.EqualsAndHashCode;
/** /**
* 支付宝业务明细对账单 * 支付宝业务明细对账单
* @author xxm * @author xxm
* @since 2024/1/18 * @since 2024/1/18
*/ */
@EqualsAndHashCode(callSuper = true)
@Data @Data
public class AliReconcileBillDetail { @DbTable(comment = "支付宝业务明细对账单")
@TableName("pay_ali_reconcile_bill_detail")
public class AliReconcileBillDetail extends MpIdEntity {
/** 关联对账订单ID */
@DbColumn(comment = "关联对账订单ID")
private Long recordOrderId;
@Alias("支付宝交易号") @Alias("支付宝交易号")
@DbColumn(comment = "支付宝交易号")
private String tradeNo; private String tradeNo;
@Alias("商户订单号") @Alias("商户订单号")
@DbColumn(comment = "商户订单号")
private String outTradeNo; private String outTradeNo;
@Alias("业务类型") @Alias("业务类型")
@DbColumn(comment = "业务类型")
private String tradeType; private String tradeType;
@Alias("商品名称") @Alias("商品名称")
@DbColumn(comment = "商品名称")
private String subject; private String subject;
@Alias("完成时间") @Alias("完成时间")
@DbColumn(comment = "完成时间")
private String endTime; private String endTime;
@Alias("门店编号") @Alias("门店编号")
@DbColumn(comment = "门店编号")
private String storeId; private String storeId;
@Alias("门店名称") @Alias("门店名称")
@DbColumn(comment = "门店名称")
private String storeName; private String storeName;
@Alias("操作员") @Alias("操作员")
@DbColumn(comment = "操作员")
private String operator; private String operator;
@Alias("终端号") @Alias("终端号")
@DbColumn(comment = "终端号")
private String terminalId; private String terminalId;
@Alias("对方账户") @Alias("对方账户")
@DbColumn(comment = "对方账户")
private String otherAccount; private String otherAccount;
@Alias("订单金额(元)") @Alias("订单金额(元)")
@DbColumn(comment = "订单金额(元)")
private String orderAmount; private String orderAmount;
@Alias("商家实收(元)") @Alias("商家实收(元)")
@DbColumn(comment = "商家实收(元)")
private String realAmount; private String realAmount;
@Alias("支付宝红包(元)") @Alias("支付宝红包(元)")
@DbColumn(comment = "支付宝红包(元)")
private String alipayAmount; private String alipayAmount;
@Alias("集分宝(元)") @Alias("集分宝(元)")
@DbColumn(comment = "集分宝(元)")
private String jfbAmount; private String jfbAmount;
@Alias("支付宝优惠(元)") @Alias("支付宝优惠(元)")
@DbColumn(comment = "支付宝优惠(元)")
private String alipayDiscountAmount; private String alipayDiscountAmount;
@Alias("商家优惠(元)") @Alias("商家优惠(元)")
@DbColumn(comment = "商家优惠(元)")
private String discountAmount; private String discountAmount;
@Alias("券核销金额(元)") @Alias("券核销金额(元)")
@DbColumn(comment = "券核销金额(元)")
private String couponDiscountAmount; private String couponDiscountAmount;
@Alias("券名称") @Alias("券名称")
@DbColumn(comment = "券名称")
private String couponName; private String couponName;
@Alias("商家红包消费金额(元)") @Alias("商家红包消费金额(元)")
@DbColumn(comment = "商家红包消费金额(元)")
private String couponAmount; private String couponAmount;
@Alias("卡消费金额(元)") @Alias("卡消费金额(元)")
@DbColumn(comment = "卡消费金额(元)")
private String cardAmount; private String cardAmount;
@Alias("退款批次号/请求号") @Alias("退款批次号/请求号")
@DbColumn(comment = "退款批次号/请求号")
private String batchNo; private String batchNo;
@Alias("服务费(元)") @Alias("服务费(元)")
@DbColumn(comment = "服务费(元)")
private String serviceAmount; private String serviceAmount;
@Alias("分润(元)") @Alias("分润(元)")
@DbColumn(comment = "分润(元)")
private String splitAmount; private String splitAmount;
@Alias("备注") @Alias("备注")
@DbColumn(comment = "备注")
private String remark; private String remark;
} }

View File

@@ -1,5 +1,6 @@
package cn.bootx.platform.daxpay.service.core.channel.alipay.entity; package cn.bootx.platform.daxpay.service.core.channel.alipay.entity;
import cn.bootx.table.modify.annotation.DbColumn;
import cn.hutool.core.annotation.Alias; import cn.hutool.core.annotation.Alias;
import lombok.Data; import lombok.Data;
@@ -10,29 +11,44 @@ import lombok.Data;
*/ */
@Data @Data
public class AliReconcileBillTotal { public class AliReconcileBillTotal {
/** 关联对账订单ID */
@DbColumn(comment = "关联对账订单ID")
private Long recordOrderId;
@Alias("门店编号") @Alias("门店编号")
@DbColumn(comment = "门店编号")
private String storeId; private String storeId;
@Alias("门店名称") @Alias("门店名称")
@DbColumn(comment = "门店名称")
private String storeName; private String storeName;
@Alias("交易订单总笔数") @Alias("交易订单总笔数")
@DbColumn(comment = "交易订单总笔数")
private String totalNum; private String totalNum;
@Alias("退款订单总笔数") @Alias("退款订单总笔数")
@DbColumn(comment = "退款订单总笔数")
private String totalRefundNum; private String totalRefundNum;
@Alias("订单金额(元)") @Alias("订单金额(元)")
@DbColumn(comment = "订单金额(元)")
private String totalOrderAmount; private String totalOrderAmount;
@Alias("商家实收(元)") @Alias("商家实收(元)")
@DbColumn(comment = "商家实收(元)")
private String totalAmount; private String totalAmount;
@Alias("支付宝优惠(元)") @Alias("支付宝优惠(元)")
@DbColumn(comment = "支付宝优惠(元)")
private String totalDiscountAmount; private String totalDiscountAmount;
@Alias("商家优惠(元)") @Alias("商家优惠(元)")
@DbColumn(comment = "商家优惠(元)")
private String totalCouponAmount; private String totalCouponAmount;
// 卡消费金额(元) 服务费(元) 分润(元) 实收净额(元) // 卡消费金额(元) 服务费(元) 分润(元) 实收净额(元)
@Alias("卡消费金额(元)") @Alias("卡消费金额(元)")
@DbColumn(comment = "卡消费金额(元)")
private String totalConsumeAmount; private String totalConsumeAmount;
@Alias("服务费(元)") @Alias("服务费(元)")
@DbColumn(comment = "服务费(元)")
private String totalServiceAmount; private String totalServiceAmount;
@Alias("分润(元)") @Alias("分润(元)")
@DbColumn(comment = "分润(元)")
private String totalShareAmount; private String totalShareAmount;
@Alias("实收净额(元)") @Alias("实收净额(元)")
@DbColumn(comment = "实收净额(元)")
private String totalNetAmount; private String totalNetAmount;
} }

View File

@@ -2,9 +2,13 @@ package cn.bootx.platform.daxpay.service.core.channel.alipay.service;
import cn.bootx.platform.daxpay.exception.pay.PayFailureException; import cn.bootx.platform.daxpay.exception.pay.PayFailureException;
import cn.bootx.platform.daxpay.service.code.AliPayCode; import cn.bootx.platform.daxpay.service.code.AliPayCode;
import cn.bootx.platform.daxpay.service.common.local.PaymentContextLocal;
import cn.bootx.platform.daxpay.service.core.channel.alipay.dao.AliReconcileBillDetailManager;
import cn.bootx.platform.daxpay.service.core.channel.alipay.dao.AliReconcileBillTotalManager;
import cn.bootx.platform.daxpay.service.core.channel.alipay.entity.AliPayConfig;
import cn.bootx.platform.daxpay.service.core.channel.alipay.entity.AliReconcileBillDetail; 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.channel.alipay.entity.AliReconcileBillTotal;
import cn.bootx.platform.daxpay.service.core.channel.alipay.entity.AliPayConfig; import cn.bootx.platform.daxpay.service.core.order.reconcile.entity.PayReconcileDetail;
import cn.hutool.core.io.IoUtil; import cn.hutool.core.io.IoUtil;
import cn.hutool.core.text.csv.CsvReader; import cn.hutool.core.text.csv.CsvReader;
import cn.hutool.core.text.csv.CsvUtil; import cn.hutool.core.text.csv.CsvUtil;
@@ -20,6 +24,7 @@ import lombok.val;
import org.apache.commons.compress.archivers.zip.ZipArchiveEntry; import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
import org.apache.commons.compress.archivers.zip.ZipArchiveInputStream; import org.apache.commons.compress.archivers.zip.ZipArchiveInputStream;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.io.BufferedReader; import java.io.BufferedReader;
import java.io.ByteArrayInputStream; import java.io.ByteArrayInputStream;
@@ -40,12 +45,19 @@ import java.util.stream.Collectors;
public class AliPayReconcileService { public class AliPayReconcileService {
private final AliPayConfigService configService; private final AliPayConfigService configService;
private final AliReconcileBillDetailManager reconcileBillDetailManager;
private final AliReconcileBillTotalManager reconcileBillTotalManager;
/** /**
* 下载对账单, 并进行解析进行保存 * 下载对账单, 并进行解析进行保存
*
* @param date 对账日期 yyyy-MM-dd 格式 * @param date 对账日期 yyyy-MM-dd 格式
* @param recordOrderId 对账订单ID
*/ */
@SneakyThrows @SneakyThrows
public void downAndSave(String date){ @Transactional(rollbackFor = Exception.class)
public void downAndSave(String date, Long recordOrderId){
AliPayConfig config = configService.getConfig(); AliPayConfig config = configService.getConfig();
configService.initConfig(config); configService.initConfig(config);
@@ -63,29 +75,73 @@ public class AliPayReconcileService {
// 获取对账单下载地址并下载 // 获取对账单下载地址并下载
String url = response.getBillDownloadUrl(); String url = response.getBillDownloadUrl();
byte[] bytes = HttpUtil.downloadBytes(url); byte[] bytes = HttpUtil.downloadBytes(url);
// 使用 Apache commons-compress 包装流, // 使用 Apache commons-compress 包装流, 读取返回的对账CSV文件
ZipArchiveInputStream zipArchiveInputStream = new ZipArchiveInputStream(new ByteArrayInputStream(bytes),"GBK"); ZipArchiveInputStream zipArchiveInputStream = new ZipArchiveInputStream(new ByteArrayInputStream(bytes),"GBK");
ZipArchiveEntry entry; ZipArchiveEntry entry;
List<AliReconcileBillDetail> billDetails; List<AliReconcileBillDetail> billDetails = new ArrayList<>();
List<AliReconcileBillTotal> billTotals; List<AliReconcileBillTotal> billTotals = new ArrayList<>();
while ((entry= zipArchiveInputStream.getNextZipEntry()) != null){ while ((entry= zipArchiveInputStream.getNextZipEntry()) != null){
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(zipArchiveInputStream,"GBK")); BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(zipArchiveInputStream,"GBK"));
List<String> strings = IoUtil.readLines(bufferedReader, new ArrayList<>()); List<String> strings = IoUtil.readLines(bufferedReader, new ArrayList<>());
String name = entry.getName(); String name = entry.getName();
if (StrUtil.endWith(name,"_业务明细(汇总).csv")){ if (StrUtil.endWith(name,"_业务明细(汇总).csv")){
// 汇总
billTotals = this.parseTotal(strings); billTotals = this.parseTotal(strings);
} else { } else {
// 明细
billDetails = this.parseDetail(strings); billDetails = this.parseDetail(strings);
} }
} }
// 保存 // 保存原始对账记录
System.out.println(); this.save(billDetails, billTotals, recordOrderId);
// 将原始交易明细对账记录转换通用结构并保存到上下文中
this.convertAndSave(billDetails);
} catch (AlipayApiException e) { } catch (AlipayApiException e) {
log.error("下载对账单失败",e); log.error("下载对账单失败",e);
throw new RuntimeException(e); throw new RuntimeException(e);
} }
} }
/**
* 保存原始对账记录
*/
private void save(List<AliReconcileBillDetail> billDetails, List<AliReconcileBillTotal> billTotals, Long recordOrderId){
billDetails.forEach(o->o.setRecordOrderId(recordOrderId));
reconcileBillDetailManager.saveAll(billDetails);
billTotals.forEach(o->o.setRecordOrderId(recordOrderId));
reconcileBillTotalManager.saveAll(billTotals);
}
/**
* 转换为通用对账记录对象
*/
private void convertAndSave(List<AliReconcileBillDetail> billDetails){
List<PayReconcileDetail> collect = billDetails.stream()
.map(this::convert)
.collect(Collectors.toList());
// 写入到上下文中
PaymentContextLocal.get().getReconcile().setReconcileDetails(collect);
}
/**
* 转换为通用对账记录对象
*/
private PayReconcileDetail convert(AliReconcileBillDetail billDetail){
// 默认为支付
PayReconcileDetail payReconcileDetail = new PayReconcileDetail()
.setRecordOrderId(billDetail.getRecordOrderId())
.setOrderId(billDetail.getOutTradeNo())
.setTitle(billDetail.getSubject())
.setGatewayOrderNo(billDetail.getTradeNo());
// 如果是退款
if (Objects.equals(billDetail.getTradeType(), "refund")){
}
return payReconcileDetail;
}
/** /**
* 解析明细 * 解析明细
*/ */

View File

@@ -0,0 +1,18 @@
package cn.bootx.platform.daxpay.service.core.channel.wechat.dao;
import cn.bootx.platform.common.mybatisplus.impl.BaseManager;
import cn.bootx.platform.daxpay.service.core.channel.wechat.entity.WxReconcileFundFlowDetail;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Repository;
/**
*
* @author xxm
* @since 2024/1/21
*/
@Slf4j
@Repository
@RequiredArgsConstructor
public class WxReconcileFundFlowDetailManager extends BaseManager<WxReconcileFundFlowDetailMapper,WxReconcileFundFlowDetail> {
}

View File

@@ -0,0 +1,14 @@
package cn.bootx.platform.daxpay.service.core.channel.wechat.dao;
import cn.bootx.platform.daxpay.service.core.channel.wechat.entity.WxReconcileFundFlowDetail;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
/**
*
* @author xxm
* @since 2024/1/21
*/
@Mapper
public interface WxReconcileFundFlowDetailMapper extends BaseMapper<WxReconcileFundFlowDetail> {
}

View File

@@ -0,0 +1,18 @@
package cn.bootx.platform.daxpay.service.core.channel.wechat.dao;
import cn.bootx.platform.common.mybatisplus.impl.BaseManager;
import cn.bootx.platform.daxpay.service.core.channel.wechat.entity.WxReconcileFundFlowTotal;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Repository;
/**
*
* @author xxm
* @since 2024/1/21
*/
@Slf4j
@Repository
@RequiredArgsConstructor
public class WxReconcileFundFlowTotalManager extends BaseManager<WxReconcileFundFlowTotalMapper, WxReconcileFundFlowTotal> {
}

View File

@@ -0,0 +1,14 @@
package cn.bootx.platform.daxpay.service.core.channel.wechat.dao;
import cn.bootx.platform.daxpay.service.core.channel.wechat.entity.WxReconcileFundFlowTotal;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
/**
*
* @author xxm
* @since 2024/1/21
*/
@Mapper
public interface WxReconcileFundFlowTotalMapper extends BaseMapper<WxReconcileFundFlowTotal> {
}

View File

@@ -1,6 +1,7 @@
package cn.bootx.platform.daxpay.service.core.channel.wechat.entity; package cn.bootx.platform.daxpay.service.core.channel.wechat.entity;
import cn.bootx.platform.common.mybatisplus.base.MpCreateEntity; import cn.bootx.platform.common.mybatisplus.base.MpCreateEntity;
import cn.bootx.table.modify.annotation.DbColumn;
import cn.hutool.core.annotation.Alias; import cn.hutool.core.annotation.Alias;
import com.baomidou.mybatisplus.annotation.TableName; import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data; import lombok.Data;
@@ -15,86 +16,117 @@ import lombok.EqualsAndHashCode;
@Data @Data
@TableName("pay_wechat_reconcile_bill_detail") @TableName("pay_wechat_reconcile_bill_detail")
public class WxReconcileBillDetail extends MpCreateEntity { public class WxReconcileBillDetail extends MpCreateEntity {
@DbColumn(comment = "关联对账订单ID")
private Long recordOrderId;
@Alias("交易时间") @Alias("交易时间")
@DbColumn(comment = "交易时间")
private String transactionTime; private String transactionTime;
@Alias("公众账号ID") @Alias("公众账号ID")
@DbColumn(comment = "公众账号ID")
private String appId; private String appId;
@Alias("商户号") @Alias("商户号")
@DbColumn(comment = "商户号")
private String merchantId; private String merchantId;
@Alias("特约商户号") @Alias("特约商户号")
@DbColumn(comment = "特约商户号")
private String subMerchantId; private String subMerchantId;
@Alias("微信订单号") @Alias("微信订单号")
@DbColumn(comment = "微信订单号")
private String weiXinOrderNo; private String weiXinOrderNo;
@Alias("商户订单号") @Alias("商户订单号")
@DbColumn(comment = "商户订单号")
private String mchOrderNo; private String mchOrderNo;
@Alias("用户标识") @Alias("用户标识")
@DbColumn(comment = "用户标识")
private String userId; private String userId;
@Alias("设备号") @Alias("设备号")
@DbColumn(comment = "设备号")
private String deviceInfo; private String deviceInfo;
@Alias("交易类型") @Alias("交易类型")
@DbColumn(comment = "交易类型")
private String type; private String type;
@Alias("交易状态") @Alias("交易状态")
@DbColumn(comment = "交易状态")
private String status; private String status;
@Alias("付款银行") @Alias("付款银行")
@DbColumn(comment = "付款银行")
private String bank; private String bank;
@Alias("货币种类") @Alias("货币种类")
@DbColumn(comment = "货币种类")
private String currency; private String currency;
@Alias("应结订单金额") @Alias("应结订单金额")
@DbColumn(comment = "应结订单金额")
private String amount; private String amount;
@Alias("代金券金额") @Alias("代金券金额")
@DbColumn(comment = "代金券金额")
private String envelopeAmount; private String envelopeAmount;
@Alias("微信退款单号") @Alias("微信退款单号")
@DbColumn(comment = "微信退款单号")
private String name; private String name;
@Alias("商户退款单号") @Alias("商户退款单号")
@DbColumn(comment = "商户退款单号")
private String packet; private String packet;
@Alias("退款金额") @Alias("退款金额")
@DbColumn(comment = "退款金额")
private String poundage; private String poundage;
@Alias("充值券退款金额") @Alias("充值券退款金额")
@DbColumn(comment = "充值券退款金额")
private String amount2; private String amount2;
@Alias("退款类型") @Alias("退款类型")
@DbColumn(comment = "退款类型")
private String rate; private String rate;
@Alias("退款状态") @Alias("退款状态")
@DbColumn(comment = "退款状态")
private String orderAmount; private String orderAmount;
@Alias("商品名称") @Alias("商品名称")
@DbColumn(comment = "商品名称")
private String packet2; private String packet2;
@Alias("商户数据包") @Alias("商户数据包")
@DbColumn(comment = "商户数据包")
private String packet3; private String packet3;
@Alias("手续费") @Alias("手续费")
@DbColumn(comment = "手续费")
private String packet4; private String packet4;
@Alias("费率") @Alias("费率")
@DbColumn(comment = "费率")
private String packet5; private String packet5;
@Alias("订单金额") @Alias("订单金额")
@DbColumn(comment = "订单金额")
private String packet6; private String packet6;
@Alias("申请退款金额") @Alias("申请退款金额")
@DbColumn(comment = "申请退款金额")
private String packet7; private String packet7;
@Alias("费率备注") @Alias("费率备注")
@DbColumn(comment = "费率备注")
private String packet8; private String packet8;
} }

View File

@@ -1,6 +1,7 @@
package cn.bootx.platform.daxpay.service.core.channel.wechat.entity; package cn.bootx.platform.daxpay.service.core.channel.wechat.entity;
import cn.bootx.platform.common.mybatisplus.base.MpCreateEntity; import cn.bootx.platform.common.mybatisplus.base.MpCreateEntity;
import cn.bootx.table.modify.annotation.DbColumn;
import cn.hutool.core.annotation.Alias; import cn.hutool.core.annotation.Alias;
import com.baomidou.mybatisplus.annotation.TableName; import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data; import lombok.Data;
@@ -16,25 +17,35 @@ import lombok.EqualsAndHashCode;
@TableName("pay_wechat_reconcile_bill_total") @TableName("pay_wechat_reconcile_bill_total")
public class WxReconcileBillTotal extends MpCreateEntity { public class WxReconcileBillTotal extends MpCreateEntity {
@DbColumn(comment = "关联对账订单ID")
private Long recordOrderId;
@Alias("总交易单数") @Alias("总交易单数")
@DbColumn(comment = "总交易单数")
private String totalNum; private String totalNum;
@Alias("应结订单总金额") @Alias("应结订单总金额")
@DbColumn(comment = "应结订单总金额")
private String totalAmount; private String totalAmount;
@Alias("退款总金额") @Alias("退款总金额")
@DbColumn(comment = "退款总金额")
private String totalRefundAmount; private String totalRefundAmount;
@Alias("充值券退款总金额") @Alias("充值券退款总金额")
@DbColumn(comment = "充值券退款总金额")
private String totalRefundCouponAmount; private String totalRefundCouponAmount;
@Alias("手续费总金额") @Alias("手续费总金额")
@DbColumn(comment = "手续费总金额")
private String totalFee; private String totalFee;
@Alias("订单总金额") @Alias("订单总金额")
@DbColumn(comment = "订单总金额")
private String totalOrderAmount; private String totalOrderAmount;
@Alias("申请退款总金额") @Alias("申请退款总金额")
@DbColumn(comment = "申请退款总金额")
private String applyTotalRefundAmount; private String applyTotalRefundAmount;
} }

View File

@@ -1,6 +1,7 @@
package cn.bootx.platform.daxpay.service.core.channel.wechat.entity; package cn.bootx.platform.daxpay.service.core.channel.wechat.entity;
import cn.bootx.platform.common.mybatisplus.base.MpCreateEntity; import cn.bootx.platform.common.mybatisplus.base.MpCreateEntity;
import cn.bootx.table.modify.annotation.DbColumn;
import cn.hutool.core.annotation.Alias; import cn.hutool.core.annotation.Alias;
import com.baomidou.mybatisplus.annotation.TableName; import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data; import lombok.Data;
@@ -15,26 +16,40 @@ import lombok.EqualsAndHashCode;
@Data @Data
@TableName("pay_wechat_reconcile_fund_flow_detail") @TableName("pay_wechat_reconcile_fund_flow_detail")
public class WxReconcileFundFlowDetail extends MpCreateEntity { public class WxReconcileFundFlowDetail extends MpCreateEntity {
@DbColumn(comment = "关联对账订单ID")
private Long recordOrderId;
@Alias("记账时间") @Alias("记账时间")
@DbColumn(comment = "记账时间")
private String time; private String time;
@Alias("微信支付业务单号") @Alias("微信支付业务单号")
@DbColumn(comment = "微信支付业务单号")
private String outTradeNo; private String outTradeNo;
@Alias("资金流水单号") @Alias("资金流水单号")
private String id; @DbColumn(comment = "资金流水单号")
private String flowId;
@Alias("业务名称") @Alias("业务名称")
@DbColumn(comment = "业务名称")
private String packet1; private String packet1;
@Alias("业务类型") @Alias("业务类型")
@DbColumn(comment = "业务类型")
private String packet2; private String packet2;
@Alias("收支类型") @Alias("收支类型")
@DbColumn(comment = "收支类型")
private String packet3; private String packet3;
@Alias("收支金额(元)") @Alias("收支金额(元)")
@DbColumn(comment = "收支金额(元)")
private String amount; private String amount;
@Alias("账户结余(元)") @Alias("账户结余(元)")
@DbColumn(comment = "账户结余(元)")
private String balance; private String balance;
@Alias("资金变更提交申请人") @Alias("资金变更提交申请人")
@DbColumn(comment = "资金变更提交申请人")
private String packet4; private String packet4;
@Alias("备注") @Alias("备注")
@DbColumn(comment = "备注")
private String packet5; private String packet5;
@Alias("业务凭证号") @Alias("业务凭证号")
@DbColumn(comment = "业务凭证号")
private String packet6; private String packet6;
} }

View File

@@ -1,6 +1,7 @@
package cn.bootx.platform.daxpay.service.core.channel.wechat.entity; package cn.bootx.platform.daxpay.service.core.channel.wechat.entity;
import cn.bootx.platform.common.mybatisplus.base.MpCreateEntity; import cn.bootx.platform.common.mybatisplus.base.MpCreateEntity;
import cn.bootx.table.modify.annotation.DbColumn;
import cn.hutool.core.annotation.Alias; import cn.hutool.core.annotation.Alias;
import com.baomidou.mybatisplus.annotation.TableName; import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data; import lombok.Data;
@@ -16,14 +17,21 @@ import lombok.EqualsAndHashCode;
@TableName("pay_wechat_reconcile_fund_flow_total") @TableName("pay_wechat_reconcile_fund_flow_total")
public class WxReconcileFundFlowTotal extends MpCreateEntity { public class WxReconcileFundFlowTotal extends MpCreateEntity {
@DbColumn(comment = "关联对账订单ID")
private Long recordOrderId;
@Alias("资金流水总笔数") @Alias("资金流水总笔数")
@DbColumn(comment = "资金流水总笔数")
private String totalNum; private String totalNum;
@Alias("收入笔数") @Alias("收入笔数")
@DbColumn(comment = "收入笔数")
private String incomeNum; private String incomeNum;
@Alias("收入金额") @Alias("收入金额")
@DbColumn(comment = "收入金额")
private String incomeAmount; private String incomeAmount;
@Alias("支出笔数") @Alias("支出笔数")
@DbColumn(comment = "支出笔数")
private String expenditureNum; private String expenditureNum;
@Alias("支出金额") @Alias("支出金额")
@DbColumn(comment = "支出金额")
private String expenditureAmount; private String expenditureAmount;
} }

View File

@@ -2,12 +2,14 @@ package cn.bootx.platform.daxpay.service.core.channel.wechat.service;
import cn.bootx.platform.daxpay.exception.pay.PayFailureException; import cn.bootx.platform.daxpay.exception.pay.PayFailureException;
import cn.bootx.platform.daxpay.service.code.WeChatPayCode; import cn.bootx.platform.daxpay.service.code.WeChatPayCode;
import cn.bootx.platform.daxpay.service.common.local.PaymentContextLocal;
import cn.bootx.platform.daxpay.service.core.channel.wechat.dao.WxReconcileBillDetailManager; import cn.bootx.platform.daxpay.service.core.channel.wechat.dao.WxReconcileBillDetailManager;
import cn.bootx.platform.daxpay.service.core.channel.wechat.dao.WxReconcileBillTotalManger; import cn.bootx.platform.daxpay.service.core.channel.wechat.dao.WxReconcileBillTotalManger;
import cn.bootx.platform.daxpay.service.core.channel.wechat.entity.WeChatPayConfig; import cn.bootx.platform.daxpay.service.core.channel.wechat.entity.WeChatPayConfig;
import cn.bootx.platform.daxpay.service.core.channel.wechat.entity.WxReconcileBillDetail; import cn.bootx.platform.daxpay.service.core.channel.wechat.entity.WxReconcileBillDetail;
import cn.bootx.platform.daxpay.service.core.channel.wechat.entity.WxReconcileBillTotal; 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.channel.wechat.entity.WxReconcileFundFlowDetail;
import cn.bootx.platform.daxpay.service.core.order.reconcile.entity.PayReconcileDetail;
import cn.hutool.core.codec.Base64; import cn.hutool.core.codec.Base64;
import cn.hutool.core.text.csv.CsvReader; import cn.hutool.core.text.csv.CsvReader;
import cn.hutool.core.text.csv.CsvUtil; import cn.hutool.core.text.csv.CsvUtil;
@@ -20,11 +22,13 @@ import com.ijpay.wxpay.model.DownloadFundFlowModel;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.io.ByteArrayInputStream; import java.io.ByteArrayInputStream;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Objects; import java.util.Objects;
import java.util.stream.Collectors;
import static cn.bootx.platform.daxpay.service.code.WeChatPayCode.ACCOUNT_TYPE_BASIC; import static cn.bootx.platform.daxpay.service.code.WeChatPayCode.ACCOUNT_TYPE_BASIC;
@@ -37,7 +41,6 @@ import static cn.bootx.platform.daxpay.service.code.WeChatPayCode.ACCOUNT_TYPE_B
@Service @Service
@RequiredArgsConstructor @RequiredArgsConstructor
public class WechatPayReconcileService{ public class WechatPayReconcileService{
private final WeChatPayConfigService weChatPayConfigService;
private final WxReconcileBillTotalManger reconcileBillTotalManger; private final WxReconcileBillTotalManger reconcileBillTotalManger;
private final WxReconcileBillDetailManager reconcileBillDetailManager; private final WxReconcileBillDetailManager reconcileBillDetailManager;
@@ -45,17 +48,20 @@ public class WechatPayReconcileService{
* 下载对账单并保存 * 下载对账单并保存
* @param date 对账日期 yyyyMMdd 格式 * @param date 对账日期 yyyyMMdd 格式
*/ */
public void downAndSave(String date, WeChatPayConfig config) { @Transactional(rollbackFor = Exception.class)
config = weChatPayConfigService.getConfig(); public void downAndSave(String date, Long recordOrderId, WeChatPayConfig config) {
this.downBill(date, config); this.downBill(date, recordOrderId, config);
this.downFundFlow(date, config); // 资金对账单先不启用
// this.downFundFlow(date, recordOrderId, config);
} }
/** /**
* 下载交易账单 * 下载交易账单
* @param date 对账日期 yyyyMMdd 格式 *
* @param date 对账日期 yyyyMMdd 格式
* @param recordOrderId 对账订单ID
*/ */
public void downBill(String date, WeChatPayConfig config){ public void downBill(String date, Long recordOrderId, WeChatPayConfig config){
// 下载交易账单 // 下载交易账单
Map<String, String> params = DownloadBillModel.builder() Map<String, String> params = DownloadBillModel.builder()
.mch_id(config.getWxMchId()) .mch_id(config.getWxMchId())
@@ -74,14 +80,41 @@ public class WechatPayReconcileService{
result = result.replaceAll("`", "").replaceAll("\uFEFF", ""); result = result.replaceAll("`", "").replaceAll("\uFEFF", "");
CsvReader reader = CsvUtil.getReader(); CsvReader reader = CsvUtil.getReader();
// 获取交易记录 // 获取交易记录并保存
String billDetail = StrUtil.subBefore(result, "总交易单数", false); String billDetail = StrUtil.subBefore(result, "总交易单数", false);
List<WxReconcileBillDetail> billDetails = reader.read(billDetail, WxReconcileBillDetail.class); List<WxReconcileBillDetail> billDetails = reader.read(billDetail, WxReconcileBillDetail.class);
billDetails.forEach(o->o.setRecordOrderId(recordOrderId));
reconcileBillDetailManager.saveAll(billDetails);
// 获取汇总数据 // 获取汇总数据并保存
String billTotal = result.substring(result.indexOf("总交易单数")); String billTotal = result.substring(result.indexOf("总交易单数"));
List<WxReconcileBillTotal> billTotals = reader.read(billTotal, WxReconcileBillTotal.class); List<WxReconcileBillTotal> billTotals = reader.read(billTotal, WxReconcileBillTotal.class);
billTotals.forEach(o->o.setRecordOrderId(recordOrderId));
reconcileBillTotalManger.saveAll(billTotals);
// 将原始交易明细对账记录转换通用结构并保存到上下文中
this.convertAndSave(billDetails);
}
/**
* 转换为通用对账记录对象
*/
public void convertAndSave(List<WxReconcileBillDetail> billDetails){
List<PayReconcileDetail> collect = billDetails.stream()
.map(this::convert)
.collect(Collectors.toList());
// 写入到上下文中
PaymentContextLocal.get().getReconcile().setReconcileDetails(collect);
}
/**
* 转换为通用对账记录对象
*/
public PayReconcileDetail convert(WxReconcileBillDetail billDetail){
PayReconcileDetail payReconcileDetail = new PayReconcileDetail()
.setRecordOrderId(billDetail.getRecordOrderId());
return payReconcileDetail;
} }
@@ -90,9 +123,10 @@ public class WechatPayReconcileService{
* 如果出现 No appropriate protocol (protocol is disabled or cipher suites are inappropriate) * 如果出现 No appropriate protocol (protocol is disabled or cipher suites are inappropriate)
* 更换一下最新的JDK即可, 例如 corretto Jdk * 更换一下最新的JDK即可, 例如 corretto Jdk
* *
* @param date 对账日期 yyyyMMdd 格式 * @param date 对账日期 yyyyMMdd 格式
* @param recordOrderId 对账订单ID
*/ */
public void downFundFlow(String date, WeChatPayConfig config){ public void downFundFlow(String date, Long recordOrderId, WeChatPayConfig config){
if (StrUtil.isBlank(config.getP12())){ if (StrUtil.isBlank(config.getP12())){
return; return;
} }

View File

@@ -1,44 +1,52 @@
package cn.bootx.platform.daxpay.service.core.order.reconcile.entity; package cn.bootx.platform.daxpay.service.core.order.reconcile.entity;
import cn.bootx.platform.common.mybatisplus.base.MpCreateEntity; import cn.bootx.platform.common.mybatisplus.base.MpCreateEntity;
import cn.bootx.table.modify.annotation.DbColumn;
import com.baomidou.mybatisplus.annotation.TableName; import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data; import lombok.Data;
import lombok.EqualsAndHashCode; import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors; import lombok.experimental.Accessors;
/** /**
* 支付对账记录详情 * 通用支付对账记录
* @author xxm * @author xxm
* @since 2024/1/18 * @since 2024/1/18
*/ */
@EqualsAndHashCode(callSuper = true) @EqualsAndHashCode(callSuper = true)
@Data @Data
@Accessors(chain = true) @Accessors(chain = true)
@TableName("pay_reconcile_detail_record") @TableName("pay_reconcile_detail")
public class PayReconcileDetail extends MpCreateEntity { public class PayReconcileDetail extends MpCreateEntity {
/** 交易状态 */ /** 关联对账订单ID */
@DbColumn(comment = "关联对账订单ID")
private Long recordOrderId;
/**
* 交易状态
* @see cn.bootx.platform.daxpay.code.PayStatusEnum
*/
@DbColumn(comment = "交易状态")
private String status; private String status;
/** 交易类型 支付/退款 */ /** 交易类型 支付/退款 */
@DbColumn(comment = "交易类型")
private String type; private String type;
/** 订单 - 支付ID/退款ID */ /** 订单id - 支付ID/退款ID */
private String paymentId; @DbColumn(comment = "订单id")
private String orderId;
/** 网关订单号 - 支付宝/微信的订单号 */ /** 网关订单号 - 支付宝/微信的订单号 */
@DbColumn(comment = "网关订单号")
private String gatewayOrderNo; private String gatewayOrderNo;
/** 交易金额 */ /** 交易金额 */
@DbColumn(comment = "交易金额")
private Integer amount; private Integer amount;
/** 手续费 */
private Integer poundage;
/** 费率 */
private Integer rate;
/** 商品名称 */ /** 商品名称 */
@DbColumn(comment = "商品名称")
private String title; private String title;
} }

View File

@@ -1,6 +1,7 @@
package cn.bootx.platform.daxpay.service.core.order.reconcile.entity; package cn.bootx.platform.daxpay.service.core.order.reconcile.entity;
import cn.bootx.platform.common.mybatisplus.base.MpCreateEntity; import cn.bootx.platform.common.mybatisplus.base.MpCreateEntity;
import cn.bootx.table.modify.annotation.DbColumn;
import cn.bootx.table.modify.annotation.DbTable; import cn.bootx.table.modify.annotation.DbTable;
import com.baomidou.mybatisplus.annotation.TableName; import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data; import lombok.Data;
@@ -10,15 +11,15 @@ import lombok.experimental.Accessors;
import java.time.LocalDate; import java.time.LocalDate;
/** /**
* 支付对账单记录 * 支付对账单订单
* @author xxm * @author xxm
* @since 2024/1/18 * @since 2024/1/18
*/ */
@EqualsAndHashCode(callSuper = true) @EqualsAndHashCode(callSuper = true)
@Data @Data
@Accessors(chain = true) @Accessors(chain = true)
@DbTable(comment = "支付对账单记录") @DbTable(comment = "支付对账单订单")
@TableName("pay_reconcile_record") @TableName("pay_reconcile_order")
public class PayReconcileOrder extends MpCreateEntity { public class PayReconcileOrder extends MpCreateEntity {
/** /**
@@ -26,21 +27,27 @@ public class PayReconcileOrder extends MpCreateEntity {
* 规则:通道简称 + yyyyMMdd + 两位流水号 * 规则:通道简称 + yyyyMMdd + 两位流水号
* 例子wx2024012001、ali2024012002 * 例子wx2024012001、ali2024012002
*/ */
@DbColumn(comment = "批次号")
private String batchNo; private String batchNo;
/** 日期 */ /** 日期 */
@DbColumn(comment = "日期")
private LocalDate date; private LocalDate date;
/** 通道 */ /** 通道 */
@DbColumn(comment = "通道")
private String channel; private String channel;
/** 对账单是否下载成功 */ /** 是否下载成功 */
@DbColumn(comment = "是否下载成功")
private boolean down; private boolean down;
/** 是否比对完成 */ /** 是否比对完成 */
@DbColumn(comment = "是否比对完成")
private boolean compare; private boolean compare;
/** 错误信息 */ /** 错误信息 */
@DbColumn(comment = "错误信息")
private String errorMsg; private String errorMsg;
} }

View File

@@ -0,0 +1,51 @@
package cn.bootx.platform.daxpay.service.core.order.reconcile.service;
import cn.bootx.platform.common.core.rest.PageResult;
import cn.bootx.platform.common.core.rest.param.PageParam;
import cn.bootx.platform.daxpay.service.core.order.reconcile.dao.PayReconcileDetailManager;
import cn.bootx.platform.daxpay.service.core.order.reconcile.dao.PayReconcileOrderManager;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
/**
* 支付对账订单查询服务类
* @author xxm
* @since 2024/1/21
*/
@Slf4j
@Service
@RequiredArgsConstructor
public class PayReconcileOrderQueryService {
private final PayReconcileOrderManager orderManager;
private final PayReconcileDetailManager detailManager;
/**
* 分页
*/
public PageResult<?> page(PageParam pageParam){
return null;
}
/**
* 对账订单详情
*/
public void findById(Long id){
}
/**
* 明细分页
*/
public PageResult<?> pageDetail(PageParam pageParam, Long orderId){
return null;
}
/**
* 明细详情
*/
public void findDetailById(Long id){
}
}

View File

@@ -28,7 +28,6 @@ public class PayReconcileOrderService {
private final PayReconcileOrderManager reconcileOrderManager; private final PayReconcileOrderManager reconcileOrderManager;
private final Sequence sequence; private final Sequence sequence;
/** /**
* 更新, 开启一个新事务进行更新 * 更新, 开启一个新事务进行更新
*/ */

View File

@@ -1,6 +1,10 @@
package cn.bootx.platform.daxpay.service.core.payment.reconcile.service; package cn.bootx.platform.daxpay.service.core.payment.reconcile.service;
import cn.bootx.platform.common.core.exception.DataNotExistException; import cn.bootx.platform.common.core.exception.DataNotExistException;
import cn.bootx.platform.daxpay.service.common.context.PaymentContext;
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.entity.PayReconcileDetail;
import cn.bootx.platform.daxpay.service.core.order.reconcile.entity.PayReconcileOrder; 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.order.reconcile.service.PayReconcileOrderService;
import cn.bootx.platform.daxpay.service.core.payment.reconcile.factory.PayReconcileStrategyFactory; import cn.bootx.platform.daxpay.service.core.payment.reconcile.factory.PayReconcileStrategyFactory;
@@ -9,6 +13,8 @@ import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import java.util.List;
/** /**
* 支付对账单下载服务 * 支付对账单下载服务
* @author xxm * @author xxm
@@ -19,6 +25,7 @@ import org.springframework.stereotype.Service;
@RequiredArgsConstructor @RequiredArgsConstructor
public class PayReconcileService { public class PayReconcileService {
private final PayReconcileOrderService reconcileOrderService; private final PayReconcileOrderService reconcileOrderService;
private final PayReconcileDetailManager reconcileDetailManager;
/** /**
* 下载对账单并进行保存 * 下载对账单并进行保存
@@ -33,6 +40,9 @@ public class PayReconcileService {
* 下载对账单并进行保存 * 下载对账单并进行保存
*/ */
public void downAndSave(PayReconcileOrder recordOrder) { public void downAndSave(PayReconcileOrder recordOrder) {
// 初始化上下文
PaymentContextLocal.setIfAbsent(new PaymentContext());
// 构建对账策略
AbsReconcileStrategy absReconcileStrategy = PayReconcileStrategyFactory.create(recordOrder.getChannel()); AbsReconcileStrategy absReconcileStrategy = PayReconcileStrategyFactory.create(recordOrder.getChannel());
absReconcileStrategy.initParam(recordOrder); absReconcileStrategy.initParam(recordOrder);
absReconcileStrategy.doBeforeHandler(); absReconcileStrategy.doBeforeHandler();
@@ -46,6 +56,11 @@ public class PayReconcileService {
reconcileOrderService.update(recordOrder); reconcileOrderService.update(recordOrder);
throw new RuntimeException(e); throw new RuntimeException(e);
} }
// 保存转换后的通用结构对账单
List<PayReconcileDetail> reconcileDetails = PaymentContextLocal.get()
.getReconcile()
.getReconcileDetails();
reconcileDetailManager.saveAll(reconcileDetails);
} }
} }

View File

@@ -52,11 +52,11 @@ public class AlipayReconcileStrategy extends AbsReconcileStrategy {
} }
/** /**
* 下载对账单 * 下载和保存对账单
*/ */
@Override @Override
public void downAndSave() { public void downAndSave() {
String format = LocalDateTimeUtil.format(this.getRecordOrder().getDate(), DatePattern.NORM_DATE_PATTERN); String date = LocalDateTimeUtil.format(this.getRecordOrder().getDate(), DatePattern.NORM_DATE_PATTERN);
reconcileService.downAndSave(format); reconcileService.downAndSave(date,this.getRecordOrder().getId());
} }
} }

View File

@@ -55,6 +55,6 @@ public class WechatPayReconcileStrategy extends AbsReconcileStrategy {
@Override @Override
public void downAndSave() { public void downAndSave() {
String format = LocalDateTimeUtil.format(this.getRecordOrder().getDate(), DatePattern.PURE_DATE_PATTERN); String format = LocalDateTimeUtil.format(this.getRecordOrder().getDate(), DatePattern.PURE_DATE_PATTERN);
reconcileService.downAndSave(format,this.config); reconcileService.downAndSave(format,this.getRecordOrder().getId(), this.config);
} }
} }