跳至主要內容

对账系统设计

HeChuangJun约 972 字大约 3 分钟

渠道数据处理模块

负责第三方支付渠道对账文件的下载,解析,存储数据到数据库
定时在支付渠道网站(微信支付宝open in new window,ntnstqryx招行)调用下载对账文件接口下载对账文件(SFTP)

格式:支付宝cv、微信txt、xml、xls
根据渠道特性、对账文件格式实现下载与解析接接口
需要提取的信息:

商户号、商户订单号、渠道流水号、交易日期、金额、手续费、退款原订单号、退款金额

同一渠道多个商户号多份对账文件
网络异常导致数据不完整,对账文件重复下载
每个渠道下载文件时间不一样

数据处理模块

提取前一日本地支付成功的流水数据和上一模块入库对账单的流水数据
为了减少数据库的压力,流水数据只要包括交易时间,金额,交易订单号,渠道返回流水号等必要字段
最好用备库查询。数据量大的情况下会拖慢主库,影响在线的支付交易

数据核对模块

本端与对端数据核对订单号与金额,记录本端的差异数据
//获取某一渠道本地支付数据
List<LocalDataDT0>localDatalist= getLocalPayData("支付渠道编号""账期");
//获取某一渠道对账单数据
List<ChannelDataDTO> channelDataList= getChannelPayData("支付渠道编号""账期");
Map<string, LocalDataDTO> localDataMaplocalDataList.stream().collect(collectors.toMap(localData-> localData.getorderNo()+localData.getAmount()00));
Map<String, ChannelDataDTO> channelDataMapchannelDataList.stream().collect(Collectors.toMap(channelData-> channelData.getOrderNo()+channelData.getAmount()0o));
List<LocalDataDTO>localDiffDetails = new ArrayList();
//用本地账单数据的键值逐笔核对
LocalDataMap.forEach((key,localDataDTO)->{
  if(channelDataMap.containsKey(key)){
    channelDataMap.remove(key);
  }else {
    //渠道账单数据不包含本地数据键值
    localDiffDetails.add(localDataDTO)
  };
})
//若 channelDataMap 里面还有元素将其放入 channelDiffDataList
List<channelDataDTO> channelDiffDatalist = new ArrayList>(channelDataMap.values());
//记录差异数据
recordDiffData(localDiffDetails, channelDiffDataList);

差异数据处理模块

数据核对模块可能产生三类差异数据
金额不一致(人工判断)
本端多账:本端数据存在,对端数据不存在
存在跨日情况:对账文件缺少跨日订单,本端T日数据存在夸日订单。可以将这笔数据挂账,T+1工作对账时账单会相应多出数据,产生对端多账的差异数据。然后差异处理模块将前几日差异数据都提取出来,核对本端多账数据与对端多账数据。若核对一致,将两笔差异状态都更新成处理完成。若无剩余差异数据,当天账单平账

int range = 7;
//查询对账日期到range天差异记录 包括local和非local
List<DiffPayData> allDiffDatas = queryDiffDatas(new Date(),range);
//本端多账
Map<String, DiffPayData> localDiffDatas = new HashMap();
//对端多账
Map<String, DiffPayData> remoteDiffDatas = new HashMap();
//根据类型分为本端差异数据与对端差异数据
for(DiffPayData diffData :allDiffDatas){
  if("local".equalsIgnorecase(diffData.getType())){
    localDiffDatas.put(diffData.getOrderNo()+ diffData.getAmount(), diffData);
  }else {
    remoteDiffDatas.put(diffData.getOrderNo()+ diffData.getAmount(), diffData);
  }
}  
//核对上的差异数据
List<DiffPayData> checkSucessDatas = new Arraylist<>();核对失败的差异数据
List<DiffPayData> checkFailedDatas = new ArrayList<>();
localDiffDatas.forEach((key,diffPayData)-> {
  //本端多账与对端多账键值相等
  if (remoteDiffDatas.containsKey(key)){
    checkSucessDatas.add(remoteDiffDatas.remove(key));
    checkSucessDatas.add(diffPayData);
  } else {
    checkFailedDatas.add(diffPayData);
  }

});
checkFailedDatas.addAll(remoteDiffDatas.values());
//将成功对平的差异账状态修改为处理成功
updateSuccessDiffData(checkSucessDatas):
//判断平账
if(checkFailedDatas.size()>0){
  System.out.println("不平账");
} else {
  System.out.println("平账");
}

对端多账:对端数据存在,本端数据不存在
测试、生产环境共用第三方渠道,测试环境订单出现在对账单中。忽略即可
本端存在成功状态的订单。调用第三方渠道提查询订单状态接口。成功则更新订单状态,然后将差异数据状态更改为处理成功。最后重新对账