支付系统总结 ( 收单,收银,资产交互,账务 )

本文详细介绍了支付系统的核心挑战,包括资金安全、并发控制、幂等性和账务错误处理。重点阐述了支付通架构、账务交换层、支付网关和账户系统的职责。同时,讨论了日切检查、外部核对清算、内部核对等资金安全措施,以及上游调用的最佳实践。此外,还涉及到了分布式事务、非数据库事务的对比,以及转账、提现、双边账等功能的设计。文章最后探讨了高并发变更、互斥关单和时效关单等问题,并提出了配置产品化和参数化的解决方案。
摘要由CSDN通过智能技术生成

龙果支付系统(roncoo-pay)是国内首款开源的互联网支付系统. 口碑较好, 但是应该不是单边账和分布式账务. 

 父 :  人人都是面试_个人渣记录仅为自己搜索用的博客-CSDN博客

平台建设通用的能力 ( 收单文章中也提到部分 )

技术设计金字塔 包含了实体设计文章另外一篇文章: 支付系统-收银台系统总结

本文原地址: 支付系统-帐户系统总结

子文章 平台系统建设所具备的能力_个人渣记录仅为自己搜索用的博客-CSDN博客

相关文章 支付产品/商业能力 支付业务和支付商业能力_个人渣记录仅为自己搜索用的博客-CSDN博客

目录

先说核心挑战和技术

一 支付通架构图( 收单 资产交换 账务 网络):

   1.2 账务交换层模块职责:(资产交换 付款方(内部,外部) 2 x 2 收款方(内部,外部) , 如果纯 外+外 独立一个系统 )

   1.3 支付网关职责:

   1.4 账户系统职责:

二 主要流程图

三 实体设计

    2.1账户系统 实体设计: 

    2.2收银台系统实体设计:

资金安全

上游调用最佳实践

数据库事务 / 非数据库事务对比

  多账务操作

   收单系统的操作

        分布式事务+本地数据库事务 :

         无分布式事务 + 两个前后数据库事务:

四 亮点功能

      1.  转账的额度控制通过变量传递进来.

      2.  帐户的变动和流水保存处于同一个事务中.

      3. 提现:

      4. 双边帐

      5. 帐户的高并发变更设计:

      6. 互斥关单问题. 

      7. 非分布式事务下的时效关单问题.

附录:


先说核心挑战和技术

  核心挑战:  资金安全, 细化来说, 并发, 幂等, 资金流错误, 业务错误.

  核心技术:  1. 分布式锁在以下两个场景中均是前提,1.1.解决并发竞争, 1.2.幂等二判或者insert场景.  特别是锁父维度, 操作子维度的场景. 通用解决方案是任何操作都有流水,抽象化. 类似发消息有流水,事务ack后查询能够统一.

                    2. 线上流量录制,回放,回归技术.
                    3. 端到端结合agentMock+录制回放测试平台, 发布覆盖率平台.
                    4. 核对.

                    5. xts分布式事务框架, 账号的systemAmout 事务技术, 账户操作都要有流水

   复杂业务:

                1. 根据多次入金后,可能超限, 2. 进行聚合支付, 3. 退款有两种 3.1一种是基于支付的退款, 3.2 另外一种是多出的金额退款. 且要满足先入先扣,先入先退的原则. 4. 退款要先收单, 时间到期后, 告知退款哪些成功,哪些失败.
               三张表. 1.主账户表(等价托管户).锁单 2. 出入金流水表 3.支付出金关联入金记录关系表,含退款信息.  4.支付单表-有支付流水id外键,已退款金额.

一 支付通架构图( 收单 资产交换 账务 网络):

     1.1 收单系统 -收款方信息,订单本身信息

       收单系统总结 - 内含幂等,事务,状态的非常好的例子_fei33423的专栏-CSDN博客

            1. 完成 账户交换 ,账单, 计收费, 收银台 等系统串联
            2. 完成退款等资金校验
            3. 完成一单多收等相关逻辑的聚合.
            4. 完成基金等特殊资产的串联, 不能直接购物, 赎回等概念

                收单和推进 分开且可(同步/异步) , 分开的原因是如果推进失败了, 我方还可以重试,但无论如何上游都需要重试/关单. 所以没必要收单,特别是退款单.  退款单收单的好处是用户的感受更好点.

     1.2 收银 - 付款方信息
     1.3 资产交换信息

                1.支付 - 1.1基于支付的退款, 1.2基于支付的继续支付(担保支付)  - 2 2.1单节点的冻结, 2.2 解冻   进一步衍生的端到端能力(配置能力(资产交换业务化,每次业务都要配置,太重),参数透传[建议])

   1.2 账务交换层模块职责:(资产交换 付款方(内部,外部) 2 x 2 收款方(内部,外部) , 如果纯 外+外 独立一个系统 )

        & 内部又分为 清算系统, 账户系统

        & 接受对业务系统的订单支付.充值请求

        & 账户之间转账

        &  接受业务系统的提现请求

        & 接受业务系统的退款请求(对上面几种业务)

   1.3 支付网关职责:

           负责和渠道(支付宝,微信,银联)交互,记录流水号,对账

           https://blog.csdn.net/fei33423/article/details/121859542

   1.4 账户系统职责:

         & 记录账户信息

         & 保障账户变动原子性和事务性.

         & 记录账户变动流水

   1.5 清算系统

         清算系统和网关的解耦. 因为有些只是消息,对账,不需要清算.

         清算的意义在于清算是和业务资金操作是一个整体. 清算发送了,代表业务成功执行了. commit阶段提交事务. 但是网关的流水肯定是有的.

二 主要流程图

1. 充值

    有个支付回调

2. 转账

2. 提现

  先减款,再提现.失败加款

三 实体设计

    2.1账户系统 实体设计: 

  

          帐户表 账户信息.

          Account_statement: 1.记录账户变动流水记录. 2.保存法幂等控制

复式记账内含分布式事务下的账务设计 复式记账和本文下面的对账清算相关. (分布式账户设计)

       事务下的可见性 

    2.2收银台系统实体设计:

        

         交易表: 记录外部输入的外部流水号和内部流水号相关信息

资金安全

支付系统资金安全

   核对总结文章 微服务 支付 核对 对账系统_个人渣记录仅为自己搜索用的博客-CSDN博客

   下面侧重会计视角,自核对,内外核对等

  1.  日切检查 (内部复式记账正确 - 账账,账流水和户正常 - 账户) 如果不平,就比较麻烦. 你不知道哪个和哪个不平. 所以每个账户变动都需要有个主流水号 最好是两两变动. 全网根据主流水号进行groupBy 找到那笔没有平的主流水号. 所以这个时候就需要有个 资金交换核心. 

  2.  外部核对 清算 - 外部资金流水(外部银行或者内部acs备付金)

   3. 作为会计人员对于账帐核对、账证核对、账实核对、帐表核对四种账目核对. <<基础会计学 对账和结账 一章>> 四大核对 by fei33423

       4. 核算 央行 支付机构 备付金 对账10大文件_个人渣记录仅为自己搜索用的博客-CSDN博客 

    5. 内部核对, 例如业务流程因为某种原因,没有走下去 ,用户充值了,但是挂在某个中间户上. 上面几个核对都没有问题.  ( 有时候清算会有问题,卡在最开头的话,没有报清算记录 ) , 这时候就需要业务系统自己来核对了. 5.1 中间状态的告警. 临时/异常终态   5.2 约束核对,例如退款总金额.

上游调用最佳实践

     提供的是非分布式接口,那么业务方需要"调重对关新" :

     调: 调用 

     重: 定时任务重试

     对: 和支付系统对账 (支付系统分为收单式/非收单式/非数据库事务式) ,如果是非收单式,没有数据则重试.有就代表不用重试. 如果是收单式,没有数据则重试.有就代表不重试. 如果是非数据库式,只要自己没有拿到结果,就重试. 下游做到支持幂等重试,单边账,(如果没有分布式事务, 一次转账包含三个事务. 依赖幂等重试,将所有转账操作完毕. 不具备回滚能力.)

     关: 关单 . 注意processing状态是不支持关单的. 如果支付系统没有实现互斥关单的能力. 关单需要超过30秒后才能关单.   

      新:使用新的流水号

关单接口, 支付系统实现的时候要二选一:

  1. 关单后下游再异步通知时/对账通知时需要原路逆向.   or 2.就需要级联关单,调用支付系统自身的下游关闭该单子.

数据库事务 / 非数据库事务对比

  多账务操作

        分布式数据库事务

                最底层有个减款失败,会导致所有流程都逆向回滚. 

        非数据库事务

                 需要自建一个定时任务进行事务检测,回滚, 回滚互斥插入(实现业务版非框架版的分布式事务管理能力,定时任务)( 避免空回滚然后还要避免事务悬挂,都是因为回滚先来的问题,方法: 30秒 或者 回滚和正向执行共用插记录,回滚状态为特殊的空回滚状态. 或者另外一张记录表 )(类似 互斥关单逻辑 )

   收单系统的操作

        分布式事务+本地数据库事务 :

                状态设计是 INIT (收单) processing(下游肯定已收单)  success .
                关单操作

                  * init状态,直接并发关单

                  * processing状态 比较复杂. 方案 1.先主动调用下游close  方案2: 不能被业务方close. 只能等待下游的回调.(最反逻辑,INIT和processing状态处理逻辑不一致)  方案3: 并发直接关闭,等下游回调回来逆向操作. 最复杂但最通用.

         无分布式事务 + 两个前后数据库事务:

                 状态设计 INIT(收单) beginCalling(下游未收单) afterCalling(下游已收单,内部已成功)  success.  如果是传统的 INIT processing ( 下游有没有收到未知, 不能死等下游的消息,需要有对账重试机制)  success
               关单操作
                 * init状态,直接并发关单

                 * 在processing状态可以close, 先主动调用下游close 或者 下游回调回来之后逆向操作即可.

四 亮点功能

      1.  转账的额度控制通过变量传递进来.

              转账停留在中间环节的,重试逻辑. 单边帐.

              传统信用卡,每个用户的额度不同,都是通过往卡里加钱来提升额度. ( 1. 额度增和账户增保持事务一致. 2.额度减和账户减保持事务一致,可能减款失败,如果这个用户本身已经使用了很多.)

      2.  帐户的变动和流水保存处于同一个事务中.

              切记 spring 的事务注解 , 异常必须设置为 throwable

      3. 提现:

            * 先扣帐户款再提现.

            * 银行有恶心的退票记录

     

      4. 双边帐

            加减账号分别开.

            4.1 操作分为加锁和不加锁.

            4.1.1 外部企业账户: 加款加锁,减款不加锁. 

            4.1.2 内部企业账户: 加减款都不加锁. 前面增加一个减款判断. 手动提现.

            4.1.3 需要时时查看余额的普通用户需要加锁. 

           通过分布式扩容来实现扩展性.

      5. 帐户的高并发变更设计:

                 高并发帐户不时时扣款.

      6. 互斥关单问题. 

                   记得每个update操作都要锁单(select for update)+状态校验. 在途的互斥关单. 已接受的但不是INIT单已经是processing的要关单.

      7. 非分布式事务下的时效关单问题.

           底线: 任何场景都不能在不知道结果的情况下任意关单 (终态:  关闭或者成功),否则对支付来说,可能导致用户资损,或者冲退的用户体验不好. 对提现来说可能导致平台资损,提现是绝对不能提前关闭的,不能对code进行响应,而是应该对"状态"响应,code千变万化,状态收敛,低风险 .( 导致平台资损这种,都必须被动关单,都是底层来通知关单,对账等. 做不到层层掉下游关单.)
          优化: 尽快关单. 

        timeOut场景:  给用户报错,让用户重试. (错误的小技巧优化思路, 先关闭下游,关闭成功,再关闭自己. 支付可能导致退款. 提现可能导致资金损失,原因没有跨系统关单接口 ,下游还得处理好空"类似tcc分布式事务场景的悬挂问题"或者"互斥关单问题",让系统复杂,不是好的方案.)
        有code:
          方案1: 
 是否有订单号,状态是否是Init, 是则等待处理完的消息,没有那么说明没有受理成功. 直接关单,账户等业务校验异常,给用户提示, 用户重试也没有用. (需要下游遵守 即使处理异常也返回流水号和状态的逻辑,同步接口. 异步接口,处理流程异步执行. 不影响.)  如果不能重试 先关下游,再关自己 (风险点,如果下游系统有bug,已收单异常但没有返回错误码,可能导致资损, 同样需要关注"互斥关单"(类似tcc分布式事务里的"悬挂问题",实现"空pre")的问题, 提现场景的"反退票"问题)  支付宝退票问题

           方案2: 方案1里需要强依赖下游和良好的异常case处理. 方案2的优化是不依赖同步返回,对特定的code,而是通过自己的接口查询状态不存在(可能存在事务未提交的导致"空读")或者closed后,关下游,关自己,对用户异常提示. 其他错误都是等待同步消息 或者 1天后对账状态来确定状态.(避免事务还未提交,"空读问题")

            方案3: 区分场景.  3.1 线下支付流程, 每次都生成新的流水号. 用户想重试就重试,大不了多付款,退款,重要的是能够支付成功. 3.2 线上支付,用同一个流水号.  3.3 提现: 用同一个流水号,告知用户,特殊场景,提现结果需要30分钟后. 否则提早关单返回余额会出问题.

      

     7. 当下游系统很多时. 因为每个系统都有不同的租户配置或者规则引擎元数据, 1. 一种方案如果根据两两相关,就需要每个层级各自申请租户,并对上下游租户直接关联配置; 2. 一种方式就使用打通的所有层级,将最上游的租户信息穿透过来. 但由于不同的上游来的路径不同,id域各自维护,可能导致相同. 那就需要有一个统一的id域. 这个id域作用就是标识一个租户类型,一个链路上,不同的租户信息,有些是能复用的,有些是不能复用的. 只要有一个系统配置不同,就需要用新的租户. 会导致业务变化时新申请一个id域标识的同时, 整个下游系统配置都需要提供人力来新增并修改(配置系统不一定开放), 由于没有后台查看数据,并需要所有人联调查看对应数据是否正确. 配置+接口参数都是变动,变动后测试很重要, 对比测试很重要,要从用户角度,而不是从系统角度,例如可能变更后账户维护在不同的系统,但是用户查询的时候又是聚合查询. 如果只是对比系统的入和出,肯定是对比失败,但整体是正常.

    故任何变动, 如果系统链路和接口没有变,只是新增能力, 对比测试即可,大部分接口对比数据不变.

     如果是系统迁移, 那么验证: 用户侧信息 + 资金查看系统 验证两个即可.

   问题:

  系统越来越复杂,上游的接入方越来越多. 一方面接入方面每次接入需要了解的能力,参数,配置太多. 另一方面平台方面对接入配置配置和联调等忙不过来.

  解法:

   1. 配置产品化,业务方自己配置.

      工作量: 配置插入和复制需要接口化.

      缺点: 下游系统越来越复杂,每次接入需要了解所有的参数.

   2. 配置产品化,并分类分层, 根据业务相似度进行合并(保险中台,xx中台)(模板或者中台自己封装配置后台), 层层封装, 最上层的人只需要配置少量的配置. 如果有新的需求变动时,如果现有配置无法满足需求, 再提出需求, 层层传达. 最终解决问题.

     工作量: 配置插入和复制需要接口化.

  3. 配置参数化

      缺点: 对现有系统代码,改动面较大

    8. 当资产系统很多时, 内部账户系统就有多个. 上游的资产交换系统,就不能单纯的使用支付,转账,提现三个接口语义来区分不同的转账行为了.  而需要通过付款方类型, 收款方账户类型来区分,最终的种类是笛卡尔积.  付款方是外部账户是又可以分为用户收银支付和协议支付,需要不同的字段. 不同的账户系统导致 id域空间不同,就要设置不同的type.

  9. 分布式并发. 
      悲观锁:

        先事务,然后一锁二判三更新

     乐观锁: 

         乐观锁 + 幂等. 存在有上游数据但是没有下游数据的问题. 上游数据状态更新但下游没有变的问题.

附录:

   链路跟踪traceId类似的两码一号概念用在业务系统中的弊端:

   1. 用来进行限定配置集
        缺点:  n个系统, 只要一个系统配置需要不一样. 整条链路都要新配置.  如果使用两两相关映射配置集的,只需要上游系统新增配置集id即可. 
   2. 网关场景

       例如账单场景. 开卡是业务方 1. 往这张卡上充钱是来自gateway.  端码要传成网关的的产品码. 可能粒度比较大,不够细. ?  这个时候到最下游账单就无法区分是什么业务的. 网关也无法细分两码.

     需要下游系统根据配置信息细分业务场景, 最终给账单.  这时候就只能使用业务字段. 不然就修改两码字段,违反了两码本来的定义. 端码是从最上游的系统发起的. 

   3. 回调业务场景? 
        同上.

     

  

个人渣记录,仅搜索用

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值