2017-02-16, 补充对账系统架构图

支付系统的开发和运维同学,最常见的投诉,应该就是客户说,某渠道已经扣款钱了,你看,回执都有了,可是买的东西怎么还没得到呢? 往往开发同学一查,还真是这么回事。在系统中明明记着这个订单是未支付状态呢。 那怎么办? 这就得从渠道拿对账单做一个核对。 这里要说的,就是怎么对账了。

一、对账的定义

那什么是对账?

对账指对前一个清算周期内的交易信息进行核对,以确保交易信息的一致性和正确性。

既然是对账,那首先回答的问题就是对什么账? 从会计角度来说,对账主要包括4个内容: 对账单

可以说,对账是支付系统最头疼的事情。每一笔交易,都要做到各参与者的记录能够吻合,没有偏差。对账系统的工作,是发现有差异的记录,即轧帐;然后通过人工或者自动的方式,解决这些差异,即平帐。

二、账证核对

账证核实是对账的第一步,在会计上,指将各种账簿,包括总账、明细账、分户账、日记账的记录和有关会计凭证,包括记账凭证和原始凭证,进行核实,做到账证相符。 核实支付系统和业务系统之间的记录是一致的。

三、账账核对

账账核对主要是账务、会计系统内部对账,内容包括:

  1. 借贷核对: 使用复式记账法,原则就是有借必有贷,借贷必相等。 所以借贷核实是账账核对的最基本步骤。
  2. 总分核对: 总分类账中本期借贷发生额总额、

四、账实核对

简单所,对电商系统来说,每一笔交易,在所有相关主体侧都要能对得上:

那有哪些记录需要对账? 目前主要是两个:一个是交易记录;一个是退款记录。 这里以交易记录的处理为例,退款记录可以类似处理。

一、对账处理流程

一般来说,对账流程涉及到如下步骤: 渠道对账单下载、本地交易记录准备、轧账、平账。

1.1 渠道对账单下载

银行,第三方支付,银联等,基本都会提供对账单下载的功能。不过也有少数工作做不到位或者太到位的银行,只提供账单查询后台,不提供对账单下载功能。 对开发人员来说,这里有几个坑:

看一下第三方支付的对账单情况:

渠道 对账周期 账单提供方式 账单文件格式
支付宝 每天 2:10 HTTPS XML
支付宝退款 每天3:10 HTTPS XML
百付宝 每天7:00 FTP TXT
百付宝退款 每天7:00 FTP TXT
微信支付 每天10:30 HTTPS TXT
微信退款 每天10:30 HTTPS TXT

银行直连的对账情况

银行 对账形式 对账周期 打款周期
交行 接口/商户对账系统 日对账 日结(T+1)
建行 接口 日对账 日结(T+1)
工行 登录网银的方式手动下载 日对账 日结(T+1)
浦发 信用卡登录自助平台获取对账文件,
借记卡通过接口形式提供对账文件
日对账 日结(T+1)
农行 银行定时推送对账文件 日对账 日结(T+0)
中行 银行定时推送对账文件 日对账 日结(T+1)
招行 银行定时推送对账文件 日对账 日结(T+1)

1.2 渠道对账单标准化

找个例子大家看看, 比如微信的对账单,他是csv格式的,包括如下信息:

  1. 交易时间:这是在微信侧的支付完成的时间。 这个时间会成为一个陷阱。

  2. 公众账号ID,商户号,子商户号,设备号: 这些信息需要做验证,确保是自己的单子,不要让微信把老王家的单子也给发过来了;

  3. 微信订单号,商户订单号: 这两个是对单的核心。前者是微信侧产生的订单号,在微信支付接口返回值中有。但是万一收不到这个返回值,那在本地记录中可能就空了。 后者是我们发送给微信的订单号,一般用这个来做对单依据。两边的数据中都会有这个值。

  4. 用户标识,交易类型,交易状态,付款银行,货币种类,总金额,企业红包金额: 这几个就是对单的核心字段,必须确保双方是一致的。

  5. 商品名称,商户数据包,手续费,费率:这些是可选验证。

微信对账单

而某宝的对账单,是文本格式的,用空格隔开。他们家的就简单很多,只有商户订单号,交易流水号,交易时间,支付时间,付款方,交易金额,交易类型,交易状态这些字段。 某宝对账单

由于每个渠道的账单格式都不尽相同, 在得到账单后,下一步是对账单做标准化处理,这样轧帐以及后续工作就可以统一处理了。 标准化后的账单数据可以放在文件系统或者数据库中。这取决于交易数据量。每天百万以上的量,还是使用文件系统,比较合适。数据库操作相对比较慢,也浪费资源。 基于文件系统的标准化涉及如下内容:

文件格式标准化 统一使用csv或者json或者xml格式。如果是使用hadoop或者spark来对账,使用csv是个不错的选择。

文件存储统一化 文件目录,文件名都需要遵循统一命名规范。

为了加快处理速度,我们使用hdfs作为文件系统,有利于后续的对账的处理。

1.3 本地交易记录准备

本地交易记录的准备,总的来说有如下方法:

由于交易记录是支付系统核心数据,有大量的应用,如信用、风控等,都需要交易记录数据。这些应用对交易记录的需求还不完全一致,为了提升性能, 交易记录会使用异步的方式来将数据投递给使用方。 交易记录在入库时,投递消息到消息系统中。使用方监听这个消息,一旦收到新消息,则从交易记录库中查询数据,获取数据并更新到库中。关于此类数据同步的文章不少,这里就不详细介绍。

1.4 轧帐

轧帐是按照客户订单号来比较本地交易记录和渠道交易记录是否一致。从算法角度,是计算两个数组的差异。在单机运行时,可以采用的算法不少,这里不详细介绍。 我们推荐采用mapreduce来轧帐,这有个优势,可以按照订单号将渠道提供的记录和本地记录shuffle到同一个reduce处理上,这样就可以很容易进行数据比对。 轧帐中最大的坑,莫过于切分点的问题。比如以整0点为切分点,那存在一个问题,本地23:59发起的交易,到了渠道侧,可能会在00:01处理,这一笔交易变成第二天的帐了。实际处理中,一笔交易在渠道侧处理,花上几分钟都有可能。 对于切分点附近无法确认的帐,做一个时间窗,在时间窗内的数据,留待第二天对账时继续处理。

1.5 平帐

发现两边不一致的数据,那应该如何处理?数据量不大时,记录起来,人工甄别就行。但如果数据量很大,每天上千条,人工处理就成本太高了。这个没有统一的处理方法,需要根据有问题的数据,做个分析,然后做自动处理。 针对交易记录的对账的处理,主要有如下情况:

针对退款的对账处理,主要有如下情况:

二、对账架构

基于微服务的对账系统实现的一个参考架构如下: arch

2.1 对账单下载

对账单下载组件每天定时触发,从支付通道服务器上下载对账单。 目前主要有HTTP(S)和FTP两种对账单下载方式。 技术选型上,HTTP(S)用apache httpclient即可实现链接池和断点续传, FTP也可以使用Apache Commons Net API。 不管是哪一个,都需要设置重试次数和链接超时间。重试次数和间隔的设置需要小心,重试太频繁,容易把服务器打死.;时间间隔太大,又会阻塞后续处理步骤。5~10分钟是一个合适的重试间隔区间。链接超时指在服务器出现问题时,连接在指定时间内获取不到数据即自动断开。这个很容易被忽略。我们有一次系统出问题,是渠道侧的FTP假死后重启,导致我们的客户端挂住,一直在等待重新链接。此外,注意,有些对账单下载是支持分页下载的。

2.2 对账单转换

将对账单转换为标准格式的账单,为对账Mapreduce任务执行提供支持。每个渠道的对账单格式不一,需要分别开发转换程序。 转换程序主要就两个操作: 解析源文件、转换成标准格式并输出。

2.3 轧账MR

如上所述,轧账MapReduce程序在Hadoop上运行,以交易号为Key,核对渠道订单和本地交易记录之间的差异,输出差异记录。最后将差异记录导入到差异表中。

总之,对账工作,即复杂也不复杂。需要细心,对业务要有深入的了解,并选择合适的架构。


感谢您对本文的关注,如需要及时收到凤凰牌老熊的最新作品,或者有相关问题探讨,请扫码关注“凤凰牌老熊”的微信公众号,在公众号里留言或者回复,可以尽快处理,谢谢。

本文欢迎转载,转载时请注明本文来自 微信公众号“凤凰牌老熊”。