1
0
forked from boos/BoosAPI
Files
BoosAPI/docs/superpowers/specs/2026-06-16-billing-closed-loop-design.md
T
boos 278b0c66b8 docs: 计费闭环系统设计 spec
双轨额度(USD 池 + 工作流积分池)、ledger-first 统一流水账、
消费明细/充值档位/超额预警/全量审计四块功能、A+C 混合积分计费、
Comfy 余额对账校准。分 6 期实现。

Co-Authored-By: Claude <noreply@anthropic.com>
2026-06-16 17:12:02 +08:00

150 lines
8.1 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 计费闭环系统设计
日期:2026-06-16
状态:设计已获批,待写实现计划
## 背景
BoosAPI 现有计费是零散拼接的:每个用户的 downstream API key 有 `max_cost`(美元上限)/ `used_cost`(已消耗),proxy 请求路径在 `used_cost >= max_cost` 时硬拦截返回 429;充值通过 Stripe 自动到账或 comfy_cloud 管理员确认到账,调用 `credit_user_balance` 增加 `max_cost`;新用户默认 $1 额度;usage_logs 按 key 记每笔消费。
缺口:ComfyUI 工作流执行不扣额度、无积分体系、无消费明细可视化、无充值档位配置、无低额度预警、无全量变动审计。
本设计把上述补齐为一个 **ledger-first(统一流水账)** 的计费闭环。
## 核心模型:双轨额度
- **USD 轨**:LLM 对话、生图、视频等所有走 `/v1/*` 的调用。沿用 `downstream_api_keys.max_cost/used_cost`。
- **工作流积分轨**:仅 ComfyUI 工作流执行。新建每用户独立的积分池,平台可管理。
两轨并行、互不换算。comfy_cloud 充值进积分轨;其他充值(Stripe)进 USD 轨。
## 数据模型
### 新表 `credit_ledger`(唯一真相源,所有变动记一行)
| 字段 | 类型 | 说明 |
|---|---|---|
| `id` | INTEGER PK AUTOINCREMENT | |
| `user_id` | INTEGER NOT NULL | 所属用户 |
| `track` | TEXT NOT NULL | `usd` / `points` |
| `entry_type` | TEXT NOT NULL | `recharge` / `admin_adjust` / `consume` / `refund` / `grant` |
| `amount` | REAL NOT NULL | 正=增 负=减(usd 用美元,points 用积分) |
| `balance_after` | REAL NOT NULL | 该轨本次变动后余额快照 |
| `ref_type` | TEXT | `usage_log` / `recharge_record` / `manual` / `stripe` 等 |
| `ref_id` | TEXT | 关联记录 id/public_id |
| `model` | TEXT | 消费类:模型名或工作流名(供聚合) |
| `operator` | TEXT | 操作者:管理员名 / `system` / `user` |
| `note` | TEXT | 备注 |
| `created_at` | TEXT DEFAULT (datetime('now')) | |
索引:`(user_id, created_at DESC)`、`(track, entry_type)`、`(user_id, track)`。
### 新表 `user_credits`(积分余额缓存)
| 字段 | 类型 | 说明 |
|---|---|---|
| `user_id` | INTEGER PK | |
| `points_balance` | REAL NOT NULL DEFAULT 0 | 当前积分余额(热路径读写) |
| `points_total_recharged` | REAL NOT NULL DEFAULT 0 | 累计充值积分(统计) |
| `updated_at` | TEXT | |
### 新表 `recharge_tiers`(充值档位,admin 可配)
| 字段 | 类型 | 说明 |
|---|---|---|
| `id` | INTEGER PK AUTOINCREMENT | |
| `track` | TEXT NOT NULL | `usd` / `points` |
| `amount_usd` | REAL NOT NULL | 支付金额(USD) |
| `grant_amount` | REAL NOT NULL | 到账量(USD 数或积分数) |
| `bonus` | REAL NOT NULL DEFAULT 0 | 赠送量 |
| `title` | TEXT | 档位标题 |
| `sort_order` | INTEGER DEFAULT 0 | 排序 |
| `enabled` | INTEGER DEFAULT 1 | 启用 |
### 余额派生策略:ledger + 缓存双写
- **USD 轨**:`max_cost/used_cost` 作快速余额缓存(拦截/展示零延迟读),每笔变动**同事务**写一条 `credit_ledger(track=usd)`。
- **积分轨**:`user_credits.points_balance` 作缓存,每笔变动**同事务**写 `credit_ledger(track=points)`。
- **关键不变量**:任何余额变动 = 缓存字段更新 + 一条 ledger,**同一 DB 事务**,事务失败整体回滚,绝不只改其一。
- ledger 是审计/明细/对账真相;缓存字段是热路径性能优化。
## 双轨记账接入
原则:所有动余额处,同事务"改缓存 + 写一条 ledger"。
### USD 轨
| 变动 | 现有代码 | 改造 |
|---|---|---|
| 充值到账 | `credit_user_balance`(payment.rs) | 同事务加写 ledger(usd, recharge) |
| 消费扣费 | `increment_key_usage`/`record_billing` | 同事务加写 ledger(usd, consume, model=模型名) |
| 管理员增减 | `adjust_user_balance` | 同事务加写 ledger(usd, admin_adjust, operator) |
| 额度拦截 | proxy `used_cost>=max_cost`→429 | 不变,补低额度预警信号 |
### 积分轨(基本新建)
| 变动 | 现状 | 新增 |
|---|---|---|
| 充值到账 | comfy_cloud 确认到账现加 USD | 改为加 `points_balance` + ledger(points, recharge) |
| 消费扣费 | 工作流不扣 | 工作流执行**成功后**按单价扣积分 + ledger(points, consume, model=工作流名);失败不扣 |
| 管理员发放/增减 | 无 | 新增 `adjust_user_credits` + ledger(points, admin_adjust) |
| 积分拦截 | 无 | 工作流执行**前**检查 `points_balance >= 单价`,不足拒绝;低额度预警 |
- 积分消费扣费点:`workflow/executor.rs` 的 `run_workflow` 成功收尾处(有 `ctx.user_id`),与现有"工作流按用户 key 记 USD 消费"平行。
- **comfy_cloud 充值改向积分轨**:行为变更,历史 USD **不迁移**,仅对切换后新充值生效,用 config 开关控制(可回滚)。
## 积分消费规则:A+C 混合
- **A 固定/分级单价**(主):工作流执行扣固定积分(config 默认值,可按工作流类型分级)。可预测、支持并发。
- **C 对账校准**(兜底):后台 cron 拉 Comfy 总余额对账,偏差超阈值提示管理员调单价。
## 四块功能
### A 消费明细(用户侧,明细+聚合)
- 新建 `GET /api/user/billing/ledger`:查该用户 credit_ledger,可按 track/type/时间过滤。
- 新建 `GET /api/user/billing/summary`:按天/按模型聚合,双轨分开。
- 扩展 `UsageRecords.tsx`:双轨切换 + 聚合汇总卡 + 明细列表。
### B 充值档位(本期可配置,订阅后期)
- 新建 `recharge_tiers` 表 + admin CRUD `GET/POST/PUT/DELETE /api/admin/recharge-tiers`。
- 改造用户充值:档位从 DB 读(替代 env 写死的 `USER_RECHARGE_OPTIONS`)。
- 扩展 `UserRecharge.tsx`(档位从接口拉)+ 新建 admin `RechargeTiers` 配置页。
### C 超额 + 预警(两轨硬拦 + 预警)
- USD 拦截已有(不动);积分拦截新建(工作流执行前)。
- 余额接口加 `lowBalance` 标志(余额 < 阈值,config 可配默认 20%)。
- Dashboard/充值页/视频助手:余额低显示预警条。
### D 审计对账(管理员侧,全量流水)
- 新建 `GET /api/admin/billing/ledger`:跨用户查 credit_ledger(按 user/track/type/时间过滤、分页)。
- 新建 admin `BillingAudit` 页:全量变动流水表(谁/何时/给谁/加减/原因),站点管理风格。
- 对账校准:cron 拉 Comfy 总余额,与积分消费 ledger 比对,偏差超阈值写 log + admin 告警标志。**不自动改数据**,仅提示,管理员手动调单价。
## 错误处理(不变量)
- 余额变动 = 缓存 + ledger 同事务;失败整体回滚。
- 消费扣费 best-effort 不阻断响应(沿用 record_billing 原则)。
- 积分轨:拦截是前置硬检查,扣费是后置;后置扣费失败已产出结果 → 记日志补偿。
- comfy 充值改向积分:config 开关控制,可回滚。
## 测试策略
- 单元:ledger 写入+缓存同步事务一致性;积分拦截(不足拒绝);单价扣费;充值进积分;管理员调整双轨。
- 复用现有 payment/billing 测试框架(in-memory SQLite)。
## 实现顺序(分 6 期,每期可独立上线)
1. **地基**:credit_ledger + user_credits 表 + 迁移;USD 轨记账接进 ledger(充值/消费/调整三处双写)。
2. **积分轨**:工作流积分扣费 + 拦截 + comfy 充值改进积分 + 管理员积分调整。
3. **A 消费明细**:用户侧 ledger/summary 接口 + UsageRecords 扩展。
4. **B 充值档位**:recharge_tiers 表 + admin 配置页 + 用户充值页接 DB。
5. **C 预警**:余额接口加 lowBalance + 前端预警条。
6. **D 审计 + 对账**:admin BillingAudit 页 + cron 对账校准。
## 新增清单小结
- **表**:credit_ledger(核心)、user_credits(积分缓存)、recharge_tiers(档位)。
- **后端接口**:user billing ledger/summary、admin recharge-tiers CRUD、admin billing ledger、adjust_user_credits、积分拦截/扣费。
- **前端页面**:admin RechargeTiers、admin BillingAudit;扩展 UsageRecords / UserRecharge / Dashboard。
- **cron**:Comfy 余额对账校准任务。