04.支付系统的设计
# 01.支付系统设计
# 0、需求说明
设计要点:主要考察支付系统的高可用性、安全性、分布式事务处理、数据一致性等
关键点
- 分布式事务的解决方案(如 TCC、SAGA 模式)
- 流水号生成和防重放攻击
- 支付状态机设计
- 幂等性校验,支付结果的确认和回调机制
系统设计目标
高可用性:保证支付服务在高并发情况下不宕机,具备自动容错和快速恢复的能力
安全性:防止攻击如重放攻击,确保数据传输和存储的安全性,确保支付数据的机密性和完整性
分布式事务处理:保证在跨系统、跨服务的支付场景中,数据的强一致性或最终一致性
数据一致性:确保支付过程中的数据在各个模块和服务间一致,避免出现数据不一致或支付结果丢失的情况
# 1、分布式事务解决方案
- 支付系统涉及多个服务(如订单服务、账户服务、支付渠道服务等),分布式事务是关键
# 1)TCC(Try-Confirm-Cancel)模式
Try 阶段:预先占用资源(如冻结账户金额、生成支付记录)
Confirm 阶段:确认支付完成,提交所有事务操作(如扣款、记录支付成功状态)
Cancel 阶段:如果任何步骤失败,取消操作并释放资源(如解冻资金)
注:TCC 的优势是能够提供较好的数据一致性,但在业务逻辑复杂的场景中,Cancel 操作的设计会较为复杂
# 2)SAGA 模式
SAGA 模式通过分布式的补偿机制保证最终一致性
每个事务步骤(如订单创建、扣款、发货)都由一系列子事务组成,且每个子事务都有对应的补偿操作
当某个子事务失败时,会调用补偿事务进行回滚
SAGA 模式适用于业务容错率较高的场景,系统要求对实时性较高,但对绝对一致性要求可以放宽到最终一致性
选择依据:
- 根据业务对一致性的要求,如果是银行系统等金融级别要求,可优先选择 TCC
- 对于电商类支付场景,SAGA 可以更好地处理延迟问题
# 2、流水号生成与防重放攻击
# 1)流水号生成
每笔支付都需要
唯一的流水号
,常见的流水号生成方式包括UUID(全局唯一标识符):适用于生成唯一且不连续的流水号
雪花算法(Snowflake):生成基于时间戳的分布式唯一ID,适用于高并发场景,能够保证有序性
数据库自增ID:适用于简单场景,但由于有性能瓶颈,建议在高并发场景下配合其他方案使用
# 2)防重放攻击
防止黑客利用捕获的支付请求进行重放攻击,可以采取以下措施
签名机制:每个支付请求在发出前进行签名,服务器根据
密钥验证签名的有效性,防止请求被篡改或重放
时间戳校验:在请求中加入时间戳,服务器校验请求的
时间有效性
,过期请求将被拒绝一次性Token:每次请求生成一个
唯一的Token
,并保证该Token只能使用一次
,服务器端在处理请求后销毁Token
# 3、支付状态机设计
支付状态机是整个支付过程中的核心,通常可以分为以下几种状态
待支付(Pending):订单已生成,但用户尚未完成支付
支付中(Processing):支付请求已发送到支付渠道,等待响应
支付成功(Success):支付已成功,系统已完成扣款和相关业务操作
支付失败(Failed):支付失败,系统未完成扣款
支付超时(Timeout):支付未在规定时间内完成,系统标记为超时
状态流转:
待支付 → 支付中:用户发起支付
支付中 → 支付成功/支付失败/支付超时:支付渠道返回结果或超时
支付成功/支付失败 → 结束:系统记录最终支付结果,通知相关服务
每个状态转换需要进行幂等性检查(如支付成功后,多次调用支付成功的逻辑应不会重复执行
确保系统的状态一致性和支付过程的可追溯性
# 4、幂等性校验
- 幂等性是支付系统中的重要设计原则,防止因重复请求导致重复扣款或订单多次支付的情况
# 1)幂等性设计
- 支付接口的幂等性:同一个支付请求在规定时间内只能成功一次
- 可通过订单ID+用户ID+请求流水号联合唯一确定一次支付操作
- 可以使用数据库唯一约束来防止相同的支付请求被多次处理
- 事务操作的幂等性:
- 比如扣款操作、订单状态修改操作,应该确保无论该操作被触发多少次,最终结果是一致的
# 2)幂等性实现
- 在支付流程的每个关键节点(如下单、扣款、回调等)记录支付流水号和状态
- 在处理同一个支付请求时,先检查是否已有成功记录,若有则直接返回处理结果
# 5、支付结果确认与回调机制
- 支付结果的确认和回调机制是保证支付信息准确传递给业务系统的关键步骤
# 1)同步与异步通知机制
- 同步通知:支付网关直接返回支付结果,在用户前端展示支付成功/失败结果
- 异步通知:支付网关会在后台通过回调接口异步通知系统支付结果,确保系统接收到最终的支付状态
# 2)回调处理机制
- 支付网关发送回调通知时,系统接收并校验签名、流水号等信息
- 系统处理回调时应考虑幂等性(避免重复处理回调),如校验回调状态是否已经更新为最终状态
- 回调失败时,可以设置重试机制,例如设置多次重试,每次重试间隔时间逐渐增加(指数退避算法),避免网络抖动导致回调失败
# 3)支付结果确认
- 系统在接收到支付结果后,应主动发起支付状态查询以核实支付网关的响应结果,特别是在支付结果不明确或超时的情况下
- 最终支付结果确定后,应通知相关业务模块更新订单状态,并返回用户支付结果
# 6、系统架构设计
# 1)分布式架构
- 使用微服务架构,各个功能模块如订单服务、支付服务、账户服务等独立部署,采用Spring Cloud或Dubbo等微服务框架实现
- 使用消息中间件(如Kafka、RabbitMQ)解耦各个模块之间的异步通信,特别适用于支付状态更新、支付结果通知等场景
# 2)高可用性设计
- 使用集群和负载均衡机制(如Nginx+服务器集群、Kubernetes集群等),提高系统可用性
- 采用熔断、限流和降级机制,保证在高并发情况下服务不会崩溃
# 3)安全性设计
- 支付数据在传输过程中使用HTTPS加密,防止中间人攻击
- 数据存储采用数据库加密,如用户敏感信息(卡号、交易流水)使用对称加密算法(如AES)加密存储
- 通过双因子认证、权限验证和日志审计等手段加强支付流程中的安全控制