Billing implements reserve -> commit -> refund against bl_quota and bl_ledger with row-level locking and idempotency keys; the refund commits on its own transaction so a failed request cannot silently keep a user's quota. Task implements the unified task centre over the state machine. Identity issues and resolves users. Remaining domains are placeholders whose READMEs state what belongs there and what must not.
1.8 KiB
1.8 KiB
packages/billing/ — 配额与计量(V1)
⚠️ V1 不收费(TD-28)。本域在 V1 的职责是配额限制 + 计量, 不含任何支付、订单、购买、会员能力。
已实现
bl_quota_rule(规则配置化,改配置不发版,FR-BILL-04)bl_quota(按period_key自然重置,无需定时任务清零)bl_ledger(流水是真相,余额是缓存)- 预扣三段式
reserve → commit → refund(架构 §7.4,FR-BILL-05) - 服务端硬校验(FR-BILL-06);退还幂等(refund 键由 reserve 键派生)
架构约束(不可妥协)
V1 的配额账本与 V2 的点数账本必须是同一张表。 V1 只用 system_grant /
consume / refund 三种 tx_type,V2 增加 purchase / gift。这样 V2 上
支付时不需要数据迁移,也不需要重写扣减逻辑。不要为了"V1 更简单"把表拆开。
为什么是预扣不是直接扣
长耗时任务可能失败,直接扣会产生「扣了额度没拿到结果」的客诉。V1 虽不涉及 金钱,用户对"次数被白扣"的敏感度不比扣钱低,而且 V1 没有客服退款兜底手段, 只能靠机制保证。
待实现
- FR-BILL-03 任务奖励发放(签到/完善资料/反馈/邀请/分享,同任务同周期幂等)
- 每日对账:余额由流水重算校验,不一致则告警。V1 就要做,否则 V2 上支付时 对账逻辑得从零开发且无历史数据验证。
- 设备/账号/IP 三重限流(FR-BILL-06)
- Redis 配额计数器 + PG 落账的两级结构(架构 §10)
文案约束(FR-BILL-07)
额度相关提示里不得出现任何价格、购买、会员、升级字样,只提供「等待恢复」
与「做任务换额度」两条路径。tests/unit/test_response_envelope.py 会扫描全部
错误码文案。