对账那些事儿

后台-系统设置-扩展变量-手机广告位-内容正文顶部
随着互联网行业的兴起,线上支付已经逐步取代了传统的现金交易,而对于涉及支付相关的系统来说,最棘手的事情莫过于系统间的对账工作了,因为支付系统中所有跨系统或是服务的数据交互,理论上都应该进行对账,即系统中产生的每一笔交易,都需要相关上下游系统的交易数据一致。 那么,什么是对账?对账系统在这个支付服务中所承担的职责又是什么? 笔者就此分享我们在对账系统建设方面的一些实践经验。        
   

什么是对账?

 
传统的对账又称为核对账目,是指在会计核算中,为保证账簿记录正确可靠,对账簿中的有关数据进行检查和核对的工作。在银行或者第三方支付中,对账指对前一个清算周期内的交易信息进行核对,以确保交易信息的一致性和正确性,一般都是第二天在银行或者第三方支付公司对前一日交易进行清分,生成对账单供商户方进行下载,并将应结算款结算给对应商户系统。
 

对账系统


对账系统,是支付体系中最重要的一环,也是保证交易、资金安全的最后一道防线。通过系统的使用,不仅可以提升对账效率和解放人工对账工作量,而且还可以快速扩展其他支付类渠道,它的职责就是替代传统的人工对账,解放人工对账的工作量,提升对账效率,实现系统自动化。

以笔者多年前参与的项目为例,对接了多个银行渠道系统进行代收代付业务,在实际应用场景中,生产交易系统总会存在因掉单或者系统突发异常导致的同一笔交易在支付系统与银行系统的信息不对称,使得支付系统在银行的账户资金实际发生额与应该发生额不一致,比如长款(银行多结算给支付系统)和短款(银行少结算给支付系统)。
 
而随着业务的体量不断增加、定制化与个性化的业务场景不断细化,接入更多的支付渠道已成为未来可预见的必然趋势。在这样的前提下,人工进行账目核对已经很难达到财务部门所提出的要求,如何依据软件工程设计理论和结合系统架构现状,设计一款满足对账功能、安全可靠和易于维护的高质量的对账系统,显得尤为重要。
 

如何高效对账


通过对既有系统以及其他渠道系统进行研究发现,对账的通用流程大致分为如下步骤:  渠道对账单下载、对账单文件解析、对账(轧账/平账)。  对账系统是一个以定时任务为主的系统,我们在系统架构方面基于分布式任务框架elastic-job与自定义任务逻辑相结合的方式进行设计,其中elastic-job作为无中心化的分布式定时调度框架,其优势就是保证后续任务可以在任意节点中执行。业务逻辑架构如图1所示:
 
   
图1:对账系统架构
 

各个功能模块功能:
 

1、对账单下载

 
对账单下载组件根据各个支付渠道不同的对账周期定时触发,通过支付渠道提供的方法获取相应的对账文件。目前主流的获取方式大致分为  HTTP(S)  和 FTP  两种下载方式。

 从技术实现的角度来说,我们可以将其设计为工厂模式,针对不同的支付渠道对应不同的下载类,如果是http接口可以将获取到的文件写入到对账单中,用于后续解析操作,如果是对方提供的是ftp服务器,则需要将服务器中的对账单下载至本机。  在这个环节中,为了防止单一应用宕机导致系统产生异常,对账单下载至本地后会同步将其上传至DFS服务器中,方便后续步骤中的定时任务可以从DFS服务器中获取到对应的对账单文件。  这个环节的主要编码工作包括通用ftp工具类、http(s)工具类的编写,并会涉及到IO读写相关的实现。

 在下载对账单的步骤中,很多同仁都踩过不少坑,也针对共性问题进行了总结,那就是“HTTP(S)用apache httpclient即可实现链接池和断点续传功能,亦可使用Apache Commons Net API实现FTP的上传与下载。但不管是哪一种方式,都需要谨慎的设置重试次数、重试间隔以及链接超时时间,其原因是重试太频繁容易导致服务器夯死;时间间隔太大又会阻塞后续处理步骤,评估下来5~10分钟是一个较为合理的重试间隔区间。”
 
当然,在实际应用种如何选择这个重试的区间,可能需要我们在开发时结合自身系统的特点制订出符合自身要求时间范围。
 

2、对账单转换

对于不同的支付渠道,其对账单的文件格式也略有不同,包含XML、Excel、Text、csv等不同形式。

如果完全按照下游渠道系统提供的原始账单格式进行对账单存储,那么对于后续的账单数据处理逻辑就会随着下游渠道的增加而不断的扩展,并且每增加一个新的支付渠道,账单存储表都需要根据渠道账单结构新建,使得开发工作量大幅增加。因此,从对账模块来看,为了让后续的对账操作变得统一,需要格式化不同形式的对账文件,并对其进行标准化处理显得尤为重要。

 由于支付渠道系统在设计上存在差异性,我们需要为每个渠道开发一套对应的解析规则,可能包含计量单位的转换、交易日期的格式化、交易结果的映射转换等操作,对账单转换模块的职责就是将各式各样的数据源解析为标准格式后插入交易记录表中,用于后续对账工作。
 
在导入数据的过程中,我们选择使用批量导入操作,  一方面可以避免重复记录导致的脏数据,另一方面也可避免逐行入库操作过程中因每次重新建立网络连接、关闭连接造成的效率低下。  
 

3、对账模块

在对账模块中,通常以系统调用方产生的交易订单号作为关联条件,使用事先定义好的比对规则核对对账文件中的记录与本地流水信息,得到一个交集与两个并集。这两个并集中的数据即为对账过程中产生直接的差异数据,而交集部分的数据集说明根据订单号是可以获取到对应记录,当然,我们还需要对其金额以及支付结果等信息进行比对。
 
 在对账的过程中可能出现某些系统无法匹配的异常数据,为了便于分析,我们需要将三个集合中出现的长款、短款、金额不一致等问题记录在差异表中,并同时登记产生差错的类型。  对于某些类型的差异数据,对账系统在后续的跑批中能够自动化处理,一致化交易数据。  而对于那些系统无法处理的异常,则需要人工干预排查问题原因,并寻找合理的解决方式。  此外,由于各个支付系统的日切时间会存在细微的差异,对于可能在当日的账单数据中没有匹配到待对账的数据需要我们进行滚动对账。
 
图2:交易流水表与对账单表逻辑关系
   

4、差错处理

 
差错处理的目的就是分类记录对账过程中出现的异常数据,并通过系统自动处理或者人工干预的方式将账务对平,常见的账务处理方式有  挂账、登账、调账  。
 
补单:  通过人为干预方式,将原有业务进行下去,如通过接口人工干预订单状态  
 
挂账:  对于不平账单,先挂起,等查明后再进行相应处理  
 
登账:  会计记账,伴随虚拟资金从一个账户向另一个账户转移的过程(原始凭证)
 
 
针对可能出现的情况分类,处理方式分为如下几类:
 
(1) 本地交易流水中支付状态为未支付,但是支付渠道对账单中显示记录为已支付。  这可能是由于本地未正确接收到支付渠道异步通知的消息所导致。 针对这种情况,我们通过补偿机制同步交易未决的流水信息来尽量避免这种情况的出现,但是特殊情况下,亦可通过数据维护的方式将本地支付状态修改与渠道侧一致,并响应后续的流程处理等。
 
 
(2) 本地交易流水与支付渠道支付状态一致均为已支付,但是金额不同。这个情况一般以支付渠道的金额为准,需要人工核查自有系统的代码是否存在缺陷,导致交易过程中金额计算出现了误差,出现记录失真的情况。   
 
 
(3) 本地流水中已支付,但是支付渠道中无记录。  在排查这类问题的时候首先要判断是否因为交易跨天所导致的,因为交易系统与第三方支付渠道的过程中恰好跨天,这样就会导致前一天的数据出现一笔短款记录,而后一天又会出现一笔长款记录,这个时候就需要进行补对账操作,来补偿那些由于某些原因未对账的数据,具体流程如图3所示。  
 

 

图  3:  滚动补对账流程
 
总体来说,我们发现不同渠道的对账工作会存在细微的差异,但是具体的步骤却又具有共性。细节往往决定事情的成败,简单的业务反而需要更加细心去处理可能存在的异常情况。比如,下载过程中断线后如何操作,重试次数如何设置以及超时时间的设定都需要结合实际业务,并深入熟悉其背景后选择最优解决方案。

另外,从技术角度发现对账过程中逐行比对算法效率较低,但目前仍未找到更为合理的算法进行替代,如采用数据库INTERSECT、MINUS的方式进行比对则将压力转嫁到了对数据库侧。当业务呈井喷式增长时,大量的交易数据需要进行对账操作,也会导致数据库负荷较高,通过读写分离以及避开交易高峰等空间换时间的操作虽然可降低生产系统的风险,但仍没有从根本上彻底解决问题。后续优化重构的过程中也会尝试使用Redis等NOSQL数据库进行对账操作,如使用Redis的set集合的sdiff功能,返回两个集合之间的差异集合,比对解析后的对账单记录和本地自有记录的差异,降低对生产交易中的mysql数据库的压力,并且Redis数据库在扩展上也相对容易。

当然,这个方案是否是最优解仍需要验证后才可知,如何在特定的情况制定出一套最佳方案仍需要我们在漫漫长路上不断探索与研究。

本文作者:兴业数金供应链金融事业部技术团队 张佳鹏
 
特别声明:

文章来源:兴业数金公众号(ID:gh_b700b775ae81)

原文链接:https://mp.weixin.qq.com/s/2tiHlWT_6iXmIRpxnlwCww

如有侵权,请联系删除

 
 

未经允许不得转载:RPA中国 | RPA全球生态 | 数字化劳动力 | RPA新闻 | 推动中国RPA生态发展 | 流 > 对账那些事儿

后台-系统设置-扩展变量-手机广告位-内容正文底部