系统流程图栏目 ·

下单-支付-发货流程图怎么画:含库存不足/支付失败/超时取消

系统讲清“下单-支付-发货”从页面到后端的主流程与关键异常(库存不足、支付失败、超时取消、重复支付/回调竞态等),并给出可交付的流程图画法规范、清单与 FAQ。

很多“下单-支付-发货”流程图看起来像一条顺滑的直线,但真正上线后最先把团队打懵的,往往不是主流程,而是这些瞬间:

  • 用户点了支付,前端显示失败,但几秒后渠道回调却显示成功(前端结果≠最终结果
  • 库存看似够,多个并发下单把库存打穿(库存校验时机
  • 订单已经超时关闭,支付却在最后一秒成功(关闭与回调竞态
  • 仓库拆单/缺货导致部分发货(发货不是一个动作

所以这篇文章不是“给你一张图让你照抄”,而是把可交付的画法拆成一套可复用的思维框架:先定边界与对象、再定状态与判断、最后把异常分支画得能落到系统里。

如果你希望先用文本把流程写清楚、再自动排版生成流程图(并导出 PNG / draw.io),可以用这个工具快速起稿:

提醒:正文里我会用“订单服务/库存服务/支付服务/仓库/物流”这类抽象名词;你可以把它替换成你们的具体系统(例如 OMS/WMS/TMS、第三方支付渠道、ERP 等)。


1. 先定边界:这张“下单-支付-发货”图到底要覆盖到哪?

画流程图的第一步不是画节点,而是回答:这张图的读者是谁、要解决什么决策问题。同一个“下单-支付-发货”,在不同读者眼里边界完全不同:

  • 产品/运营:关心页面路径、状态提示、异常兜底、用户体验(比如库存不足提示、支付失败重试)
  • 研发/架构:关心接口时序、幂等、状态机、补偿、异步消息、竞态处理
  • 测试/交付:关心用例覆盖、异常分支是否闭环、是否可回归

建议你把流程分成三层,避免一张图堆到爆:

  1. 业务层流程图(推荐主图):以“订单/支付/库存/发货”的业务对象状态为主,能让产品、研发、测试同时读懂
  2. 系统交互时序(可选附图):当你需要讨论回调竞态、消息一致性、重试策略时,再补一张时序图或交互图
  3. 页面/运营路径(可选附图):当你需要讲清前台页面跳转、文案提示、运营策略时,再补一张用户旅程

本文重点是第 1 类:可交付的业务层流程图,但会把关键系统落点(幂等/回调/补偿)写清楚。


2. 把“对象”和“状态”写清楚:否则你画出来的只是故事,不是系统

下单到发货,至少会涉及 4 个核心对象。你不需要把数据库字段画进去,但要把“状态机”立起来:

2.1 四个核心对象(建议写在图的注释区)

  • 订单(Order):用户买了什么、多少钱、属于谁、当前处于哪个业务阶段
  • 支付单(Payment):对接渠道的支付尝试记录(一次订单可能多次支付尝试)
  • 库存记录(Inventory / Stock Reservation):扣减/预占/释放的依据
  • 履约/发货单(Fulfillment/Shipment):仓库拣货、出库、发货、物流轨迹

常见误区:把“订单=支付=发货”混在一个状态里。这样一遇到“支付成功但发货失败”“部分发货”“改地址补运费”就无从落笔。

2.2 建议的订单主状态(不求全,但要闭环)

你可以按你们业务简化,但至少要保证每条异常分支最后都有归宿(结束节点能说明“最终状态是什么”)。一个常见且好用的拆法:

  • 待支付:订单已创建,但尚未确认支付成功
  • 已支付:支付最终成功(注意:以回调/查询为准,不以“前端返回”或“跳转成功”为准)
  • 已取消/已关闭:超时关闭或用户主动取消,且库存/支付都已处理完毕
  • 待发货/履约中:已支付,等待仓库处理
  • 已发货:物流单已创建且出库
  • 已完成:签收或确认收货

支付单可以有自己的状态:支付中/成功/失败/已关闭/已退款;发货单也有:待拣货/已出库/已发货/异常。流程图里不一定要把全部细分画出,但你要在文字说明里明确:你正在画哪一个状态机为主


3. 主流程怎么拆:把“5~9 个关键节点”画成一条可阅读的主干

主流程建议控制在 5~9 个节点,否则读者会在第一屏就迷路。下面是一条更贴近真实系统的主干(带上必要的判断点):

  1. 用户提交订单(确认商品/地址/优惠/运费)
  2. 创建订单(订单状态=待支付)
  3. 库存处理(预占/锁定/校验)
  4. 发起支付(生成支付单,跳转/拉起收银台)
  5. 支付结果确认(回调/查询,最终落库)
  6. 订单状态更新为已支付(触发履约)
  7. 仓库履约(拣货/出库/创建物流)
  8. 发货完成(订单状态=已发货)
  9. 后续完成(签收/确认收货/自动完成)

3.1 你必须在主流程里明确的两个“现实问题”

问题 A:库存到底在什么时候扣?

  • 只“校验不锁定”:并发下单容易超卖,体验差
  • “锁定/预占”:更常见,需要配套释放机制(取消/超时/支付失败)
  • “真实扣减”可以在支付成功后或出库前,取决于业务(虚拟商品/实物商品差异很大)

你的流程图至少要能回答:库存不足发生在什么节点、发生后订单是什么状态、库存会不会被释放

问题 B:支付成功的判定依据是什么?

  • 仅靠前端返回:风险大(用户关闭页面、网络抖动、渠道返回不可靠)
  • 以渠道回调/主动查询为准:更可靠,但要处理“回调延迟/重复回调/乱序回调”

你的流程图要能回答:订单从待支付到已支付,是由哪个事件驱动(回调/查询/轮询),并且如何保证幂等


4. 关键异常分支怎么画:库存不足 / 支付失败 / 超时取消 / 回调竞态

异常分支画得好不好,决定这张图能不能用来评审、落地、写用例。建议你遵循两条规则:

  • 异常分支要“闭环”:每条异常路径都要回到一个明确的终态(取消/关闭/待支付重试/人工处理等)
  • 异常分支要“可执行”:写清楚谁来做(系统自动/用户触发/定时任务/人工),以及关键动作(释放库存、关闭支付单、记录原因)

4.1 库存不足(或锁定失败)

库存不足不是一个“提示弹窗”,而是一个系统分叉点。画法建议:

  • 判断节点:库存是否可用/是否锁定成功?
  • 否分支(失败):
    • 订单处理:订单创建失败(不落单)或落单后标记为“无库存待处理”(看业务)
    • 用户体验:提示缺货/限购/调整数量
    • 系统动作:记录失败原因(SKU、库存快照、请求 id),必要时触发补货/告警

推荐做法(更容易闭环):在“创建订单”之后立刻进行库存预占/锁定;锁定失败则将订单标记为“已取消/已关闭(库存不足)”,并把失败原因写进订单取消原因。这样测试和运营都能追溯。

4.2 支付失败(含取消/拒付/风控)

支付失败至少分两类:

  • 明确失败:渠道返回失败、用户取消、卡余额不足等
  • 不确定结果:网络超时、渠道无响应、回调未到

流程图里建议把“支付失败”画成可重试的分支:

  • 明确失败:订单回到 待支付(允许用户重试)或直接关闭(看业务)
  • 不确定:进入 支付结果待确认(或仍在待支付,但标记“查询中”),由定时任务/查询接口确认最终结果

关键点:不确定结果千万别直接把订单判死刑。正确做法是“延迟确认 + 幂等落库”。

4.3 超时取消(订单关闭)

“超时取消”最好不要画成用户动作,而要明确它通常由:

  • 定时任务(扫描待支付订单超过 N 分钟)
  • 或延迟消息(创建订单时投递一个“X 分钟后检查”的延迟消息)

在流程图里,超时取消分支建议写清楚三个动作:

  1. 关闭订单(订单状态=已关闭,原因=支付超时)
  2. 释放库存预占
  3. 关闭未完成的支付单(如果支付渠道支持关闭/撤销)

4.4 订单关闭 vs 支付成功:最常见的竞态(建议在图上明确“最终裁决规则”)

这是很多团队流程图的缺口:订单可能在超时任务里被关闭,但支付回调刚好到达。到底谁赢?

建议你在流程图的注释区写清楚一条“裁决规则”,例如:

  • 以支付渠道最终确认成功为准:如果订单已关闭但渠道确认成功,则走“自动恢复订单并进入履约/或自动退款”(按业务)
  • 以订单关闭为准:如果订单已关闭,则一律拒绝履约,并触发退款

无论你选哪一种,都必须把两点画出来:

  • 回调处理需要幂等:同一个支付单回调多次,只能成功更新一次
  • 回调处理要能识别“订单已关闭”:并走到明确的补偿路径(恢复或退款)

你可以在流程图中用一个判断节点表达:订单当前是否允许进入已支付?(条件包含“未关闭/可恢复”)。


5. 画法规范:泳道、节点粒度、判断写法、连线命名(让图能评审)

5.1 泳道怎么划(推荐 5~7 条,别太多)

常见泳道划分(按职责,不按系统名炫技):

  • 用户/前台(App/H5)
  • 订单服务(创建/关闭/状态更新)
  • 库存服务(预占/释放/扣减)
  • 支付服务(支付单/回调/查询)
  • 履约/仓库(拣货/出库/拆单)
  • 物流(发货/轨迹)
  • 通知/消息(短信、站内信、消息队列)——可选

泳道的意义是:读者一眼看出“这一步是谁负责”。如果你发现某一步跨了 3 条泳道,那说明你画的不是业务流程,而是实现细节缠在一起了。

5.2 节点粒度:一个节点只表达一个“业务动作”

好节点的表达通常是:动词 + 对象,例如:

  • 创建订单
  • 预占库存
  • 发起支付
  • 确认支付结果
  • 触发履约
  • 创建发货单

坏节点通常把多个动作打包成一句“做完一切”:

  • “下单并支付并发货”
  • “通知相关系统”

节点越模糊,后面越难补异常分支。

5.3 判断节点写法:条件要可验证、分支要命名

判断节点建议写成明确条件(能写用例/能查日志):

  • 库存锁定是否成功?
  • 支付是否确认成功?
  • 是否超过支付时限?
  • 订单状态是否允许变更?

连线(分支)最好标注:是/否成功/失败超时/未超时,不要只用颜色。

5.4 连线避免“乱飘”:异常分支放右侧或下方,并标明归宿

一个实用排版习惯:

  • 主流程从左到右(或上到下)保持直
  • 异常分支统一往右侧展开
  • 每条异常分支最终回到一个终止节点(如:订单关闭、返回待支付、人工处理)

这能显著减少交叉线,让图“能读”。


6. 用文本起稿(只给一个小例子):快速把主干和关键分支写出来

很多人卡在“我不知道从哪里下手”。我建议先写一个极简主干,把你确定的判断点写出来,再逐步加细节。下面只是一个小例子(不要当作可直接复用的大段文本):

开始 -> 创建订单(待支付)
创建订单 -> [库存锁定成功?]
[是] -> 发起支付 -> [支付最终成功?]
[否] -> 取消订单(缺货) -> 结束
[是] -> 触发履约 -> 仓库出库 -> 已发货 -> 结束
[否] -> 释放库存 -> 订单保持待支付/关闭(按策略) -> 结束

你把这段文本丢进在线生成器,就能先得到一张结构清晰的草图,然后再在图上补充:

  • 超时关闭由“定时任务/延迟消息”触发
  • 回调竞态的裁决规则
  • 支付单/发货单等对象的状态说明

工具入口(用于起稿与导出):


7. 落地到系统:你画的图需要能回答这些工程问题(否则评审会吵翻)

流程图不是“好看”,而是“能减少沟通成本”。下面这些问题,你不一定要在图里展开实现细节,但至少要在图旁注释里给出原则。

7.1 幂等:同一事件来两次,会不会扣两次库存/发两次货?

典型重复来源:

  • 支付回调重复(渠道重试)
  • 前端重复提交(用户连点/网络重试)
  • 消息重复投递(至少一次语义)

你在图里可以用一句注释表达:

  • “创建订单:以 requestId 幂等”
  • “支付回调:以 paymentId 幂等落库”
  • “发货触发:以 orderId + shipmentNo 幂等”

7.2 一致性:库存、订单、支付三者如何对齐?

现实里你不可能靠一个大事务把所有系统锁在一起。常见的更稳妥的落地方式是:

  • 订单状态变更发布事件(如 OrderPaid
  • 库存、履约订阅事件执行各自动作
  • 失败则进入补偿/重试队列,并可人工介入

流程图里可以把“发布事件/消费事件”画成一个节点(例如“发布 OrderPaid 消息”),并在旁边标明:至少一次投递 + 幂等消费

7.3 可观测:出了问题你怎么定位?

建议在图的交付说明里包含三类信息:

  • 关键业务 ID:orderId、paymentId、shipmentId
  • 关键日志点:创建订单、库存锁定、支付确认、订单关闭、履约触发、出库
  • 告警点:支付成功但履约未触发、订单关闭但支付成功、库存预占长期未释放

这部分属于“独有信息增量”:很多流程图不写,导致上线后出了问题只能靠人肉排查。


8. 交付清单:评审/对齐/测试都用得上

当你要把这张图交付给团队(写 PRD、开评审、给测试用例、对接外包),建议你在流程图旁边附上这个清单(可当作你自己的检查表):

  • 流程边界写清:从哪里开始,到哪里结束(是否包含签收/退款/售后)
  • 泳道清晰:每个动作都有责任方(前台/订单/库存/支付/仓库/物流)
  • 主干节点 5~9 个:可在 30 秒内讲完一遍
  • 至少覆盖 3 类异常:库存不足、支付失败/不确定、超时关闭
  • 竞态规则明确:订单关闭 vs 支付成功的最终裁决
  • 状态闭环:每条异常分支最终落到明确终态(不悬空)
  • 幂等点标注:重复提交/重复回调/重复消息不会产生重复履约
  • 交付信息:版本号、日期、参与人、假设前提(例如“库存为预占模式”)

当你需要快速把图做成可分享、可导出的交付物时,用文本生成+自动排版会省大量时间:


9. 常见反例(踩一次坑就够了)

反例 1:把“接口时序”当作“业务流程”

如果你的图里全是“调用 A 接口→调用 B 接口→调用 C 接口”,没有对象状态、没有异常终态,那它更像一张开发笔记,产品和测试读不懂,评审也很难对齐。

改法:把“对象状态”放到主干(订单状态/支付确认/履约触发),接口细节放到注释或附图。

反例 2:异常分支只写“失败”,没有后续动作

“支付失败”之后是回到待支付重试?还是关闭订单?库存要不要释放?支付单要不要关闭?这些不写,流程图就无法落地。

改法:每个失败分支至少补三件事:订单状态、库存处理、用户提示/下一步。

反例 3:把“同步/异步”混在一起,导致读者误以为一步就能完成

支付确认、发货、物流轨迹这些都可能是异步。你如果画成一条同步直线,会让需求对齐出现错觉:以为“支付成功立刻发货”。

改法:在节点上标注“异步事件/消息触发”,或把异步环节用虚线/注释表示。


10. FAQ:经常被问到的几个细节

Q1:库存到底用“预占”还是“支付后扣减”?

没有放之四海皆准的答案:

  • 预占适合高并发、库存敏感、需要强用户体验的场景(先锁住再让用户去付钱)
  • 支付后扣减适合虚拟商品或库存压力小的场景,但要接受超卖/补偿的成本

关键不是选哪一种,而是:你的流程图要能把“释放/补偿”画清楚

Q2:用户支付完成后为什么还会看到“处理中”?

因为“支付完成”往往先发生在渠道侧,你的系统需要通过回调/查询确认并落库。这个延迟在高峰期更明显。

流程图里建议把“支付结果确认”独立成节点,并标注“以回调/查询为准”。

Q3:订单关闭后收到支付成功回调,最稳妥的处理是什么?

从风险控制角度,常见稳妥策略是:

  • 如果订单已关闭:不再履约,进入退款流程(或引导用户重新下单)
  • 同时记录竞态事件并告警,避免大面积发生

但如果你们业务强调体验,也可以选择“自动恢复订单并履约”。无论选择哪种,都要在图里写清“裁决规则”。

Q4:一张图画不下怎么办?

别硬塞。建议拆成:

  • 一张“业务主流程 + 关键异常”的总览图(本文目标)
  • 一张“支付确认与竞态处理”的细化图
  • 一张“履约/拆单/部分发货”的细化图

11. 最后:用一张“能落地”的流程图,减少跨团队扯皮

下单-支付-发货是电商系统最经典、也最容易踩坑的链路。真正有价值的流程图,必须能回答:

  • 订单/支付/库存/发货这几个对象的状态如何变化?
  • 库存不足/支付失败/超时关闭这些异常发生后,系统怎么闭环?
  • 回调竞态出现时,谁说了算?补偿路径是什么?

当你把这些讲清楚,再去画图就会变得很“工程化”:每个节点都有责任方、每条分支都有终态、每个关键点都能落到实现和测试。

如果你希望把文字流程快速变成一张可交付的图(并导出 PNG / draw.io 给评审或写文档),可以直接用: