2023年参与某城市通项目,对接某地农商行免密代扣,作为平台商户对接后,可以对介入的商户做分账,这里就涉及到对账逻辑的问题。
对账逻辑参考了网络上部分博客想法,还参考了龙果学院的部分代码逻辑
1、下载银行对账单
对账单下载一般在内网完成,可以使用sftp或者ftp方式。一般对账发起是在凌晨,请求对账指令发出后,需要经过一段时间银行内部处理,才能生成对账单。
2、解析银行对账单
对账单的格式可能不同,较多的是txt文档,内部使用逗号或者其他符号分割。内容通常包括了总金额、总交易笔数、总退款笔数,以及每一笔交易(退款也算)时间、金额、是否退款、交易类型(区分交易场景等);
3、对账逻辑
-
查询平台(平台指的是本地支付平台)的所有记录
-
查询平台的所有交易成功的记录
-
初始化差错列表List
-
初始化缓冲池表List(缓冲池的用途是存储平台长款的记录)
-
初始化需要从缓冲池删掉的(主要用于以银行为基准对账时候,如果在缓冲池中查询到,就可以删除调。之所以是另外新初始化一个,就是因为从对账角度,进账和销账两个互相独立)
-
以平台数据为准对账(传入平台成功订单列表、银行对账单列表)
-
设置平台交易总金额、平台总手续费、平台订单总数为0
-
遍历平台交易列表(每个订单获取到后)
-
累计计算平台交易总金额、总手续费、订单总数
-
如果匹配到银行对账单中订单号,那么校验金额和手续费(这里不用校验付款方、收款方)
- 如果比较金额后,平台的金额多,那么创建差错记录,放入到差错记录列表中。(差错记录标记为平台爱长款)
- 如果比较金额后,平台金额少,那么创建差错记录,放入到差错记录列表。(差错记录记录标记为平台短款)
- 如果订单手续费不匹配,加入到差错列表中(差错记录标记为手续费不匹配)
-
如果没有匹配到,此记录放入到缓冲池记录列表中。
-
-
生成批次,统计的平台交易总金额、总订单数、总手续费生成批次对象。
-
以平台数据为准的对账结束
-
-
以银行对账单数据为准的对账开始
-
设置平台交易总金额、平台总手续费、平台订单总数为0
-
遍历银行对账单交易列表(每个订单获取到后)
-
如果匹配到平台数据的的订单号,
-
判断状态(交易成功、失败、取消、待支付),是否和平台对应的订单状态不同;这里只需要比较下状态就行,因为金额和手续费在上面的以平台为基础的比对中已经做过比对了。
-
如果不状态匹配
记录差错。放入到差错列表中;(标记为平台短款,状态不符)
比对金额,如果平台金额多,那么记录差错,放入到差错列表中;(标记为平台长款,金额不符)
比对金额,如果平台金额少,那么记录差错,放入到差错列表中(标记为平台,平台短款,金额不符)
比对订单的手续费,如果不匹配,记录差错,放入到差错列表中。(标记为手续费不匹配)
-
如果状态匹配,不做任何操作。
-
-
如果没有匹配到平台订单数据
-
去缓冲池查找。前提是缓冲池需要有数据
-
如果缓冲池匹配到。
- 累计平台交易总金额。累计平台总手续费。
- 匹配订单金额,如果金额不匹配,平台金额多,那么记录差错,放入到差错记录表(标记为平台长款,金额不符)
- 如果金额不匹配,平台金额少,那么记录差错,放入到差错记录表(标记为平台短款,金额不符)
- 匹配订单手续费,如果手续费不符合,记录差错,放入到差错记录表(标记为手续费不匹配)
- 删除缓冲池中匹配的记录(放入到一个list中,标记为已经匹配的list)
-
如果缓冲池中没有匹配,那么记录差错,放入到差错记录列表(标记为平台漏单)
-
统计批次对账的数据。交易额=以平台为准的交易额+本次统计平台交易额;统计交易订单数=以平台为准的交易订单数+本次统计的交易订单数,统计费用总额=以平台为准统计的费用额+本次统计的额度;统计差错总数=以平台为准统计到 差错数+本次批次统计的差错数。
-
-
-
保存统计数据
- 开启事务(数据库事务不是分布式事务)
- 对账批次保存(list存储到数据库)
- 差错记录保存
- 缓冲池记录保存
- 从缓冲池删除已经匹配记录
-
生成业务订单:先根据参数中商户编号和商户订单号,生成业务订单号(平台订单号)
BANK_MISS("银行漏单"), // 银行不存在该订单
PLATFORM_MISS("平台漏单"), // 平台不存在该订单
PLATFORM_SHORT_STATUS_MISMATCH("平台短款,状态不符"), // 银行支付成功,平台支付不成功(比较常见)
PLATFORM_SHORT_CASH_MISMATCH("平台短款,金额不符"), // 平台需支付金额比银行实际支付金额少(基本不会出现)
PLATFORM_OVER_CASH_MISMATCH("平台长款,金额不符"), // 银行实际支付金额比平台需支付金额少
PLATFORM_OVER_STATUS_MISMATCH("平台长款,状态不符"), // 平台支付成功,银行支付不成功(基本不会出现)
FEE_MISMATCH("手续费不匹配");