首页 / 业务功能与流程 / 支付与订阅开通流程

流程总览

App 下单 → 创建 Checkout 会话 → 创建支付尝试 → 跳转提供商 → 支付
  → 提供商异步通知 → 校验/幂等 → 订单支付成功 → 订阅激活 → Seat 占用
  → 对账(定期)→ 未知状态恢复(补偿)

涉及 pay 模块事实分层(订单/尝试/通知/对账)与 subscription 模块激活链路,与绑定 Saga 联动。

Checkout 与支付尝试

  1. App 调用 AppPayCheckoutController 创建 Checkout 会话(PayCheckoutService.createCheckout:用户、类型、金额、产品映射)
  2. PayProductMappingService 选择提供商渠道(PayProviderAccountService 维护渠道账户)
  3. 创建支付尝试(PayAttemptPersistenceService / createAttempt),生成客户端幂等键与提供商幂等键
  4. 返回支付地址/凭证;PayReturnUrlValidator 校验回跳地址合法性
  5. 用户完成支付,App 可选 verifyStoreTransaction 校验门店交易

异步通知与状态迁移

  1. 提供商回调进入 PayProviderWebhookController:验签 + 幂等(attempt 幂等键)
  2. 通知事实落表,PayNotifyJob 驱动订单/尝试状态迁移
  3. 订单支付成功 → 发布订阅激活事件(绑定 Saga 的 paid.activation.requested 或独立激活链路)
  4. 通知失败进重试;超过阈值由 PayUnknownAttemptRecoveryJob 主动查询提供商
回调处理必须验签 + 幂等;处理失败进重试/Outbox,不直接修改业务行伪造成功。

订阅激活

  1. 支付成功事件触发订阅激活(subscription.paid.activation.requested
  2. Subscription 执行 handlePaidActivationRequested:创建/更新 subscription_active、记录 subscription_record
  3. 占用 subscription_seat(session/device guard 唯一)
  4. 回发 paid.activation-completed,绑定流程继续;到期由 SubscriptionExpireJob 处理过期

对账与未知状态恢复

机制实现说明
结算对账PaySettlementReconciliationJob定期以提供商流水核对订单/结算
差异 casePayReconciliationCaseJob + ReconciliationCaseService差异生成 case 人工/自动处理
未知尝试恢复PayUnknownAttemptRecoveryJob超时未回调尝试主动查询恢复
订单过期PayOrderExpireJob超时未支付订单关闭
提供商事件/资源PayProviderEventJobPayProviderResourceSyncJob同步提供商事件与资源状态

事实表与状态机

事实状态机(示例)唯一约束
Checkout 会话CREATED → ATTEMPT_CREATED → PAID / EXPIRED / CANCELLED会话 ID 唯一
支付订单CREATED → WAITING → SUCCESS / FAILED / CLOSED租户订单号、app_id+merchant_order_id
支付尝试CREATED → PROCESSING → SUCCESS / FAILED / UNKNOWN公开 attempt ID、客户端/提供商幂等键
订阅 activePENDING → ACTIVE → EXPIRED / CANCELLED / TRANSFERRED主体 + 产品组合