04.支付系统的设计
分布式事务处理
- 采用TCC或SAGA模式,确保跨服务数据一致性
- TCC分为Try、Confirm、Cancel三阶段;SAGA通过子事务与补偿操作实现最终一致性
流水号与防重放
- 使用雪花算法生成唯一流水号
- 通过签名、时间戳校验和一次性Token防止重放攻击
支付状态机设计
- 状态包括待支付、支付中、成功、失败、超时
- 状态流转需幂等性校验,确保一致性与可追溯性
幂等性校验
- 通过订单ID、用户ID、流水号唯一标识支付操作
- 数据库唯一约束防止重复处理
支付结果确认
- 同步通知前端,异步回调通知系统支付结果
- 回调失败时采用指数退避重试,最终通过主动查询确认支付状态并更新订单
# 01.支付系统设计
# 0、需求说明
设计要点:主要考察支付系统的高可用性、安全性、分布式事务处理、数据一致性等
关键点
- 分布式事务的解决方案(如 TCC、SAGA 模式)
- 流水号生成和防重放攻击
- 支付状态机设计
- 幂等性校验,支付结果的确认和回调机制
系统设计目标
高可用性:保证支付服务在高并发情况下不宕机,具备自动容错和快速恢复的能力
安全性:防止攻击如重放攻击,确保数据传输和存储的安全性,确保支付数据的机密性和完整性
分布式事务处理:保证在跨系统、跨服务的支付场景中,数据的强一致性或最终一致性
数据一致性:确保支付过程中的数据在各个模块和服务间一致,避免出现数据不一致或支付结果丢失的情况
# 1、分布式事务TCC
- 支付系统涉及多个服务(如订单服务、账户服务、支付渠道服务等),分布式事务是关键
# 1)TCC 模式
① Try 阶段
Order Service
创建订单并检查库存,订单状态变为待支付
Account Service
检查账户余额并预扣(锁定)金额,状态变为锁定
Payment Gateway Service
尝试发起支付,验证支付信息,但不实际扣款
② Confirm 阶段
Order Service
更新订单状态为已支付
Account Service
扣款,并更新账户余额Payment Gateway Service
扣除用户的支付金额,支付成功
③ Cancel 阶段
如果订单未成功支付(例如,库存不足),
Order Service
将状态更新为已取消
Account Service
会释放已锁定的金额Payment Gateway Service
将停止支付,并取消所有扣款
# 2)SAGA 模式
① 子事务 1(创建订单)
Order Service
创建一个新订单并保存订单数据,订单状态变为待支付
- 如果失败,补偿操作为取消订单,状态改为
已取消
② 子事务 2(扣款)
Account Service
扣除用户账户中的金额,锁定资金- 如果扣款失败,执行补偿操作:
Account Service
将金额返还给用户
③ 子事务 3(支付处理)
Payment Gateway Service
发起支付请求并扣款- 如果支付失败,执行补偿操作:
Payment Gateway Service
向账户服务发送消息 - 要求返还扣除的金额,并通知
Order Service
取消订单
④ 最终一致性
- 如果所有子事务都成功,
Order Service
最终将订单状态更新为已支付
,整个支付流程完成 - 如果任一子事务失败,系统通过执行补偿操作,回滚整个事务,确保数据一致性
- 如果所有子事务都成功,
# 2、流水号生成与防重放攻击
流水号生成
- 使用
雪花算法
为每笔支付都需要唯一的流水号
- 使用
防重放攻击
攻击者通过捕获、存储并重新发送合法用户的有效请求,来冒充用户进行不正当操作
签名机制:每个支付请求在发出前进行签名,服务器根据
密钥验证签名的有效性,防止请求被篡改或重放
时间戳校验:在请求中加入时间戳,服务器校验请求的
时间有效性
,过期请求将被拒绝一次性Token:每次请求生成一个
唯一的Token
,并保证该Token只能使用一次
,服务器端在处理请求后销毁Token
# 3、支付状态机设计
支付状态机是整个支付过程中的核心,通常可以分为以下几种状态
待支付(Pending):订单已生成,但用户尚未完成支付
支付中(Processing):支付请求已发送到支付渠道,等待响应
支付成功(Success):支付已成功,系统已完成扣款和相关业务操作
支付失败(Failed):支付失败,系统未完成扣款
支付超时(Timeout):支付未在规定时间内完成,系统标记为超时
状态流转:
待支付 → 支付中:用户发起支付
支付中 → 支付成功/支付失败/支付超时:支付渠道返回结果或超时
支付成功/支付失败 → 结束:系统记录最终支付结果,通知相关服务
每个状态转换需要进行幂等性检查(如支付成功后,多次调用支付成功的逻辑应不会重复执行)
确保系统的状态一致性和支付过程的可追溯性
# 4、幂等性校验
- 幂等性是支付系统中的重要设计原则,防止因重复请求导致重复扣款或订单多次支付的情况
支付接口的幂等性:同一个支付请求在规定时间内只能成功一次
- 可通过
订单ID+用户ID+请求流水号联合唯一确定一次支付操作
- 可以
使用数据库唯一约束
来防止相同的支付请求被多次处理
- 可通过
在支付流程的每个关键节点(如下单、扣款、回调等)记录支付流水号和状态
在处理同一个支付请求时,先检查是否已有成功记录,若有则直接返回处理结果
# 5、支付结果确认
- 支付结果的确认和回调机制是保证支付信息准确传递给业务系统的关键步骤
同步与异步通知机制
同步通知:支付网关直接返回支付结果,在用户前端展示支付成功/失败结果
异步通知:支付网关会在后台通过回调接口异步通知系统支付结果,确保系统接收到最终的支付状态
回调处理机制
支付网关发送回调通知时,系统接收并校验签名、流水号等信息
回调失败时,可以设置重试机制,每次重试间隔时间逐渐增加(指数退避算法)
支付结果确认
系统在接收到支付结果后,应主动发起支付状态查询以核实支付网关的响应结果
最终支付结果确定后,应通知相关业务模块更新订单状态,并返回用户支付结果