支付系统数据库设计思考

Posted LuckyZhouStar

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了支付系统数据库设计思考相关的知识,希望对你有一定的参考价值。

主支付表

字段名

字段类型

备注

id

bigint(16)

主键id

order_id

varchar(24)

订单号

bus_pay_no

varchar(24)

支付id

Pay_status

varchar(24)

支付状态

total_amount

bigdecimal(16,2)

总金额

pay_type

varchar(24)

支付方式(成功后回写)

create_time

datetime

创建时间

update_time

datetime

更新时间

 

从支付表

字段名

字段类型

备注

id

bigint(16)

主键id

order_id

varchar(24)

订单号

bus_pay_no

varchar(24)

支付id

sub_pay_no

varchar(24)

从支付id

Pay_status

tinyint

支付状态

pay_type

tinyint

支付方式

total_amount

bigdecimal(16,2)

支付总金额

create_time

datetime

创建时间

update_time

datetime

更新时间

prepay_id

 

第三方支付预会话id

union_id

varchar

联合支付关联id

pay_amount

 

该支付方式下支付的实际金额(比如余额+支付宝联合支付)

card_no

 

银行卡支付卡号

 

用户支付操作记录表

字段名

字段类型

备注

id

bigint(16)

主键id

order_id

varchar(24)

订单号

bus_pay_no

varchar(24)

支付id

sub_pay_no

varchar(24)

从支付id

Pay_status

tinyint

支付状态

pay_type

tinyint

支付方式

total_amount

bigdecimal(16,2)

总金额

create_time

datetime

创建时间

update_time

datetime

更新时间

 

 

 

 

 

 


 

 

1、银行卡支付

    1.主支付表生成用户支付单信息

    2.从支付表生成用户银行卡支付信息

    3.调用银行渠道发起支付,传递主支付订单号、从支付订单号

    4.银行渠道回调支付状态,更新从支付表和主支付表即可

    注意:每次发起支付,如果卡号不一样,是多条记录,卡号一样是一条记录

 

2.微信支付

    1.调用微信生成预会话id

    2.从支付表和主支付表记录信息

    3.微信回调,更新主支付表,更新从支付表(先更新主,防止多个支付造成支付单信息不一致,事务加行锁控制)

 

 

3.支付宝支付

    1.调用支付宝生成预会话id

    2.从支付表和主支付表记录信息

    3.支付宝回调,更新主支付表,更新从支付表

 

 

4.支付宝支付后,余额不足,微信再次支付

    1.调用支付宝生成预会话id

    2.从支付表和主支付表记录信息

    3.此时用户支付宝支付失败,支付宝会进行回调

    4.用户调用微信,生成预会话id

    5.从支付表记录用户的微信支付单信息

    6.用户支付后,微信会回调

    7.为了防止微信和支付宝并发回调,先事务加行锁更新主支付单信息,更新成功后,再更新从支付单信息

    注意:另外回调的时候,不以回调的状态为准,主动在查询一次,以查询到的状态为准

 

 

5.支付宝、微信多次支付

    1.调用支付宝生成预会话id

    2.从支付表和主支付表记录信息

    3.此时用户支付宝支付,支付宝会进行回调

    4.用户调用微信,生成预会话id

    5.从支付表记录用户的微信支付单信息

    6.用户支付后,微信会回调

    7.两个回调的时候,为了防止并发回调,先事务加行锁,更新主支付单信息,更新成功后,再更新从支付单,比如微信先回调,更新主订单,更新从订单;此时支付宝再次回调的话,判断订单状态,如果是成功,则发起退款,生成退款单的逻辑后续再补充

 

 

 

 

6.余额+支付宝联合支付,金额是汇总的,上述表结构就有问题,回调的时候如何知道是与那笔联合的,通过金额判断?

    1.生成一笔主支付单,两笔从支付单,两笔支付单通过一个unionid进行关联

    2.先调用账户系统,进行预冻操作(有具体的冻结时间标识),冻结失败后,比如余额不足,直接返回错误报文

    3.如果冻结成功,则进行支付宝支付流程,发起支付宝预会话id

    4.用户支付宝支付后,支付宝回调,如果支付失败,则更新支付单信息,异步发起余额解冻操作

    5.用户支付宝支付后,支付宝回调,如果回调成功,则更新支付单信息,异步发起余额支付操作,记录支付操作流水等

    6.支付宝回掉后,支付宝回调成功,如何知晓,该笔主支付单绑定了两笔从支付单呢,此时判断支付宝回调的余额与主支付单余额是否一致,一致就代表是一种支付,如果不一致,代表是联合支付,然后找从支付单中余额的从支付单记录即可。这种方案不好,通过一个union联合字段解决

   7.支付宝回调后,更新主支付单状态,从支付单状态,然后异步判断余额是否与总金额一致,如果一致则按照上述流程单一支付更新操作。如果不一致,通过unionid关联查找余额的单子,进行与账户系统交接。并且查找其他冻结的单子,进行补偿操作

 

 

 

联合支付场景(余额+支付宝,余额+微信,余额+银行卡)

7.余额+支付宝联合支付,金额是汇总的,上述表结构就有问题,回调的时候如何知道是与那笔联合的,通过金额判断?

    1.生成一笔主支付单,两笔从支付单

    2.先调用账户系统,进行预冻操作(有具体的冻结时间标识),冻结失败后,比如余额不足,直接返回错误报文

    3.如果冻结成功,则进行支付宝支付流程,发起支付宝预会话id

    4.用户如果唤起支付宝后,kill掉支付宝

    5.用户再次支付,选择了支付宝单一支付

    6.调用支付宝,重新生成新的从支付单即可

    7.用户支付成功后,行锁更新主支付单,从支付单,余额订单发起解冻操作

 

 

8.余额+支付宝联合支付,金额是汇总的,上述表结构就有问题,回调的时候如何知道是与那笔联合的,通过金额判断?

    1.生成一笔主支付单,两笔从支付单

    2.先调用账户系统,进行预冻操作(有具体的冻结时间标识),冻结失败后,比如余额不足,直接返回错误报文

    3.如果冻结成功,则进行支付宝支付流程,发起支付宝预会话id

    4.用户如果唤起支付宝后,kill掉支付宝

    5.用户再次通过微信+余额来支付

    

 

 


 

单一支付场景

    1.微信支付记录、支付宝支付记录都是一条,每次支付的时候,都返回相同的预会话id

    2.卡支付记录,都是两条,防止用户用不同的卡号进行多次支付,重复支付的话,进行退款操作(卡号字段进行冗余操作)

 

 

联合支付场景(余额+卡、余额+支付宝、余额+微信)

1.每次发起,都生成两条支付操作记录,通过unionid进行联合

 

虚拟币支付场景(京东豆+余额)

该场景是在提交订单的时候,直接预先冻结了,不在支付系统考虑范围内

以上是关于支付系统数据库设计思考的主要内容,如果未能解决你的问题,请参考以下文章

如何用消息系统避免分布式事务?

如何用消息系统避免分布式事务?(转)

如何用消息系统避免分布式事务?

如何用消息系统避免分布式事务

如何用消息系统避免分布式事务?

[转]如何使用消息系统避免分布式事务?