支付系统数据库设计思考
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进行联合
虚拟币支付场景(京东豆+余额)
该场景是在提交订单的时候,直接预先冻结了,不在支付系统考虑范围内
以上是关于支付系统数据库设计思考的主要内容,如果未能解决你的问题,请参考以下文章