feat 对账开发

This commit is contained in:
bootx
2024-03-01 23:46:02 +08:00
parent 01b5c7f29d
commit 71727c26bd
17 changed files with 238 additions and 166 deletions

View File

@@ -4,13 +4,13 @@ import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* 支付对账交易类型
* 对账交易类型
* @author xxm
* @since 2024/1/23
*/
@Getter
@AllArgsConstructor
public enum PayReconcileTradeEnum {
public enum ReconcileTradeEnum {
PAY("pay","支付"),
REFUND("refund","退款"),

View File

@@ -0,0 +1,24 @@
package cn.bootx.platform.daxpay.service.code;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* 对账差异类型
* @author xxm
* @since 2024/3/1
*/
@Getter
@AllArgsConstructor
public enum ReconcileDiffTypeEnum {
/** 本地订单不存在 */
LOCAL_NOT_EXISTS("local_not_exists","本地订单不存在"),
/** 远程订单不存在 */
REMOTE_NOT_EXISTS("remote_not_exists","远程订单不存在"),
/** 订单信息不一致 */
NOT_MATCH("not_match","订单信息不一致");
final String code;
final String name;
}

View File

@@ -2,6 +2,7 @@ package cn.bootx.platform.daxpay.service.core.channel.alipay.convert;
import cn.bootx.platform.daxpay.service.core.channel.alipay.entity.AliPayConfig;
import cn.bootx.platform.daxpay.service.core.channel.alipay.entity.AliPayRecord;
import cn.bootx.platform.daxpay.service.core.payment.reconcile.domain.GeneralReconcileRecord;
import cn.bootx.platform.daxpay.service.dto.channel.alipay.AliPayConfigDto;
import cn.bootx.platform.daxpay.service.dto.channel.alipay.AliPayRecordDto;
import cn.bootx.platform.daxpay.service.param.channel.alipay.AliPayConfigParam;
@@ -19,10 +20,10 @@ public interface AlipayConvert {
AlipayConvert CONVERT = Mappers.getMapper(AlipayConvert.class);
AliPayConfig convert(AliPayConfigDto in);
AliPayRecordDto convert(AliPayRecord in);
GeneralReconcileRecord convertReconcileRecord(AliPayRecord in);
AliPayConfig convert(AliPayConfigParam in);
AliPayConfigDto convert(AliPayConfig in);

View File

@@ -34,7 +34,7 @@ public class AliReconcileBillDetail extends MpIdEntity {
@DbColumn(comment = "商品名称")
private String subject;
@Alias("创建时间")
@DbColumn(comment = "完成时间")
@DbColumn(comment = "创建时间")
private String createTime;
@Alias("完成时间")
@DbColumn(comment = "完成时间")

View File

@@ -1,9 +1,10 @@
package cn.bootx.platform.daxpay.service.core.channel.alipay.service;
import cn.bootx.platform.daxpay.code.PayReconcileTradeEnum;
import cn.bootx.platform.daxpay.code.ReconcileTradeEnum;
import cn.bootx.platform.daxpay.exception.pay.PayFailureException;
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.AliPayRecordManager;
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;
@@ -50,6 +51,8 @@ public class AliPayReconcileService {
private final AliReconcileBillTotalManager reconcileBillTotalManager;
private final AliPayRecordManager recordManager;
/**
* 下载对账单, 并进行解析进行保存
*
@@ -139,14 +142,14 @@ public class AliPayReconcileService {
PayReconcileDetail payReconcileDetail = new PayReconcileDetail()
.setRecordOrderId(billDetail.getRecordOrderId())
.setOrderId(billDetail.getOutTradeNo())
.setType(PayReconcileTradeEnum.PAY.getCode())
.setType(ReconcileTradeEnum.PAY.getCode())
.setAmount(amount)
.setTitle(billDetail.getSubject())
.setGatewayOrderNo(billDetail.getTradeNo());
// 退款覆盖更新对应的字段
if (Objects.equals(billDetail.getTradeType(), "退款")){
payReconcileDetail.setOrderId(billDetail.getBatchNo())
.setType(PayReconcileTradeEnum.REFUND.getCode());
.setType(ReconcileTradeEnum.REFUND.getCode());
}
return payReconcileDetail;
@@ -156,7 +159,7 @@ public class AliPayReconcileService {
/**
* 解析明细
*/
public List<AliReconcileBillDetail> parseDetail(List<String> list){
private List<AliReconcileBillDetail> parseDetail(List<String> list){
// 截取需要进行解析的文本内容
String billDetail = list.stream()
.collect(Collectors.joining(System.lineSeparator()));
@@ -171,7 +174,7 @@ public class AliPayReconcileService {
/**
* 解析汇总
*/
public List<AliReconcileBillTotal> parseTotal(List<String> list){
private List<AliReconcileBillTotal> parseTotal(List<String> list){
// 去除前 4 行和后 2 行 然后合并是个一个字符串
String billTotal = list.stream()
.collect(Collectors.joining(System.lineSeparator()));
@@ -183,4 +186,5 @@ public class AliPayReconcileService {
CsvReader reader = CsvUtil.getReader();
return reader.read(billTotal, AliReconcileBillTotal.class);
}
}

View File

@@ -2,6 +2,7 @@ package cn.bootx.platform.daxpay.service.core.channel.wechat.convert;
import cn.bootx.platform.daxpay.service.core.channel.wechat.entity.WeChatPayConfig;
import cn.bootx.platform.daxpay.service.core.channel.wechat.entity.WeChatPayRecord;
import cn.bootx.platform.daxpay.service.core.payment.reconcile.domain.GeneralReconcileRecord;
import cn.bootx.platform.daxpay.service.dto.channel.wechat.WeChatPayConfigDto;
import cn.bootx.platform.daxpay.service.dto.channel.wechat.WeChatPayRecordDto;
import cn.bootx.platform.daxpay.service.param.channel.wechat.WeChatPayConfigParam;
@@ -23,6 +24,8 @@ public interface WeChatConvert {
WeChatPayRecordDto convert(WeChatPayRecord in);
GeneralReconcileRecord convertReconcileRecord(WeChatPayRecord in);
WeChatPayConfigDto convert(WeChatPayConfig in);
}

View File

@@ -30,13 +30,13 @@ public class WxReconcileFundFlowDetail extends MpCreateEntity {
private String flowId;
@Alias("业务名称")
@DbColumn(comment = "业务名称")
private String packet1;
private String name;
@Alias("业务类型")
@DbColumn(comment = "业务类型")
private String packet2;
private String businessType;
@Alias("收支类型")
@DbColumn(comment = "收支类型")
private String packet3;
private String incomeType;
@Alias("收支金额(元)")
@DbColumn(comment = "收支金额(元)")
private String amount;
@@ -45,11 +45,11 @@ public class WxReconcileFundFlowDetail extends MpCreateEntity {
private String balance;
@Alias("资金变更提交申请人")
@DbColumn(comment = "资金变更提交申请人")
private String packet4;
private String applyUser;
@Alias("备注")
@DbColumn(comment = "备注")
private String packet5;
private String remark;
@Alias("业务凭证号")
@DbColumn(comment = "业务凭证号")
private String packet6;
private String voucherNo;
}

View File

@@ -1,9 +1,10 @@
package cn.bootx.platform.daxpay.service.core.channel.wechat.service;
import cn.bootx.platform.daxpay.code.PayReconcileTradeEnum;
import cn.bootx.platform.daxpay.code.ReconcileTradeEnum;
import cn.bootx.platform.daxpay.exception.pay.PayFailureException;
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.WeChatPayRecordManager;
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.entity.WeChatPayConfig;
@@ -45,6 +46,8 @@ public class WechatPayReconcileService{
private final WxReconcileBillTotalManger reconcileBillTotalManger;
private final WxReconcileBillDetailManager reconcileBillDetailManager;
private final WeChatPayRecordManager recordManager;
/**
* 下载对账单并保存
* @param date 对账日期 yyyyMMdd 格式
@@ -127,7 +130,7 @@ public class WechatPayReconcileService{
String orderAmount = billDetail.getOrderAmount();
double v = Double.parseDouble(orderAmount) * 100;
int amount = Math.abs(((int) v));
payReconcileDetail.setType(PayReconcileTradeEnum.PAY.getCode())
payReconcileDetail.setType(ReconcileTradeEnum.PAY.getCode())
.setAmount(amount);
}
// 退款
@@ -136,7 +139,7 @@ public class WechatPayReconcileService{
String refundAmount = billDetail.getApplyRefundAmount();
double v = Double.parseDouble(refundAmount) * 100;
int amount = Math.abs(((int) v));
payReconcileDetail.setType(PayReconcileTradeEnum.REFUND.getCode())
payReconcileDetail.setType(ReconcileTradeEnum.REFUND.getCode())
.setAmount(amount)
.setOrderId(billDetail.getMchRefundNo());
}

View File

@@ -2,7 +2,7 @@ package cn.bootx.platform.daxpay.service.core.order.reconcile.entity;
import cn.bootx.platform.common.core.function.EntityBaseFunction;
import cn.bootx.platform.common.mybatisplus.base.MpCreateEntity;
import cn.bootx.platform.daxpay.code.PayReconcileTradeEnum;
import cn.bootx.platform.daxpay.code.ReconcileTradeEnum;
import cn.bootx.platform.daxpay.service.core.order.reconcile.conver.PayReconcileConvert;
import cn.bootx.platform.daxpay.service.dto.order.reconcile.PayReconcileDetailDto;
import cn.bootx.table.modify.annotation.DbColumn;
@@ -12,6 +12,8 @@ import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;
import java.time.LocalDateTime;
/**
* 通用支付对账记录
* @author xxm
@@ -38,7 +40,7 @@ public class PayReconcileDetail extends MpCreateEntity implements EntityBaseFunc
/**
* 交易类型
* @see PayReconcileTradeEnum
* @see ReconcileTradeEnum
*/
@DbColumn(comment = "交易类型")
private String type;
@@ -59,6 +61,10 @@ public class PayReconcileDetail extends MpCreateEntity implements EntityBaseFunc
@DbColumn(comment = "网关订单号")
private String gatewayOrderNo;
/** 订单时间 */
@DbColumn(comment = "订单时间")
private LocalDateTime orderTime;
@Override
public PayReconcileDetailDto toDto() {

View File

@@ -1,6 +1,7 @@
package cn.bootx.platform.daxpay.service.core.order.reconcile.entity;
import cn.bootx.platform.common.mybatisplus.base.MpBaseEntity;
import cn.bootx.platform.daxpay.code.ReconcileTradeEnum;
import cn.bootx.table.modify.annotation.DbColumn;
import cn.bootx.table.modify.annotation.DbTable;
import com.baomidou.mybatisplus.annotation.TableName;
@@ -38,11 +39,17 @@ public class PayReconcileDiffRecord extends MpBaseEntity {
@DbColumn(comment = "订单标题")
private String title;
/** 订单类型 */
@DbColumn(comment = "订单类型")
/**
* 对账订单类型
* @see ReconcileTradeEnum
*/
@DbColumn(comment = "对账订单类型")
private String orderType;
/** 差异类型 */
/**
* 差异类型
*
*/
@DbColumn(comment = "差异类型")
private String diffType;

View File

@@ -0,0 +1,37 @@
package cn.bootx.platform.daxpay.service.core.payment.reconcile.domain;
import cn.bootx.platform.daxpay.service.code.AliPayRecordTypeEnum;
import lombok.Data;
import java.time.LocalDateTime;
/**
* 通用对账记录对象,用于与网关进行对账
* @author xxm
* @since 2024/3/1
*/
@Data
public class GeneralReconcileRecord {
/** 标题 */
private String title;
/** 金额 */
private Integer amount;
/**
* 业务类型
* @see AliPayRecordTypeEnum
*/
private String type;
/** 本地订单号 */
private Long orderId;
/** 网关订单号 */
private String gatewayOrderNo;
/** 网关完成时间 */
private LocalDateTime gatewayTime;
}

View File

@@ -0,0 +1,9 @@
package cn.bootx.platform.daxpay.service.core.payment.reconcile.domain;
/**
* 对账差异内容
* @author xxm
* @since 2024/3/1
*/
public class ReconcileDiff {
}

View File

@@ -1,8 +1,13 @@
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.daxpay.code.PayChannelEnum;
import cn.bootx.platform.daxpay.code.ReconcileTradeEnum;
import cn.bootx.platform.daxpay.exception.pay.PayFailureException;
import cn.bootx.platform.daxpay.service.code.AliPayRecordTypeEnum;
import cn.bootx.platform.daxpay.service.code.ReconcileDiffTypeEnum;
import cn.bootx.platform.daxpay.service.common.local.PaymentContextLocal;
import cn.bootx.platform.daxpay.service.core.order.reconcile.dao.PayReconcileDetailManager;
import cn.bootx.platform.daxpay.service.core.order.reconcile.dao.PayReconcileOrderManager;
@@ -11,6 +16,7 @@ import cn.bootx.platform.daxpay.service.core.order.reconcile.entity.PayReconcile
import cn.bootx.platform.daxpay.service.core.order.reconcile.entity.PayReconcileOrder;
import cn.bootx.platform.daxpay.service.core.order.reconcile.service.PayReconcileDiffRecordService;
import cn.bootx.platform.daxpay.service.core.order.reconcile.service.PayReconcileOrderService;
import cn.bootx.platform.daxpay.service.core.payment.reconcile.domain.GeneralReconcileRecord;
import cn.bootx.platform.daxpay.service.core.payment.reconcile.factory.PayReconcileStrategyFactory;
import cn.bootx.platform.daxpay.service.func.AbsReconcileStrategy;
import lombok.RequiredArgsConstructor;
@@ -20,7 +26,12 @@ import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import java.time.LocalDate;
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;
/**
* 支付对账单下载服务
@@ -131,7 +142,8 @@ public class PayReconcileService {
reconcileStrategy.setReconcileDetails(reconcileDetails);
try {
// 执行比对任务, 获取对账差异记录
List<PayReconcileDiffRecord> diffRecords = reconcileStrategy.generateDiffRecord();
List<GeneralReconcileRecord> generalReconcileRecord = reconcileStrategy.getGeneralReconcileRecord();
List<PayReconcileDiffRecord> diffRecords = this.generateDiffRecord(generalReconcileRecord,reconcileDetails);
// reconcileOrder.setCompare(true);
// reconcileOrderService.update(reconcileOrder);
} catch (Exception e) {
@@ -141,4 +153,90 @@ public class PayReconcileService {
throw new RuntimeException(e);
}
}
/**
* 比对生成对账差异单
* 1. 远程有, 本地无 补单(追加回订单/记录差异表)
* 2. 远程无, 本地有 记录差错表
* 3. 远程有, 本地有, 但状态不一致 记录差错表
*
*/
private List<PayReconcileDiffRecord> generateDiffRecord(List<GeneralReconcileRecord> records, List<PayReconcileDetail> details){
if (CollUtil.isEmpty(details)){
return new ArrayList<>();
}
Map<String, PayReconcileDetail> detailMap = details.stream()
.collect(Collectors.toMap(PayReconcileDetail::getOrderId, Function.identity(), CollectorsFunction::retainLatest));
List<PayReconcileDiffRecord> diffRecords = new ArrayList<>();
Map<Long, GeneralReconcileRecord> recordMap = records.stream()
.collect(Collectors.toMap(GeneralReconcileRecord::getOrderId, Function.identity(), CollectorsFunction::retainLatest));
// 对账与流水比对
for (PayReconcileDetail detail : details) {
// 判断本地流水有没有记录, 流水没有记录查询本地订单
GeneralReconcileRecord record = recordMap.get(Long.valueOf(detail.getOrderId()));
if (Objects.isNull(record)){
log.info("本地订单不存在: {}", detail.getOrderId());
PayReconcileDiffRecord diffRecord = new PayReconcileDiffRecord()
.setDiffType(ReconcileDiffTypeEnum.LOCAL_NOT_EXISTS.getCode())
.setOrderId(Long.valueOf(detail.getOrderId()))
.setDetailId(detail.getId())
.setRecordId(detail.getRecordOrderId())
.setTitle(detail.getTitle())
.setDiffType(detail.getType())
.setGatewayOrderNo(detail.getGatewayOrderNo())
.setAmount(detail.getAmount())
.setOrderTime(detail.getOrderTime());
diffRecords.add(diffRecord);
continue;
}
// 交易类型 支付/退款
if (Objects.equals(detail.getType(), ReconcileTradeEnum.PAY.getCode())){
// 判断类型是否存在差异
if (!Objects.equals(record.getType(), AliPayRecordTypeEnum.PAY.getCode())){
PayReconcileDiffRecord diffRecord = new PayReconcileDiffRecord()
.setDiffType(ReconcileDiffTypeEnum.NOT_MATCH.getCode())
.setOrderId(Long.valueOf(detail.getOrderId()))
.setDetailId(detail.getId())
.setRecordId(detail.getRecordOrderId())
.setTitle(detail.getTitle())
.setDiffType(detail.getType())
.setGatewayOrderNo(detail.getGatewayOrderNo())
.setAmount(detail.getAmount())
.setOrderTime(detail.getOrderTime());
diffRecords.add(diffRecord);
continue;
}
} else {
// 判断类型是否存在差异
if (!Objects.equals(record.getType(), AliPayRecordTypeEnum.REFUND.getCode())) {
log.info("本地订单类型不正常: {}", detail.getOrderId());
continue;
}
}
// 判断是否存在差异 金额, 状态
if (!Objects.equals(record.getAmount(), detail.getAmount())){
log.info("本地订单金额不正常: {}", detail.getOrderId());
continue;
}
}
// 流水与对账单比对, 找出本地有, 远程没有的记录
for (GeneralReconcileRecord record : records) {
PayReconcileDetail detail = detailMap.get(String.valueOf(record.getOrderId()));
if (Objects.isNull(detail)){
log.info("远程订单不存在: {}", record.getOrderId());
continue;
}
}
return diffRecords;
}
/**
* 判断订单之间是否存在差异
*/
public void reconcileDiff(GeneralReconcileRecord record, PayReconcileDetail detail){
}
}

View File

@@ -1,19 +1,16 @@
package cn.bootx.platform.daxpay.service.core.payment.reconcile.strategy;
import cn.bootx.platform.common.core.function.CollectorsFunction;
import cn.bootx.platform.common.core.util.CollUtil;
import cn.bootx.platform.common.core.util.LocalDateTimeUtil;
import cn.bootx.platform.common.sequence.func.Sequence;
import cn.bootx.platform.daxpay.code.PayChannelEnum;
import cn.bootx.platform.daxpay.code.PayReconcileTradeEnum;
import cn.bootx.platform.daxpay.service.code.AliPayRecordTypeEnum;
import cn.bootx.platform.daxpay.service.core.channel.alipay.convert.AlipayConvert;
import cn.bootx.platform.daxpay.service.core.channel.alipay.dao.AliPayRecordManager;
import cn.bootx.platform.daxpay.service.core.channel.alipay.entity.AliPayConfig;
import cn.bootx.platform.daxpay.service.core.channel.alipay.entity.AliPayRecord;
import cn.bootx.platform.daxpay.service.core.channel.alipay.service.AliPayConfigService;
import cn.bootx.platform.daxpay.service.core.channel.alipay.service.AliPayReconcileService;
import cn.bootx.platform.daxpay.service.core.order.reconcile.entity.PayReconcileDetail;
import cn.bootx.platform.daxpay.service.core.order.reconcile.entity.PayReconcileDiffRecord;
import cn.bootx.platform.daxpay.service.core.payment.reconcile.domain.GeneralReconcileRecord;
import cn.bootx.platform.daxpay.service.func.AbsReconcileStrategy;
import cn.hutool.core.date.DatePattern;
import lombok.Getter;
@@ -25,11 +22,7 @@ import org.springframework.stereotype.Service;
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;
import static org.springframework.beans.factory.config.BeanDefinition.SCOPE_PROTOTYPE;
@@ -100,72 +93,15 @@ public class AlipayReconcileStrategy extends AbsReconcileStrategy {
}
/**
* 比对生成对账差异单
* 1. 远程有, 本地无 补单(追加回订单/记录差异表)
* 2. 远程无, 本地有 记录差错表
* 3. 远程有, 本地有, 但状态不一致 记录差错表
* 获取通用对账对象, 将流水记录转换为对账对象
*/
@Override
public List<PayReconcileDiffRecord> generateDiffRecord() {
List<PayReconcileDetail> details = this.getReconcileDetails();
if (CollUtil.isEmpty(details)){
return new ArrayList<>(0);
}
// 差异单列表
List<PayReconcileDiffRecord> diffRecords = new ArrayList<>();
Map<String, PayReconcileDetail> detailMap = details.stream()
.collect(Collectors.toMap(PayReconcileDetail::getOrderId, Function.identity(), CollectorsFunction::retainLatest));
// 对哪天进行对账
LocalDate date = this.getRecordOrder().getDate();
public List<GeneralReconcileRecord> getGeneralReconcileRecord() {
// 查询流水
LocalDateTime localDateTime = LocalDateTimeUtil.date2DateTime(date);
LocalDateTime localDateTime = LocalDateTimeUtil.date2DateTime(this.getRecordOrder().getDate());
LocalDateTime start = LocalDateTimeUtil.beginOfDay(localDateTime);
LocalDateTime end = LocalDateTimeUtil.endOfDay(localDateTime);
List<AliPayRecord> records = recordManager.findByDate(start, end);
Map<Long, AliPayRecord> recordMap = records.stream()
.collect(Collectors.toMap(AliPayRecord::getOrderId, Function.identity(), CollectorsFunction::retainLatest));
// 对账与流水比对
for (PayReconcileDetail detail : details) {
// 判断本地有没有记录
AliPayRecord record = recordMap.get(Long.valueOf(detail.getOrderId()));
if (Objects.isNull(record)){
log.info("本地订单不存在: {}", detail.getOrderId());
continue;
}
System.out.println(detail.getId());
// 交易类型 支付/退款
if (Objects.equals(detail.getType(), PayReconcileTradeEnum.PAY.getCode())){
// 判断类型是否存在差异
if (!Objects.equals(record.getType(), AliPayRecordTypeEnum.PAY.getCode())){
log.info("本地订单类型不正常: {}", detail.getOrderId());
continue;
}
} else {
// 判断类型是否存在差异
if (!Objects.equals(record.getType(), AliPayRecordTypeEnum.REFUND.getCode())){
log.info("本地订单类型不正常: {}", detail.getOrderId());
continue;
}
}
// 判断是否存在差异 金额, 状态
if (!Objects.equals(record.getAmount(), detail.getAmount())){
log.info("本地订单金额不正常: {}", detail.getOrderId());
continue;
}
}
// 流水与对账单比对, 找出本地有, 远程没有的记录
for (AliPayRecord record : records) {
PayReconcileDetail detail = detailMap.get(String.valueOf(record.getOrderId()));
if (Objects.isNull(detail)){
log.info("远程订单不存在: {}", record.getOrderId());
continue;
}
}
return diffRecords;
return records.stream().map(AlipayConvert.CONVERT::convertReconcileRecord).collect(Collectors.toList());
}
}

View File

@@ -1,19 +1,16 @@
package cn.bootx.platform.daxpay.service.core.payment.reconcile.strategy;
import cn.bootx.platform.common.core.function.CollectorsFunction;
import cn.bootx.platform.common.core.util.CollUtil;
import cn.bootx.platform.common.core.util.LocalDateTimeUtil;
import cn.bootx.platform.common.sequence.func.Sequence;
import cn.bootx.platform.daxpay.code.PayChannelEnum;
import cn.bootx.platform.daxpay.code.PayReconcileTradeEnum;
import cn.bootx.platform.daxpay.service.code.AliPayRecordTypeEnum;
import cn.bootx.platform.daxpay.service.core.channel.wechat.convert.WeChatConvert;
import cn.bootx.platform.daxpay.service.core.channel.wechat.dao.WeChatPayRecordManager;
import cn.bootx.platform.daxpay.service.core.channel.wechat.entity.WeChatPayConfig;
import cn.bootx.platform.daxpay.service.core.channel.wechat.entity.WeChatPayRecord;
import cn.bootx.platform.daxpay.service.core.channel.wechat.service.WeChatPayConfigService;
import cn.bootx.platform.daxpay.service.core.channel.wechat.service.WechatPayReconcileService;
import cn.bootx.platform.daxpay.service.core.order.reconcile.entity.PayReconcileDetail;
import cn.bootx.platform.daxpay.service.core.order.reconcile.entity.PayReconcileDiffRecord;
import cn.bootx.platform.daxpay.service.core.payment.reconcile.domain.GeneralReconcileRecord;
import cn.bootx.platform.daxpay.service.func.AbsReconcileStrategy;
import cn.hutool.core.date.DatePattern;
import lombok.RequiredArgsConstructor;
@@ -25,9 +22,6 @@ import org.springframework.stereotype.Service;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.function.Function;
import java.util.stream.Collectors;
import static org.springframework.beans.factory.config.BeanDefinition.SCOPE_PROTOTYPE;
@@ -100,64 +94,19 @@ public class WechatPayReconcileStrategy extends AbsReconcileStrategy {
* 1. 远程有, 本地无 补单(追加回订单/记录差异表)
* 2. 远程无, 本地有 记录差错表
* 3. 远程有, 本地有, 但状态不一致 记录差错表
*
* @return
*/
/**
* 获取通用对账对象, 将流水记录转换为对账对象
*/
@Override
public List<PayReconcileDiffRecord> generateDiffRecord() {
List<PayReconcileDetail> details = this.getReconcileDetails();
if (CollUtil.isEmpty(details)){
return;
}
Map<String, PayReconcileDetail> detailMap = details.stream()
.collect(Collectors.toMap(PayReconcileDetail::getOrderId, Function.identity(), CollectorsFunction::retainLatest));
// 对哪天进行对账
LocalDate date = this.getRecordOrder().getDate();
public List<GeneralReconcileRecord> getGeneralReconcileRecord() {
// 查询流水
LocalDateTime localDateTime = LocalDateTimeUtil.date2DateTime(date);
LocalDateTime localDateTime = LocalDateTimeUtil.date2DateTime(this.getRecordOrder().getDate());
LocalDateTime start = LocalDateTimeUtil.beginOfDay(localDateTime);
LocalDateTime end = LocalDateTimeUtil.endOfDay(localDateTime);
List<WeChatPayRecord> records = recordManager.findByDate(start, end);
Map<Long, WeChatPayRecord> recordMap = records.stream()
.collect(Collectors.toMap(WeChatPayRecord::getOrderId, Function.identity(), CollectorsFunction::retainLatest));
// 对账与流水比对
for (PayReconcileDetail detail : details) {
// 判断本地有没有记录
WeChatPayRecord record = recordMap.get(Long.valueOf(detail.getOrderId()));
if (Objects.isNull(record)){
log.info("本地订单不存在: {}", detail.getOrderId());
continue;
}
// 交易类型 支付/退款
if (Objects.equals(detail.getType(), PayReconcileTradeEnum.PAY.getCode())){
// 判断类型是否存在差异
if (!Objects.equals(record.getType(), AliPayRecordTypeEnum.PAY.getCode())){
log.info("本地订单类型不正常: {}", detail.getOrderId());
continue;
}
} else {
// 判断类型是否存在差异
if (!Objects.equals(record.getType(), AliPayRecordTypeEnum.REFUND.getCode())){
log.info("本地订单类型不正常: {}", detail.getOrderId());
continue;
}
}
// 判断是否存在差异 金额, 状态
if (!Objects.equals(record.getAmount(), detail.getAmount())){
log.info("本地订单金额不正常: {}", detail.getOrderId());
continue;
}
}
// 流水与对账单比对, 找出本地有, 远程没有的记录
for (WeChatPayRecord record : records) {
PayReconcileDetail detail = detailMap.get(String.valueOf(record.getOrderId()));
if (Objects.isNull(detail)){
log.info("远程订单不存在: {}", record.getOrderId());
continue;
}
}
return records.stream().map(WeChatConvert.CONVERT::convertReconcileRecord).collect(Collectors.toList());
}
}

View File

@@ -1,8 +1,8 @@
package cn.bootx.platform.daxpay.service.func;
import cn.bootx.platform.daxpay.service.core.order.reconcile.entity.PayReconcileDetail;
import cn.bootx.platform.daxpay.service.core.order.reconcile.entity.PayReconcileDiffRecord;
import cn.bootx.platform.daxpay.service.core.order.reconcile.entity.PayReconcileOrder;
import cn.bootx.platform.daxpay.service.core.payment.reconcile.domain.GeneralReconcileRecord;
import lombok.Getter;
import lombok.Setter;
@@ -42,13 +42,8 @@ public abstract class AbsReconcileStrategy implements PayStrategy {
public abstract void downAndSave();
/**
* 比对生成对账差异单
* 1. 远程有, 本地无 补单(追加回订单/记录差异表)
* 2. 远程无, 本地有 记录差错表
* 3. 远程有, 本地有, 但状态不一致 记录差错表
*
* @return
* 获取通用对账对象, 将流水记录转换为对账对象
*/
public abstract List<PayReconcileDiffRecord> generateDiffRecord();
public abstract List<GeneralReconcileRecord> getGeneralReconcileRecord();
}

View File

@@ -1,7 +1,7 @@
package cn.bootx.platform.daxpay.service.param.reconcile;
import cn.bootx.platform.common.core.annotation.QueryParam;
import cn.bootx.platform.daxpay.code.PayReconcileTradeEnum;
import cn.bootx.platform.daxpay.code.ReconcileTradeEnum;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.experimental.Accessors;
@@ -22,7 +22,7 @@ public class ReconcileDetailQuery {
/**
* 交易类型
* @see PayReconcileTradeEnum
* @see ReconcileTradeEnum
*/
@Schema(description = "交易类型")
private String type;