平台管理
计划和 Stripe 同步
计划是管理员直接创建的唯一面向客户的数据。
计划 CRUD 页面(/admin/plans)与 Stripe 配对,
因此您永远不需要接触 Stripe 仪表板来配置产品和价格 —
每次保存都会自动同步到 Stripe。
计划表
/admin/plans 列出每个计划及其核心属性、
使用它的工作区数量,以及同步状态药丸(绿色 = 与 Stripe 同步,
琥珀色 = 待处理,灰色 = 仅本地/免费)。
| 列 | 注释 |
|---|---|
| Name | 显示名称。可编辑。 |
| Slug | 稳定标识符。创建后锁定 — workspaces.plan_id 通过 Plan 表间接按 slug 解析,更改它会破坏发票。 |
| Monthly conversations | 配额。 |
| Price | 每月价格。更改它会归档旧的 Stripe Price + 创建新的。 |
| Workspaces | 今天有多少工作区在此计划上。 |
| Stripe IDs | 同步后的 Product + Price ID。免费/自定义计划显示 "—"。 |
| Active | 切换。非活动计划在客户端不可选择。 |
创建计划
New plan 打开表单。字段:
- Name — 必填。
- Monthly conversations — 必填。
0= 无限。 - Price (cents) — 必填。
0= 免费/自定义(跳过 Stripe)。 - Features — 切换:
remove_branding(和未来标志)。 - Active — 默认为 true。
保存时,服务器创建本地行,然后触发
StripeProductSync::syncPlan()。如果价格 > 0,
则创建 Stripe Product + Price,并将它们的 ID 保存在计划行上。
如果 Stripe 无法访问或配置错误,则保留本地行并显示 flash 错误解释失败 —
您可以重试同步而无需重新保存表单。
Sync 按钮
每行都有一个 Sync 操作,直接触发
StripeProductSync::syncPlan()。返回带有结果的 JSON,
因此 UI 可以内联显示 "Synced" / 错误而无需页面重新加载。有用当:
- 您更改了 Stripe 密钥并希望重新绑定所有内容。
- 之前的同步失败且您已修复底层问题。
- 您想验证计划的 Stripe 状态而不触碰表单。
编辑
编辑行为直观,除了两个微妙之处:
- 价格更改轮换 Stripe Price。 Stripe Prices 是不可变的,因此我们归档旧的并创建新的。现有订阅保留在旧 Price 上(祖父条款);只有新订阅使用新的。
- Slug 被锁定。 表单输入在编辑模式下禁用。
删除
计划永远不会破坏性删除。
destroy 操作软删除(is_active = false)
并归档 Stripe Product。原因:
workspaces.plan_id是真正的外键 — 删除会使孤立或级联。- 历史发票引用计划;我们需要能够永远查找它。
- 进行中的订阅需要稳定的计划来附加。
重新激活软删除的计划:编辑它并将 Active 切换回开启。 Stripe Product 取消归档,计划再次可选择。
免费/自定义计划
price_cents = 0 的计划永远不会同步到 Stripe。
它们只存在于互客鱼中 — 对于默认免费计划和手动制作的企业交易很有用,
您需要配额和功能标志但带外发票。
货币
通过环境中的 CASHIER_CURRENCY 全局设置。
默认为 USD。在具有现有 Prices 的部署中途更改货币是手动迁移 —
您需要归档每个 Stripe Price,更改 env var,然后同步每个计划以在新货币中铸造新 Prices。