mirror of
https://gitee.com/dromara/dax-pay.git
synced 2025-09-02 10:36:57 +00:00
feat 对账开发
This commit is contained in:
@@ -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","退款"),
|
@@ -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;
|
||||
}
|
@@ -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);
|
||||
|
@@ -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 = "完成时间")
|
||||
|
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -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);
|
||||
|
||||
}
|
||||
|
@@ -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;
|
||||
}
|
||||
|
@@ -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());
|
||||
}
|
||||
|
@@ -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() {
|
||||
|
@@ -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;
|
||||
|
||||
|
@@ -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;
|
||||
|
||||
|
||||
}
|
@@ -0,0 +1,9 @@
|
||||
package cn.bootx.platform.daxpay.service.core.payment.reconcile.domain;
|
||||
|
||||
/**
|
||||
* 对账差异内容
|
||||
* @author xxm
|
||||
* @since 2024/3/1
|
||||
*/
|
||||
public class ReconcileDiff {
|
||||
}
|
@@ -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){
|
||||
|
||||
}
|
||||
}
|
||||
|
@@ -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());
|
||||
}
|
||||
}
|
||||
|
@@ -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());
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -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();
|
||||
|
||||
}
|
||||
|
@@ -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;
|
||||
|
Reference in New Issue
Block a user