spec.md 10.0 KB

Feature Specification: 国际机票(盘合 iFlight 分销接入)

Feature Branch: (待创建,暂未建分支/未提交)

Created: 2026-07-29

Status: Draft —— 范围与多项关键决策待定(见「待定决策」)

Input: 接入上海盘合 shpanhe 国际机票开放接口(http://open.shpanhe.com/api/iFlight),实现国际机票查询/预订等能力。凭证见 文档/旅游/API测试接口.txt


集成背景(已确认事实)

  • 盘合是分销平台,我方是分销商:从同平台国内机票文档出现的「票面价 / 机建税 / 燃油费 / 结算价 / 返点返现政策」可确认这是 B2B 分销结算模型,不是消费者直连航司/盘合的透传支付。
  • 测试凭证(国际机票)
    • AppKey:4298c05600816da82abdbc899cd0c344
    • SecretKey:7ad3915eaf9a47156adcd31a1c51f2df
    • 接口网关域名:http://api.panhe.net
    • 测试分销后台:http://fxtest.panhe.net(账号 15978194868 / 密码 086915
  • 接口文档可获取性:iFlight 在线文档(open.shpanhe.com/api/iFlight)需登录,自动抓取(HTTP/HTTPS/真实浏览器)均被屏蔽或超时失败,搜索引擎未收录。同平台国内机票文档 /api/flight 公开,可作为流程/签名/信封惯例的参考模板(国际机票大概率同源,待文档验证)。

资金模型:两层资金流(核心)

层级 方向 价格 通道
第一层(零售) 消费者 → 平台 零售价(票面价 + 税费 + 我方加价/返点) 平台自有支付通道(复用,见下)
第二层(结算) 平台 → 盘合 结算价 分销商账户(余额/授信/代扣,方式待文档确认)
  • 消费者全程不接触盘合。
  • 结算价与零售价的差 / 返点返现 = 平台利润
  • 第一层收款复用 foodie 现有支付通道,不为机票新建支付:当前 NewebPay 蓝新金流代码就绪但未启用,VNPay / ZaloPay 已废弃(详见 project-deprecated-code 记忆)。
  • 真正新增的复杂点不是支付通道本身,而是:零售价定价结算价/利润记账出票后资金核销与对账

待定决策(用户后续决定)

以下决策显著影响 spec 范围与用户场景,需用户拍板后再细化。当前 spec 先以「假设全流程」记录,范围边界以 D1 为准回收。

  • D1 — 范围边界:仅查票展示 / 查票+生单(不含支付出票)/ 全流程(查→订→付→出票→售后)。
  • D2 — 落地端:用户端(uni-app,消费者自助)/ 平台管理端(foodie-admin-vue)/ 两端。
  • D3 — iFlight 接口契约获取方式:用户提供完整文档 / 以国内机票 /api/flight 为模板推断(后续校正)/ 仅写业务级 spec、接口细节推迟到 plan 的 research 步骤。
  • D4 — 第二层(平台→盘合)结算方式:账户余额实时扣款 / 授信额度周期结算 / 下单网关代扣。(决定记账与资金风险设计)
  • D5 — 零售价定价策略:直接用票面价 / 票面价 + 固定加价 / 按返点反算。(决定利润模型)
  • D6 — 第一层(消费者)收款通道:是否启用 NewebPay 或使用当时可用通道。

⚠️ 硬阻塞:在拿到 iFlight 接口契约(D3)前,/speckit-plan 的 research 与 /speckit-tasks 的实现细节无法落地,本 spec 只能停留在业务级。


User Scenarios & Testing (mandatory)

优先级以「假设全流程(D1=全流程)」编写;若 D1 收窄为「仅查票」,则仅保留 US1,其余降级或移除。

User Story 1 - 查询国际航班(Priority: P1)

消费者选择出发/到达城市(三字码)、出发日期、舱等,查看可选国际航班及其舱位票价(票面价、税费、飞行时段、航司、中转信息)。

Why this priority:查票是整个机票功能的入口和最小可用形态,即使后续环节都不做,单查票展示也有独立价值。

Independent Test:给定一条真实国际航线 + 日期,调用查询能返回航班与价格列表并在前端展示。

Acceptance Scenarios:

  1. Given 消费者输入有效的出发地、到达地、日期,When 发起查询,Then 返回当日可选航班列表(含航司、起降时间、舱位、票价、税费、是否中转)。
  2. Given 无效或无航班航线,When 查询,Then 返回明确的「无航班」提示而非报错。
  3. Given 查询往返/联程,When 查询,Then 通过分段查询组合出往返/联程结果。

User Story 2 - 下单与支付(Priority: P2)

消费者选定航班舱位、填写乘机人信息后生成订单,按零售价通过平台支付通道付款。

Why this priority:完成「能买到票」的核心交易闭环。

Independent Test:从选定航班到支付成功,生成一条待出票的机票订单。

Acceptance Scenarios:

  1. Given 消费者选定舱位并填妥乘机人,When 提交订单,Then 生成机票订单并按零售价发起支付。
  2. Given 支付成功,When 平台收到回调,Then 订单进入「待出票」,平台据此向盘合按结算价下单/订座。
  3. Given 支付超时或失败,When 超时未支付,Then 订单自动取消、释放占座(若已占座)。

User Story 3 - 出票与售后(Priority: P3)

支付成功后由盘合出票,消费者获得票号;支持退票/改签等售后。

Why this priority:完成完整购票体验,但可晚于 MVP。

Independent Test:支付成功后能拿到真实票号并展示;能发起一次退票流程。

Acceptance Scenarios:

  1. Given 订单已支付且盘合侧下单成功,When 出票完成,Then 消费者可见票号/行程单。
  2. Given 出票失败,When 平台感知失败,Then 自动重试或退款,并通知消费者。
  3. Given 已出票订单,When 消费者申请退票/改签,Then 按航司规则计算手续费并退款/改期。

Edge Cases

  • 查票有结果但下单时座位已被占满(库存瞬时变化)如何处理?
  • 支付成功但盘合侧出票失败的资金兜底(退款给消费者 + 平台与盘合的结算对账)。
  • 价格在查票与下单之间发生变动(税费/汇率波动)。
  • 多乘机人部分出票成功部分失败。
  • 国际行程的护照/证件信息校验、签证提示(信息性,非校验)。
  • 币种与汇率:盘合结算币种 vs 消费者支付币种。

Requirements (mandatory)

Functional Requirements

  • FR-001:系统 MUST 支持按出发/到达城市(三字码)、日期、舱等查询国际航班,返回航班、舱位、票面价、税费、起降时间、航司、中转信息。
  • FR-002:系统 MUST 支持往返/联程查询(分段组合实现)。
  • FR-003:系统 MUST 在消费者选定舱位并填写乘机人后生成国际机票订单,订单含零售价与结算价两套价格记录。
  • FR-004:系统 MUST 通过平台自有支付通道收取消费者零售价款项(复用,不新建支付通道)。
  • FR-005:系统 MUST 在消费者支付成功后,按结算价向盘合完成下单/订座/出票,并记录票号。
  • FR-006:系统 MUST 记录每笔订单的两层资金流(消费者零售收款 + 平台与盘合结算价/返点),支持对账与利润核算。
  • FR-007:系统 MUST 支持出票失败的自动重试与退款兜底。
  • FR-008:系统 MUST 支持退票/改签,按航司规则计算手续费。
  • FR-009:功能范围(查票/下单/支付/出票/售后)以 [NEEDS CLARIFICATION: D1 范围边界] 为准。
  • FR-010:功能落地端(用户端/管理端)以 [NEEDS CLARIFICATION: D2 落地端] 为准。
  • FR-011:零售价定价以 [NEEDS CLARIFICATION: D5 定价策略] 为准。
  • FR-012:第二层结算方式以 [NEEDS CLARIFICATION: D4 结算方式] 为准。

Key Entities (include if feature involves data)

  • 航班查询结果(FlightSearchResult):航班段、舱位、票面价、税费、结算价、返点政策、起降时间、航司、中转。
  • 国际机票订单(IntlFlightOrder):订单号、消费者、航线、舱位、乘机人列表、零售价、结算价、状态(待支付/待出票/已出票/已退/已改)、关联支付流水、票号。
  • 乘机人(Passenger):姓名(拼音/英文)、证件类型与号码(护照等)、性别、出生日期、手机号。
  • 资金流水(FlightPaymentSettlement):消费者侧收款记录 + 平台与盘合的结算扣款/返点记录(用于对账与利润)。

Success Criteria (mandatory)

Measurable Outcomes

  • SC-001:消费者发起国际航班查询后,95% 的查询在可接受时长内返回结果。
  • SC-002:查票成功率(有航线的查询返回有效结果的比例)达到目标值。
  • SC-003:从下单到出票完成(含支付)的端到端时长满足消费者预期。
  • SC-004:每笔订单的两层资金(零售收款 vs 盘合结算)100% 可对账,利润可核算。
  • SC-005:出票失败场景 100% 有明确的退款/重试兜底,无资金悬空。

Assumptions

  • 平台已作为分销商在盘合完成开户,测试凭证可用,生产凭证后续提供。
  • 复用 foodie 现有的用户体系、App 端框架、支付通道,不为此功能新建用户体系或支付通道。
  • 国际机票与国内机票同源(同一平台),签名方式、请求信封、接口流程一致——此为推断,待 iFlight 文档验证。
  • 在拿到 iFlight 接口契约前,plan/tasks/实现 阶段无法进入字段级细节,本 spec 保持业务级。
  • 接口调用走服务端(AppKey/SecretKey 不下发前端),签名在服务端完成。
  • 测试先用 api.panhe.net 测试网关与测试凭证,生产环境与凭证后续切换。