Skip to main content

Documentation Index

Fetch the complete documentation index at: https://tech.illasoft.com/llms.txt

Use this file to discover all available pages before exploring further.

概述

kira-sg-billing 是独立 Hono 服务,集中处理所有 Stripe 交互:订阅、Booster 购买、Portal、Webhook。2026-02 从 kira-be 拆分,支持 US/SG 双区域 Stripe 账户,按用户 billing_region 路由。 kira-be 侧保留的只有「使用时的 credit 扣减」(src/ai/libs/billing.ts)和「用户删除时的 Stripe customer 清理」,所有订阅和支付流程都走本服务

部署形态

平台Fly.io
区域sjc + fra 双机
每机资源512 MB / 1 CPU
端口8081
入口bun run dev(实际:src/bootstrap.tssrc/index.ts
公网域名billing.kira.art

路由清单

Method + Path用途认证
POST /billing/checkout创建订阅 Checkout SessionJWT
POST /billing/checkout/booster一次性 Booster 购买JWT
POST /billing/portal客户自助 PortalJWT
POST /billing/webhook/usUS Stripe WebhookStripe 签名
POST /billing/webhook/sgSG Stripe WebhookStripe 签名
POST /billing/daily日常任务(预留)密码保护
GET /health健康检查

双区域路由

resolveRegion(user) — 结账/Booster 时的区域选择

if (user.plan !== 'free' && user.billing_region) {
  → 用已有的 billing_region(US 或 SG)
} else {
  → 默认 SG(2026-02 后新订阅默认走 SG)
}

resolvePortalRegion(user) — Portal 时的区域选择

基于活跃订阅历史:如果用户曾在 US 订阅过,Portal 回到 US;否则 SG。避免用户的历史发票被隐藏。

Plans 与 Credits

PlanCredits / 月变体
free0
basic1000basic_year
pro2000pro_year
max6000max_year
年付变体按月度 credits 等比折算(pro_year = 24000/年)。

Boosters(一次性)

SKUCredits
booster_small100
booster_medium300
booster_large1000
Booster 充到 user_profiles.addon_credits,与月度 credit 分开结算;月度 credit 每月重置,addon_credits 持续累积直到用完。

Stripe Webhook 处理

关键事件

事件处理
customer.subscription.created记录 customer_id / customer_id_sg,设 billing_region
customer.subscription.updated升/降级处理;月度 credit 按新 plan 补发/保留
customer.subscription.deleted降级到 free,保留 customer_id 便于重订阅
invoice.payment_succeeded发放月度 credit(覆盖上月余额)
invoice.payment_failedPostHog 事件 + 降级流程
checkout.session.completed (mode=payment)Booster 充值到 addon_credits

Webhook URL 配置

在 Stripe Dashboard 为两个账户分别配置:
  • UShttps://billing.kira.art/billing/webhook/us,签名 secret 存 STRIPE_WEBHOOK_SECRET
  • SGhttps://billing.kira.art/billing/webhook/sg,签名 secret 存 STRIPE_WEBHOOK_SECRET_SG

数据模型(user_profiles)

字段说明
customer_idUS Stripe customer ID
customer_id_sgSG Stripe customer ID
billing_region"us""sg",未订阅为 null
plan当前 plan slug
credit月度 credits(下月重置)
addon_creditsBooster credits(持续)
last_credit_issued_at最近一次月度 credit 发放时间(防重复)

环境变量

# Stripe(US)
STRIPE_SECRET_KEY
STRIPE_WEBHOOK_SECRET

# Stripe(SG)
STRIPE_SECRET_KEY_SG
STRIPE_WEBHOOK_SECRET_SG

# 共用
SUPABASE_URL
SUPABASE_KEY           # service_role
POSTHOG_API_KEY
SENTRY_DSN
NODE_ENV

与 kira-be 的协作

职责分工

动作发生位置
创建订阅 / Boosterkira-sg-billing(Stripe Checkout)
发放 credits(webhook 触发)kira-sg-billing(UPDATE user_profiles)
使用时扣减 creditskira-be src/ai/libs/billing.ts
Plan 准入检查kira-be checkVideoEligibility / checkMusicEligibility
删除用户时清 Stripe customerkira-be src/hono/user/index.ts:33-88

kira-be 的 credit 扣减

// kira-be/src/ai/libs/billing.ts
minusCredit(userId, cost, taskId?) 
Supabase RPC: deduct_credits(p_user_id, p_cost, p_task_id?)
  // Postgres 原子扣减,先扣 credit 再扣 addon_credits
RPC 函数 deduct_credits 用行锁保证并发安全,且写入 credit_deductions 表留审计。

迁移对照(从 kira-be 搬走的)

原 kira-be 路由现 kira-sg-billing 路由状态
POST /billing/checkoutPOST /billing/checkout已迁
POST /billing/checkout/boosterPOST /billing/checkout/booster已迁
POST /billing/portalPOST /billing/portal已迁
Stripe webhook(原统一端点)/billing/webhook/us + /webhook/sg分区改造
kira-be 的 src/hono/billing/ 目录如还存在,应标为 deprecated 或删除。

最近重要变更

  • c716e47 端口从 8080 → 8081(避免与 kira-be 冲突)
  • 8c9fd92 SG 区域配置完善
  • 111f29a 用户 profile not found 时的 500 → 404 修正
  • 新增 GitHub Actions Fly deploy workflow

Caveat

  • webhook 端点必须区分 US / SG;用错签名 secret 会导致 Stripe 401
  • 升级 plan 时 credit 立即补足到新 plan 月度上限,但不会重置 addon_credits
  • billing_region 一旦设置,除非用户完全退订后重新订阅到另一侧,否则不再切换