开源航空订票系统需求与流程设计:从查询到出票的完整状态机实践

发布时间:2026/9/9 0:43:38

开源航空订票系统需求与流程设计:从查询到出票的完整状态机实践
航空订票系统这种项目一听“需求与流程设计”很多开发者的第一反应是“这不就是个CRUD吗”。但真正上手去做你会发现查询、下单、支付、出票、退改签这一条链路里到处是坑。我把这个开源项目的需求文档、流程图、数据库设计和核心状态机整理开放出来就是想让想练手业务系统的同学能有一份贴近真实工程的可参考素材。这个开源项目不追求花哨的技术栈重点在把业务逻辑想清楚。它适合正在做毕业设计、准备面试项目、或者刚进入企业接触业务系统的后端同学去阅读。哪怕你不写代码作为产品或者测试把里面的流程设计过一遍也会对航空订票这类预订交易系统有更具体的认知。1. 项目定位与需求全景图1.1 为什么值得做开源航空订票系统航旅预订属于典型的交易型业务系统复杂度比普通的单商品电商要高。它要处理多城市、多日期、多航班、多舱位的动态库存还要对接支付、退款、异步出票、行程通知等环节。这种复杂度恰恰是练习系统设计的好素材。我在整理这个开源项目时想的不是做一个只能“查航班、下订单”的玩具而是尽可能把真实业务里会碰到的需求收敛进来。比如不同客票的退改规则、订单超时未支付怎么处理、支付回调重复通知怎么保证幂等、出票失败怎么补偿。这些需求单独看都不难但组合在一起就需要一个清晰的需求框架来托底。这个项目对学习者的帮助主要有三点一是能直观理解一个业务系统从需求到流程再到数据模型是怎么逐步落地的二是可以通过状态机和接口设计理解订单生命周期管理的关键三是可以把这个项目作为模板迁移到酒店预订、门票预约等同类交易系统。1.2 角色与核心能力矩阵从使用角色来看这个系统分为乘客端和管理端两条主线。乘客端面向普通用户核心能力包括用户注册登录、航班查询、创建订单、在线支付、订单详情查看、退票改签申请。航班查询要支持按出发城市、到达城市、出发日期三个关键条件检索同时还能按时间段、航空公司、价格区间做二次筛选。用户下单时需要填写乘机人信息包括姓名、证件类型、证件号码。管理端面向航空公司的运营人员核心能力包括航班计划维护、航线创建、机型舱位配置、航班时刻调整、订单查询、退款审核。航班计划维护又涉及航线、航班号、执飞日期、起飞到达时刻、开放销售状态、各舱位可售数量等。这两个角色是所有后续流程设计的基础。需求阶段最常见的错误就是一上来直接画数据库表或者写Controller接口结果发现漏了后台管理员需要用的航班维护功能又重新改表。先做角色和用例梳理能避免后面返工。1.3 非功能需求不只是能跑通就行很多人做完功能演示就认为项目完成了但在航空订票场景下非功能需求比功能需求更容易暴露设计短板。首先是高并发。遇到节假日和促销节点航班查询和下单请求量会呈几十倍增长。这个开源项目建议在架构设计阶段就预留缓存和限流的概念虽然实现可以简化但设计文档里必须写清楚。其次是数据一致性。订票系统最容易出现两类一致性问题座位超售和订单状态错乱。座位超售的根源是并发扣减没有做控制订单状态错乱则是因为支付回调、用户取消、超时释放之间存在竞态条件。项目文档里把这些问题全部做了显式设计而不是等代码写崩了再补。再次是可审计性。每一笔订单的创建、支付、出票、改签、取消、退款都要有操作记录。后台运营人员、系统定时任务、用户前台请求三类操作来源都需要落到日志或操作流水表里。这一点很多初学者会忽略但真实生产环境下是刚需。2. 流程设计从查询到出票的核心链路2.1 航班查询与筛选最基础也最容易被低估的环节航班查询是用户接触系统的第一个页面也是承载并发量最高的接口。很多初次做这个项目的人会直接把航班信息存一张表然后写一个SQL按条件查询。这样做演示当然没问题但一旦需要支持“同一个航线每天多个航班”“有航班计划但当天不执飞”“各舱位可售数量动态变化”单表模型就撑不住了。我把这一块拆成了航线、航班计划、执飞实例三个层次。航线是静态定义比如北京到上海航班计划是某个航班号在哪些日期执飞比如CA1501每周一三五执飞执飞实例是某一天具体的航班它才有独立的库存和状态。用户查询时先根据出发城市和到达城市找到航线再匹配日期范围内的执飞实例最后返回航班列表和实时可售舱位。这个设计的好处是航班取消时只需要维护某一天的执飞实例状态不需要删掉整个航班计划增加一个新航班时也只需要新增一条班期规则不需要提前创建一年的执飞记录。从需求与流程设计的角度看这是把“一张航班表”升级为“具备时间维度的航班模型”的关键点。2.2 下单-支付-出票状态机怎么设计才稳订单是整个系统的核心聚合根。订单状态如果只设计成“待支付”和“已支付”两种后面接支付、对账、退改签时一定会被自己坑到。我在项目里把订单状态设计为完整的状态机。初始状态统一为待支付。用户提交订单后进入该状态此时系统会锁定所选航班对应舱位的座位并设置支付超时时间。如果在超时时间后仍未支付订单自动取消座位释放。用户在待支付状态主动取消订单称为用户取消同样会释放座位。用户支付成功后订单进入已支付状态。此时系统并不直接把票出给用户而是进入出票中状态由后台异步任务调用出票引擎。出票引擎在实际航司系统中对接的是GDS或者航司接口开源版本中为了便于演示会用本地模拟出票逻辑代替。出票成功订单变为已出票出票失败则触发自动退款流程。这张状态机图是整个需求与流程设计的核心。订单模块的每个方法都必须基于当前状态判断可执行的动作。比如已出票状态下不允许重复支付已取消状态下不允许再发起支付退款申请只有在已出票状态下才允许发起。状态流向清楚之后代码很难写乱。2.3 退改签流程经常被低估的重头戏退改签是航空订票系统里最容易出bug的地方因为规则多、组合多。我整理这个开源项目时把退改签规则单独拆成一张规则表而不是硬编码在代码里。规则表大致包含这几个维度客票类型经济舱特价、经济舱标准、头等舱、退改类型自愿退票、非自愿退票、自愿改期、距离航班起飞的天数区间、对应手续费比例或固定金额。例如特价票在起飞48小时前退票收取票面价80%的手续费起飞前48小时内不允许退票。具体规则每家航司不一样但作为需求设计规则表的模式是通用的。退票流程上用户提交退票申请后系统根据规则表计算应退金额生成退款记录。开源版本先进入退款审核状态管理端可以审核通过或驳回。审核通过后才真正执行退款操作同时更新订单状态和释放座位。改签流程类似需要先判断新航班是否还有对应舱位的库存有库存则锁定新座位再按规则计算改期费用。这个流程最能体现“需求设计”的价值。如果一上来就写退票接口很容易把退款金额、手续费、订单状态三个字段的联动逻辑漏掉最后算出来的金额对不上账。3. 数据模型与接口约定3.1 核心数据表设计思路需求与流程设计落到最后一定会转化为数据结构。这个开源项目的核心表我列出来供参考表名核心字段说明设计要点user用户ID、登录名、密码盐值、姓名、证件信息密码不可明文存储证件信息做脱敏展示airport机场三字码、城市、机场名称机场与城市是多对一关系route航线ID、出发机场、到达机场外键一条航线是城市对机场对的组合flight_schedule航班号、航线ID、班期、起飞/到达时刻班期用位图或字符串标记周几执飞flight_instance执飞实例ID、航班计划ID、执飞日期、状态取消航班只改此表状态cabin_stock执飞实例ID、舱位代码、总座位数、已售座位数库存扣减必须使用原子SQL或乐观锁fare_rule客票类型、退改规则JSON、价格策略规则尽量数据化避免代码写死orders订单号、用户ID、执飞实例ID、舱位、状态状态枚举必须和状态机设计一致passenger_info订单ID、乘机人姓名、证件号、票号一单可多乘机人但要支持部分退票payment_record订单ID、支付流水号、支付金额、状态用业务订单号做幂等键refund_resord订单ID、退款流水号、退款金额、审核人、状态退款状态必须闭环支持审核驳回operation_log操作来源、操作类型、业务单号、操作内容所有写操作都走日志记录订单表里“状态”这个字段在整个项目里使用频率最高建议使用数字枚举并与代码里的常量或枚举类一一对应不要用容易被误解的字符串。比如已支付与已出票在外界看都是用户侧已经付过款但是在系统内部必须严格区分否则对账时会把未出票的单子统计为有效票。3.2 对外API的核心约定这个开源项目的接口遵循REST风格约定统一返回结构。每个接口的正常返回包含业务码、消息和数据体异常时也会返回对应的业务码而不是直接把500错误抛给前端。接口方法说明关键入参/api/flights/searchPOST航班查询出发城市、到达城市、日期、舱位类型/api/ordersPOST创建订单执飞实例ID、舱位代码、乘机人列表/api/orders/{id}/payPOST发起支付订单ID、支付方式/api/payment/callbackPOST支付回调第三方支付流水号、订单号、支付结果/api/orders/{id}/cancelPOST取消订单订单ID、取消原因/api/orders/{id}/refundPOST申请退票订单ID、乘机人列表/api/orders/{id}GET查询订单详情订单ID支付回调接口是这里最需要注意的业务约束。第三方支付平台会异步通知结果并且会重试多次接口必须做到幂等。实现时先用订单号加支付流水号查本地记录如果已处理过就直接返回成功不重复更新订单状态。这部分在需求文档里要单独强调因为新手很容易忽略重复通知的问题。3.3 并发与座位库存设计座位库存是这个项目里最容易出并发问题的地方同时也是面试时最容易拿得出手的亮点。舱位库存表保存的是某个执飞日期的某个客舱等级对应的已售座位数和总座位数剩余座位数就是两者之差。用户下单时不能先查剩余数再做内存判断必须用原子操作扣减。推荐的做法是使用数据库的原子更新update cabin_stock set sold_count sold_count 1 where flight_instance_id ? and cabin_class ? and sold_count total_count。这样单条SQL就能保证不会超售执行后影响行数为0就代表没有库存了。如果系统访问量很大可以再引入Redis缓存库存但DB仍然是最终一致性的来源。下单时需要锁定座位但用户未必会支付。所以设计里必须有超时释放机制。开源项目里安排了一个定时任务每分钟扫描待支付状态且超过支付时效的订单将其状态改为已取消同时执行sold_count减一操作。这里还要考虑一个问题用户重复下单占用了多个座位超时后自然释放对真实业务来说这个体验并不好但作为基础版本先把资源释放的链路走通后续可以再扩展真人校验、防重复下单等逻辑。4. 从需求到可运行系统实操落地过程4.1 需求文档到用例拆解这个开源项目发布时我附上了完整的用例文档。核心用例包括查询可用航班、提交订单、支付订单、取消订单、申请退票、审核退票、维护航班计划、调整航班价格等。每个用例都写了主流程、扩展流程和异常流程。举例说明提交订单这个用例。主流程是用户先搜索航班、选择舱位、填写乘机人信息、提交订单、系统锁定座位、返回待支付订单。扩展流程是提交时库存不足系统提示无票。异常流程是用户连续双击提交形成两个订单系统需要在前端做防重复提交后端也需要在短时间内使用相同请求参数创建订单时返回已有的待支付订单而不是重复创建。把这些用例写清楚比直接贴代码更能帮助理解和交流。使用例能保证前后端对同一个业务流程的理解一致减少联调阶段的返工。4.2 先画流程状态图再画页面原型我自己在项目里踩过不少坑最大的一个心得是不要先打开代码编辑器写实体类先打开白板画流程图和状态图。特别是订单、支付、退款三条核心路径一定要把状态节点和触发动作画到没有疑问之后再动手。页面原型在这个项目里可以很简单用主流原型工具画几个关键页面就行。真正需要投入时间画的是业务流程图。比如支付回调到来时如果订单已经处于已取消状态这时不能直接把订单改成已支付而是要进入一笔新的待支付或者提示用户重新下单退票审核驳回后订单要回到已出票状态并且退还的座位不能重复释放。从需求与流程设计的角度来说流程图和状态图比页面原型重要得多。页面只是交互呈现状态图才是系统行为的内在约束。开源项目里我把这几张图整理成了电子文档作为代码仓库的一部分发布就是希望使用者先看图而不是先跑代码。4.3 最小可运行闭环的实现顺序给想基于这个开源项目做二次开发或者学习的人一个实现顺序建议。第一步建议先做航班查询这个功能不涉及支付和状态流转能快速跑通前后端联通。第二步做用户认证和创建订单此时把座位库存的原子扣减加进去体会一下库存控制的逻辑。第三步做支付回调Mock和订单状态流转这是最核心的部分。第四步做退改签流程和管理端的审核功能。大概的顺序就是你先把一条能走通的主链路搭起来也就是查询到出票然后再加入退票、改签、超时释放这些分支链路。不要试图第一版就把所有功能全部完成分支逻辑很容易在初期拖垮整体进度。这个项目发布的状态已经是完整跑通的状态可以直接作为课程设计参考也可以在此基础上继续扩展。5. 常见问题与排查技巧实录5.1 订单状态不一致支付回调与订单状态不同步开发阶段和试用阶段最容易出现的问题就是用户已经支付成功但订单状态还停留在待支付。排查时先看支付回调有没有被正确接收最常见的原因有三个回调接口地址配置错误、回调处理里没有正确使用事务或幂等键、回调解析时因为签名校验失败被抛弃。建议在日志里增加支付回调原始报文打印同时表里记录第三方支付流水号。这样收到用户反馈后可以按订单号反查支付记录确认是回调缺失还是逻辑处理异常。定时对账机制也需要写进去每天把本地为已支付但支付平台查不到的单子捞出来核对。5.2 座位超售与并发扣减有些同学实现座位扣减时是先select查剩余座位数再在应用层判断大于0最后update更新已售数量。这种写法在并发情况下一定会超售。正确的做法是前面提到的单条原子update语句而且扣减前不用查询。另外还要注意扫码重复提交的问题。用户在下单页快速点了两次提交按钮可能生成两笔订单占用两个座位。解决方案是前端提交按钮置灰后端同时按用户ID和执飞实例ID做短时间重复单校验。这类问题在演示环境不太容易暴露但在真正的并发请求下非常致命。5.3 时区与航班日期显示问题航班日期和起飞时间涉及多个时区很多人会忽略。数据库如果直接存本地时间之后做国际化展示时就会乱套。这个项目里约定数据库统一存UTC时间接口返回ISO8601字符串前端根据用户本地时区做展示。在排查问题过程中看到过很多次日志里的时间比真实时间晚8小时的情况基本都是时区没有统一。排查时间问题时先看日志里的时间戳带不带时区标识再确认数据库连接URL里serverTimezone参数是否正确。这类问题在真实项目中很常见但不影响业务流程正确性所以常被归为“看起来不影响功能”的隐患。5.4 数据安全与操作审计开源项目必须强调安全红线。用户密码不能明文存储至少要做加盐哈希再入库推荐直接使用成熟加密库。乘机人证件号、手机号等敏感信息在接口返回时要做脱敏处理日志里也不要打印完整原文。支付接口必须有签名机制支付回调要做验签。操作审计这块建议做成一个独立模块后台管理员的所有关键操作比如审核退票、调整航班状态、修改价格都记录到操作日志表。这个模块本身不复杂但能极大提升系统的可追溯性后期排查问题的时候作用很大。最后再分享两个小技巧我自己在整理这个开源项目时最大的体会是流程设计文档比代码本身更有复用价值。代码逻辑每个项目不同但订单状态机、库存扣减规则、支付幂等处理这些设计思想互相之间是可以迁移的。你如果学会了这里面的思路再去做酒店预订、景点门票、活动票务会发现大部分东西都能直接复用。第二个建议是看完文档后一定要自己动手把状态机画一遍再对照开源代码看实现是否一致。只看不画很容易以为自己懂了真让你写的时候还是会在支付回调、超时释放这些点上卡住。希望你在这个项目里获得的不是一堆可运行的代码而是把复杂业务拆清楚的能力。

相关新闻

Android Studio学生信息管理系统源码解析:从环境搭建到功能实现

Android Studio学生信息管理系统源码解析:从环境搭建到功能实现

2026/9/9 0:33:38

简介:这套基于Android Studio开发的学生信息管理系统源码,是作者大四毕业设计的高分项目(评审分98.5分),主要面向计算机相关专业准备毕业设计、课程设计或期末大作业的学生,也适合需要Android项目实战练习的…

VSCode Claude Code插件配置指南:从安装到中转API避坑全解析

VSCode Claude Code插件配置指南:从安装到中转API避坑全解析

2026/9/9 0:33:38

先说个实际场景:你在VSCode里装好Claude Code插件,满心期待让它帮你改代码、写测试、梳理项目结构,结果点开面板要么报401认证失败,要么提示model not found,要么直接转圈半天最后超时。这几乎是每个刚接触Claude Code…

Claude Code完整实战指南:安装配置、MCP与Skills应用全解析

Claude Code完整实战指南:安装配置、MCP与Skills应用全解析

2026/9/9 0:33:37

老早就想把Claude Code的完整用法写下来,这阵子项目里的文件整理、脚本调试、代码重构,几乎都是开着终端用Claude Code在处理。它的思路和传统的AI聊天窗口完全不同,不是一问一答就结束,而是给你一个正在干活的人:你交…

AI编程返工多?用Spec Kit流程规范需求与任务,减少无效代码

AI编程返工多?用Spec Kit流程规范需求与任务,减少无效代码

2026/9/9 1:23:39

不知道你有没有过这种经历:让 AI 帮忙写一个功能模块,它几分钟就生成了一整段逻辑清晰的代码,你甚至还没来得及夸它,测试那边就报了一堆“不是你需求”的问题。到了下午,你又重新描述了一遍需求,AI 又一次爽…

opencode实战指南:终端AI编码代理安装配置与排错全攻略

opencode实战指南:终端AI编码代理安装配置与排错全攻略

2026/9/9 1:23:39

最近这一个月,我的终端里多了一个常驻工具:opencode。它不是IDE里的插件面板,也不是网页对话框,而是一个跑在命令行里的AI编码代理。我身边越来越多同事开始搜"opencode安装""opencode使用教程""opencod…

51单片机红外遥控解码:NEC协议与定时器中断实现空调遥控码接收

51单片机红外遥控解码:NEC协议与定时器中断实现空调遥控码接收

2026/9/9 1:23:39

简介:面向51单片机学习者和红外遥控解码开发者,这套格力空调遥控码接收程序采用中断方式完成信号采集,并在1602液晶上实时显示解码结果,适合用于智能家电控制、红外协议分析或毕业设计参考。压缩包共56个文件,总大小5.…

基于STM32的电流电压检测模块设计:从硬件到标定

基于STM32的电流电压检测模块设计:从硬件到标定

2026/9/9 1:23:39

简介:面向STM32嵌入式开发与电源监测场景,这份资料提供了一套基于STM32F103的电流电压检测模块完整实现方案,适用于工业控制、物联网设备中的实时电压电流采集与远程监控。压缩包共183个文件,约25.51MB,核心包含C源码&…

FM17550 NFC芯片开发资料包实战:从原理图到DEMO代码

FM17550 NFC芯片开发资料包实战:从原理图到DEMO代码

2026/9/9 1:23:39

简介:复旦微电子的FM17550开发资料包,面向NFC/RFID硬件设计及嵌入式开发工程师,适合正在选型评估、需要电路参考或驱动移植的中级开发者使用。压缩包共138个文件,大小仅3.74MB,以PDF硬件手册、C/H源代码、Keil工程文件…

EEGdenoiseNet基准数据集实战:脑电信号深度学习去噪全解析

EEGdenoiseNet基准数据集实战:脑电信号深度学习去噪全解析

2026/9/9 1:13:39

简介:EEGdenoiseNet 是一套面向深度学习脑电(EEG)去噪研究的公开基准数据集,适用于科研人员、算法工程师及神经工程相关专业学生,用来训练、测试和横向对比各类去噪模型。数据集中包含 4514 个干净 EEG 时期、3400 个 …

中国人民大学杨琳团队《Nature Communications》 | 全球潮汐湿地土壤有机碳时空格局与环境驱动:一项2009-2020年的全球评估

中国人民大学杨琳团队《Nature Communications》 | 全球潮汐湿地土壤有机碳时空格局与环境驱动:一项2009-2020年的全球评估

2026/9/9 1:14:29

本文首发于“生态学者”!从“湿地面积”到“土壤碳密度”:为什么需要重新认识潮汐湿地蓝碳变化?潮汐湿地位于陆地与海洋的交汇地带,包括红树林、盐沼和潮滩,是全球重要的蓝碳生态系统。其土壤能够长期储存大量有机碳&a…

adb抓包

adb抓包

2026/9/8 4:55:53

前言 本文介绍如何通过 tcpdump 在 Android 手机上抓取网络数据包,并在电脑端使用 Wireshark 进行分析。适用于需要排查 App 网络请求、分析接口调用或调试网络问题的开发与测试场景。1. 手机要有 root 权限2. 下载 tcpdump3. adb push C:\Users\zhangkuixun\Downlo…

大模型推理镜像极简瘦身:从 25GB 巨无霸到 3GB 精简镜像实战

大模型推理镜像极简瘦身:从 25GB 巨无霸到 3GB 精简镜像实战

2026/9/8 22:37:26

大模型推理镜像极简瘦身:从 25GB 巨无霸到 3GB 精简镜像实战 在云原生基础设施中,容器镜像体积直接决定了服务的部署速度与弹性扩容敏捷度。对于传统的 Go / Java 微服务,镜像体积通常被严格控制在 50MB 到 200MB 以内,拉取镜像只…

扩散模型图像恢复实战:从DDPM原理到PyQt5可视化系统

扩散模型图像恢复实战:从DDPM原理到PyQt5可视化系统

2026/9/9 0:03:36

简介:面向毕业设计场景的PyQt5扩散模型图像恢复项目,提供完整Python源码与项目说明,适合图像处理、深度学习方向的高年级本科生与研究生参考。项目在模块设计上覆盖图像处理、扩散模型、参数配置、用户界面与结果评估五部分,具体涉…

开关电源环路裕量测试实战:相位裕量与增益裕量详解

开关电源环路裕量测试实战:相位裕量与增益裕量详解

2026/9/9 0:03:36

1. 项目概述:为什么环路裕量测试是电子工程师绕不开的“体检项目”“从零开始的电子工程师生活(6)——环路裕量测试”,这个标题一出来,老电源工程师可能已经下意识摸了摸示波器探头,新同事则大概率在想&…

定时插座芯片怎么选?专用定时IC与单片机MCU选型对比

定时插座芯片怎么选?专用定时IC与单片机MCU选型对比

2026/9/9 0:03:36

拆开市面上不同价位的定时插座,你会发现一个有意思的现象:有的里面躺着一颗黑色的软封装芯片,丝印都看不清;有的则是一块小小的蓝色或绿色PCB,上面赫然印着STM8或者STC的字样。同样叫"定时插座",…

远程协作的工作台整理

远程协作的工作台整理

2026/9/8 4:23:39

远程协作的工作台整理远程协作的核心不是再加一个工具,而是让交接信息足够完整。异步任务要写明目标、输入位置、完成标准和需要决策的人。 工作台的最小配置 将日程、待办、代码和沟通入口收拢到少数固定位置;通知按紧急程度分层。工作台不需要模仿办公…

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

2026/9/8 3:19:39

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能分类:[AI/大模型]细分主题:AI 增强型 CI/CD 流水线自动化与 GitOps 实践:Agent 工作流、工具调用与任务拆解:从原型到生产的验收清单很多团队在尝试用大…

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

2026/9/8 4:00:23

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场分类:[工程技术]细分主题:Kubernetes 生产环境运维与排障实战:可复制的项目复盘模板与决策记录大部分团队的事故复盘报告,最后都变成了躺在 Confluence 或钉…