👉 这是一个或许对你有用的社群
🐱 一对一交流/面试小册/简历优化/求职解惑,欢迎加入「芋道快速开发平台」知识星球。下面是星球提供的部分资料:
《项目实战(视频)》:从书中学,往事上“练”
《互联网高频面试题》:面朝简历学习,春暖花开
《架构 x 系统设计》:摧枯拉朽,掌控面试高频场景题
《精进 Java 学习指南》:系统学习,互联网主流技术栈
《必读 Java 源码专栏》:知其然,知其所以然

👉这是一个或许对你有用的开源项目
国产Star破10w的开源项目,前端包括管理后台、微信小程序,后端支持单体、微服务架构
RBAC权限、数据权限、SaaS多租户、商城、支付、工作流、大屏报表、ERP、CRM、AI大模型、IoT物联网等功能:
多模块:https://gitee.com/zhijiantianya/ruoyi-vue-pro
微服务:https://gitee.com/zhijiantianya/yudao-cloud
视频教程:https://doc.iocoder.cn
【国内首批】支持 JDK17/21+SpringBoot3、JDK8/11+Spring Boot2双版本

在当今的支付业务领域,其涉及的环节繁多,涵盖了创建订单、发起支付、等待第三方回调、退款以及关闭等多个关键步骤。
由于环节复杂且异常场景层出不穷,如果仅仅依赖一个简单的 status 字段来随意更新订单状态,极易引发逻辑混乱、漏单现象,同时也会给后续的审计工作带来极大的困难。
为了解决这些问题,众多支付系统纷纷引入了状态机 (State Machine)这一强大工具,用于管理支付订单在不同阶段的状态转移。与此同时,配合使用状态变更记录表 (也称为历史表)进行详细记录,为后续的审计和问题排查提供有力支持。
一、为何支付系统需要状态机
1. 业务复杂度的应对
支付流程犹如一幅错综复杂的画卷,从订单创建伊始,到支付成功或失败,再到可能的退款或关闭操作,其间存在着各种各样的中间状态和异常情况。
例如,用户可能因为各种原因迟迟不进行付款操作;第三方回调信息可能由于网络等因素丢失;部分退款的情况也时有发生。
这些复杂的业务场景使得简单的状态管理方式难以胜任,而状态机的引入则为解决这些问题提供了有效的途径。
2. 提升可维护性与可审计性
可维护性 :状态机能够清晰地列出状态与事件之间的对应关系,就像一张精确的地图,为团队成员指引方向。这避免了团队成员随意修改订单状态,减少了沟通成本和排查问题的时间。关注工众号:码猿技术专栏,回复关键词:1111 获取阿里内部Java性能调优手册!团队成员可以根据状态机的规则,快速了解系统的运行逻辑,提高开发和维护的效率。
可审计性 :支付业务涉及资金流动,受到严格的监管和合规要求。因此,对每一步状态变更进行详细的留痕记录是必不可少的。状态变更记录表可以记录下状态变更的时间、原因、操作者等重要信息,为后续的审计工作提供了完整的证据链。
3. 有序处理异常场景
在支付过程中,异常场景时有发生,如第三方回调可能延迟或失败;用户可能在支付中途取消订单;退款过程需要多次与第三方进行确认等。
状态机的引入使得这些异常场景的处理更加有序,能够确保系统内状态的一致性。通过状态机的规则,可以对不同的异常情况进行分类处理,避免系统出现混乱。
综上所述,对于中大型支付系统而言,状态机几乎是不可或缺的设计工具,它能够帮助系统更好地应对复杂的业务场景,提高系统的稳定性和可维护性。
基于 Spring Boot + MyBatis Plus + Vue & Element 实现的后台管理系统 + 用户小程序,支持 RBAC 动态权限、多租户、数据权限、工作流、三方登录、支付、短信、商城等功能
项目地址:https://github.com/YunaiV/ruoyi-vue-pro
视频教程:https://doc.iocoder.cn/video/
二、常见支付状态的解析
在实际的支付业务中,支付状态的定义并非一成不变,而是需要根据具体的业务需求进行灵活调整。下面为大家呈现一个常见且相对完整的支付状态集合,你可以根据自身业务的特点进行增减或合并。
1. CREATED(已创建)
当订单在支付中心成功生成,但尚未正式发起支付时,订单处于此状态。这是订单生命周期的起始阶段,标志着订单的初步创建。
2. PENDING(待支付)
一旦向第三方发起支付请求,或者生成了支付链接/二维码供用户进行支付操作,但尚未收到最终的支付结果时,订单进入待支付状态。此时,系统需要等待用户完成支付或第三方返回支付结果。
3. PROCESSING(支付中 / 处理中)
部分支付渠道会返回「处理中」的状态信息,这意味着第三方需要一定的时间来完成扣款确认操作。在某些业务场景中,可能会将「待支付」和「支付中」这两个状态合并为一个状态,以简化业务逻辑。
4. SUCCESS(支付成功)
当收到第三方支付成功的回调信息,或者主动查询到支付成功的结果时,订单正式完成支付,进入支付成功状态。这是支付流程的一个重要里程碑,标志着交易的顺利完成。
5. FAIL(支付失败)
若第三方支付明确表示失败,或者用户超时未付款,订单将进入支付失败状态。一旦进入此状态,通常情况下订单将无法再进行支付操作。
6. REFUNDING(退款中)
对于已经支付成功的订单,当用户或系统发起退款请求后,订单进入退款中状态,此时需要等待第三方的退款结果。在这个阶段,系统需要与第三方进行沟通,确保退款操作的顺利进行。
7. REFUNDED(退款成功)
当第三方确认退款成功后,订单进入退款成功状态。如果是部分退款的情况,需要在订单或退款表中详细记录已退金额和剩余可退金额,以便进行后续的管理和查询。
8. CLOSED(已关闭 / 已取消)
若订单在支付成功之前被取消,例如用户主动取消订单或系统因超时自动关闭订单,订单将进入已关闭状态。一旦订单处于此状态,将不可再进行支付或退款操作。
这些状态基本涵盖了常见的支付生命周期。你可以根据实际业务场景的需求,对状态进行简化或细化。例如,如果业务场景不需要「PROCESSING」或「REFUNDING」状态,可以将其去除;若需要更加精细的退款流程,也可以进一步细化「部分退款」「多次退款」等状态。
基于 Spring Cloud Alibaba + Gateway + Nacos + RocketMQ + Vue & Element 实现的后台管理系统 + 用户小程序,支持 RBAC 动态权限、多租户、数据权限、工作流、三方登录、支付、短信、商城等功能
项目地址:https://github.com/YunaiV/yudao-cloud
视频教程:https://doc.iocoder.cn/video/
三、典型状态流转示例详解
状态机的核心机制在于通过当前状态和触发事件来确定下一个状态。下面为大家展示一个简化的示例,清晰地呈现了常见的事件触发和状态变化情况。
以上示例仅为通用情况,实际业务中可能会根据部分退款、多次退款、多渠道回调等复杂情况进行更加精细的设计。
四、状态变更记录表的设计要点
4.1 为何需要单独的记录表
审计与追溯 :资金相关的业务对留痕要求极高,通过状态变更记录表,可以在事后详细查看每一次状态变化发生的时间、原因以及操作者等重要信息。关注工众号:码猿技术专栏,回复关键词:1111 获取阿里内部Java性能调优手册!这为审计工作提供了有力的支持,确保业务操作的合规性。
问题排查 :当用户提出投诉或系统出现故障时,状态变更记录表可以帮助我们快速还原订单的完整生命周期,定位问题的根源。通过查看状态变更的历史记录,我们可以了解订单在各个阶段的状态变化情况,找出可能存在的问题。
统计分析 :基于状态变更表,我们可以进行丰富的统计分析工作。例如,统计订单在各状态停留的时间分布,了解业务流程的效率;分析失败率和退款率等指标,为业务优化提供数据支持。
4.2 表结构示例
常见的状态变更记录表(也可称为 payment_status_history 或 payment_order_history 等)可以按照以下结构进行设计:
需要注意的是,一个订单从创建到完成,可能会多次变更状态,每次状态变更都需要插入一条新的记录,而不是只保留一条记录。各字段的含义如下:
order_id:用于区分该记录属于哪个订单,确保记录与订单之间的关联关系。from_status/to_status:记录本次状态变更的起点和终点,清晰展示状态的变化过程。event:具体的事件名称,如PaymentSuccess或CloseOrder,明确触发状态变更的原因。operator:记录是由谁或哪个系统触发了本次变更,方便后续的责任追溯。remark:可以写入失败原因、第三方返回码等辅助信息,为问题排查和分析提供更多的线索。create_time:记录状态变更的发生时间戳,便于进行时间维度的统计和分析。
五、项目中状态机的落地方式
5.1 手写状态机
在大多数项目中,手动编写状态机映射或状态流转表是一种常见的做法。以下是具体的实现步骤:
首先,定义支付状态和支付事件的枚举类:
然后,在代码中使用映射或 if-else / switch 逻辑来控制当前状态和事件到下一个状态的转换规则。每次更新订单状态时,需要按照以下步骤进行操作:
查询订单的当前状态。
判断是否允许触发对应的事件。
如果允许,则将订单状态更新为目标状态。
插入一条状态变更记录到
payment_status_history表中。
以下是一个示例代码:
5.2 使用 Spring StateMachine
Spring 提供了 Spring Statemachine 库,该库可以更加系统化地管理复杂的状态、事件和转移。
它支持分层状态机、并行状态机等高级功能,还可以配置监听器在状态变更时自动将相关信息写入数据库。该库适用于状态过多、流程极其复杂或需要可视化管理的场景。
然而,如果团队对该框架不太熟悉,且业务需求不算特别复杂,手写状态机往往已经能够满足需求。
六、关键关注点解析
1. 幂等性的保障
支付回调可能会多次触发,为了确保系统的稳定性和数据的准确性,需要保证重复回调不会导致重复更新或错误更新。可以在数据库层面进行幂等校验,例如,如果订单状态已经是 SUCCESS,再次收到成功回调时可以直接忽略该请求。
2. 异常场景的处理
第三方回调丢失 :当第三方回调信息丢失时,订单可能会一直停留在
PENDING状态。为了解决这个问题,需要定期主动查询第三方支付结果,确保订单状态能够及时更新。超时关闭 :如果用户长时间未支付,订单可以自动从
CREATED或PENDING状态转为CLOSED状态,以释放系统资源,避免无效订单的占用。退款失败 :若第三方退款失败,订单需要回到
SUCCESS状态,并且可以再次发起退款请求,确保用户的退款需求能够得到妥善处理。
3. 部分退款的处理
如果业务允许部分退款,需要额外记录已退金额和剩余可退金额等信息。同时,状态机也需要支持部分退款成功、多次退款等更复杂的场景,以满足业务的多样化需求。通过合理设计状态机和数据库表结构,可以确保部分退款业务的顺利进行。
4.数据一致性
通常使用数据库事务保证订单表与状态变更表的同步更新;
大规模系统可采用消息队列或分布式事务方案。
5.对账与统计
完整的支付系统还需要对账逻辑(对比第三方交易流水),并将状态变更表的数据用于审计与统计分析。
七、总结
1.状态机设计 :
列出核心状态(CREATED、PENDING、SUCCESS、FAIL、REFUNDING、REFUNDED、CLOSED 等)和对应事件;
明确当前状态 + 事件 -> 下一个状态的规则,保证每次状态变更都有明确触发。
2.状态变更记录表 :
建议使用多条记录的方式保存状态流转历史,每次变更都插入一条;
表中至少包含订单标识、原状态、新状态、触发事件、操作人、时间、备注等核心字段;
方便后续审计、问题排查与统计分析。
3.关键落地点 :
确保幂等 与异常场景 处理;
考虑部分退款 、多次退款 等业务需求;
根据团队熟悉程度,选择手写状态机 或Spring StateMachine ;
在大规模 或合规要求高 的场景中,要特别重视审计和数据一致性。
通过以上设计,一个支付系统就能够在单体 或微服务 架构中实现对订单全生命周期的有效管理,保持状态清晰、有序,满足合规与审计需求,并在异常场景下依旧具备较好的可维护性和可追溯性。
欢迎加入我的知识星球,全面提升技术能力。
👉 加入方式,“长按”或“扫描”下方二维码噢:

星球的内容包括:项目实战、面试招聘、源码解析、学习路线。





文章有帮助的话,在看,转发吧。
谢谢支持哟 (*^__^*)
281



被折叠的 条评论
为什么被折叠?



