定价决定收多少,计费决定你到底有没有收到。
这个系列解决什么问题
一个人做订阅产品,收费这件事通常在第 30 天就上线了,然后在第 300 天开始对不上账。问题不在支付通道,而在通道和产品之间那一层:订阅有几个状态、状态之间怎么迁移、升级按什么公式补差、扣款失败重试几次、退款要不要开贷记单、发票号能不能跳号、月底怎么证明账是平的。
这个系列把这一层拆成十篇:先把订阅写成一条状态机,再把试用、续费、暂停、取消的五个时点定死;然后处理三种金额变更(升降级、按量、退款),三种不顺利(失败扣款、拒付、漏单),以及两张必须连续的单据(发票与贷记单);最后回答「这些零件该不该自己造」与「怎么验收」。
它服务的是一个每月只有几个小时做账的人。 没有财务系统、没有对账专员、没有第二位能看懂账本的人;你能投入的是每月四十五分钟对账,和一套能重放的检查。
核心主张:五条口径
- 计费是状态机,不是布尔字段。
is_paid这个字段一旦出现,重复扣款就只是时间问题。 - 金额只在最小单位里算。 数据库存分,公式里用整数,展示时才除 100。
- 一次变更只产生一条账本记录。 改订阅、开票、收款、退款,各留一条,任何两条都能对上。
- 失败是正常路径,不是异常。 每月 6% 的续费会失败,重试与宽限期要写在主流程里。
- 计费系统的价值在可对账,不在功能多。 能重放一年前的账单,比多支持一种折扣更重要。
10 篇速览
| # | 文章 | 核心内容 | 阶段 |
|---|---|---|---|
| 01 | 计费是一条状态机:五个状态、九条迁移与一次多收 420 美元 | 五个状态、九条合法迁移、幂等键 | 模型 |
| 02 | 订阅生命周期:试用、续费、暂停、取消与五个时点 | 五个时点、试用转化、取消生效时点 | 时点 |
| 03 | 升降级与按比例计费:九笔变更、十七天与 4.53 美元 | 一个公式、三处易错、升级与降级的非对称 | 变更 |
| 04 | 按量计费与计量:一百二十九万六千条事件怎么变成一张账单 | 四步聚合、阶梯价、去重与迟到事件 | 计量 |
| 05 | 失败扣款与催收:五次尝试、五十五个百分点与七天宽限 | 重试日程、回收率、宽限期与邮件 | 催收 |
| 06 | 退款、撤销与拒付:三张单据与一次少收 270 美元 | 部分退款公式、贷记单、拒付证据 | 退出 |
| 07 | 发票、收据与税务:一百零八张单据与七个必填字段 | 号段连续、七个字段、含税与不含税 | 单据 |
| 08 | 对账与收入漏损:一百零五行结算单与 0.4% 的差异 | 三张对账表、补拉兜底、漏损账 | 对账 |
| 09 | 买还是自己写:七个判据与 4,200 行计费代码的账 | 七个判据、两条路线成本、可外包比例 | 决策 |
| 10 | 计费验收:十二项检查、四维评分与一次季度演练 | 十二项检查、四维加权、3.78 与沙箱 | 验收 |
三条阅读路径
路径 A:还没开始收费。 先读 01 把状态机画出来,再读 02 把五个时点写死,最后读 09 判断哪些零件该买。这条路径的重点是「第一笔钱进来之前,别把账做死」。
路径 B:有订阅,但每月对不上账。 先读 05 看失败扣款是不是被当成异常漏掉了,再读 06 把退款与贷记单补上,用 08 的三张对账表把差异找出来。这条路径的重点是「先承认有漏损,再定位在哪一段」。
路径 C:要做按量计费或出海收税。 先读 04 把计量到出账的四步定下来,再读 07 把发票字段与含税口径分开,最后用 10 做一次季度演练。这条路径的重点是「计量与单据都不能事后补」。
与其它专题的边界
站内已有定价、财务、合规与多租户内容,但都不实现「价格怎么变成账单」。下表说明本组不重复什么。
| 既有内容 | 它讲什么 | 本组边界 |
|---|---|---|
| 一个人把价格定对:定价、付费墙与涨价 | 成本下限、模型、套餐、试用形态与涨价 | 它决定收多少;本组把已定的价格变成状态机、账单与单据 |
| 一个人把用户留住:激活、留存与复购 | 续费率、升级动机、流失分诊与召回 | 它看行为与留存;本组实现续费日、按比例计费与失败重试 |
| 一个人的财务:现金流、runway 与月度结账 | 四张表、收入确认、成本清点与月结 | 它按确认口径记账;本组产生它要对的账单与贷记单 |
| 一个人的公司:主体、税务与合规 | 主体、税种、申报、合同与知识产权 | 它判断该缴什么税;本组只把税率与发票字段做成参数 |
| 一个人的多租户:组织、角色与数据隔离 | 组织、席位、权限与数据隔离 | 它保证席位数量对;本组保证金额与状态对 |
| 一个人把 API 做成产品:对外接口与开发者体验 | 配额、限流、Webhook 与版本弃用 | 它管调用许可;本组把调用量聚合成账单行 |
| 一个人的架构:技术选型、模块边界与演进 | 模块边界、幂等与补偿、技术债 | 它给通用幂等模式;本组给计费专属的迁移守卫与重放 |
| 一个人的运维:可用性、告警、事故与值班 | 容量水位、告警降噪与事故复盘 | 它管系统活着;本组管每一笔交易的钱对不对 |
| 独立开发者的资产韧性 | 收款账号、云账号与恢复演练 | 它保证账号能接管;本组保证账单能重放 |
| 一个人的消息系统:事务邮件与送达率 | 事务邮件基线、分层与退订 | 它保证催收邮件送达;本组决定什么时候发第一封 |
| 一个人的前 100 天:从想法到第一批付费用户 | 验证、手工交付、上线与首次收费 | 它处理第一笔钱;本组处理第二笔到第一万笔 |
| 一个人的隐私工程:数据地图、最小化与删除权(10 篇) | 数据地图、最小化、合法性依据与同意、政策一致性、数据主体请求、删除、保留期、跨境与供应商、泄露响应、十二项验收 | 那组讲账单里的个人数据与 7 年法定保留;本组讲订阅状态、按比例计费与对账 |
| 一个人的数据搬家:导入、去重、迁移与退出(10 篇) | 迁移漏斗、导入契约、字段映射、去重合并、幂等重跑、人工代导入、窗口与回滚、附件限额、导出退出、十项验收 | 那组讲导入批次与计量口径;本组讲订阅状态、按比例计费与对账 |
| 一个人的质量守门:验证预算、回归清单与发布门禁(10 篇) | 47 缺陷与三条红线、12 条关键路径、三层配比、38→26 回归、六项门禁、四级缺陷、测试数据、不可逆保护、测试债、十项验收 | 那组讲发布门禁与关键路径验证;本组讲订阅状态、按比例计费与对账 |
| 一个人的安全基线:十四个入口、十七个密钥与一次 72 小时响应 | 14 个攻击面、认证与枚举、会话撤销、17 个密钥三档、四条边界、41 个依赖与 186 条告警、四类限流、9 类审计日志、72 小时三段响应、20 项验收 | 那组把支付账号列为不可逆入口并给保护;本组讲订阅状态、按比例计费与对账 |
| 一个人的性能与账单:4.2 秒的首屏、一千二百次查询与每月 210 美元 | 4 项预算与 20 格、RUM 与慢查询、412→168 KB、1,200→3 次查询、0→86% 缓存、34 秒导出、7→4 个第三方、210→118 美元、3 次回归告警、10 项验收 | 那组讲账单里的基础设施成本;本组讲订阅状态、按比例计费与对账 |
| 一个人的企业客户:九家询价、一百四十八道问卷与 134 天的第一单 | 9 家询价与 130 h、96 天采购、148 题问卷、7 个子处理者、SLA 43.2/216 分钟、26 h SSO、4 周试点、38 天到账、8 h 实施、10 项验收 | 那组讲企业 PO、账期与发票流程;本组讲订阅状态、按比例计费与对账 |
| 一个人的开源产品:4,200 个 star、一百八十个付费与一年 612 小时的维护 | 4,200 star 与 1,949 美元、612 h 维护、214 依赖、48,600 行 78/22、1,180 个 issue、214 条告警、23 个赞助者、9 家双许可、17 位贡献者、10 项验收 | 那组讲开源项目的收入结构;本组讲订阅状态、按比例计费与对账 |
这十篇不承诺「按这套做就不会算错」,也不推荐任何支付通道。可复算的部分全部用四则运算给出算式;不可复算的部分(通道费率、税务辖区、供应商能力)明确指向官方文档。所有数字都是教学假设,代入前请换成自己的订阅数与账单笔数。
本组统一口径
全组共用一组教学假设,各篇引用时不换分母:
产品:一人 SaaS,与既有组同一产品;账号 344,付费订阅 120
套餐:个人档 12 美元/月 × 100;团队档 30 美元/月 × 20 → 标价 MRR 1,800
计费周期:月付 84(个人 70 + 团队 14);年付 36(个人 30 + 团队 6)
年付价 = 10 个月价:个人 120/年、团队 300/年 → 年付现金 5,400/年
年付按月直线确认 450/月;月付确认 1,260/月 → 确认收入 1,710/月
标价差 1,800 − 1,710 = 90/月(年付两个月免费);年确认收入 20,520
订阅状态:active 113 + past_due 7 = 120 付费;trialing 18;paused 2
本月取消 4 → 3.33%
账单:月付续费 84 + 年付续费 3 + 新购 6 + 升降级 9 + 退款 3 = 105 笔/月
webhook:420 事件/月;丢失/重投 1.5% = 6.3;疑似重复 0.9% = 3.8
按比例计费:升级 6、降级 3;价差 8、剩余 17 天 / 30 天 = 4.53/笔
失败扣款:84 × 6% = 5.0 笔/月;重试 4 次回收 55%
退款 36/月 = 432/年;拒付 3.8 笔/年;单据 108 张/月 = 1,296/年
钱相关表 7 张 / 全库 34 张;billing 模块 4,200 行 / 全库 62,400 行 = 6.7%
计费事故(14 个月 3 次):多收 420 + 少收 270 + 重复退款 120 = 810
按量计费:12 客户 × 108,000 = 1,296,000 条/月;5 分钟桶 8,640 个
机会成本 40 美元/小时;供应商抽成 0.5% = 102.6/年
对账:结算单 105 行/月;差异 0.4% = 0.42 行;45 分钟/月
1,710 是不含税确认收入,1,800 是标价 MRR。 凡写「收入」的复算一律用 1,710;年付两个月免费造成的 90/月差额不是折扣费用,而是收入口径差。
金额只在最小单位里算。 数据库存分、公式用整数、展示时除 100;这条口径决定了 4.53 这类数字在系统里其实是 453。
105 笔是「账单对象」的数量,不是支付次数。 一次重试会产生新的支付尝试,但不产生新账单;两者混算会让失败率虚高。
所有成本都是教学假设。 40 美元/小时、6% 失败率、55% 回收率只用来展示数量级;真实估算请用自己最近三个月的结算单。
使用说明
先画状态机,再写任何计费代码。 五个状态与九条迁移画不出来,后面的试用、暂停与退款都会变成 if-else。
把「失败」写进主流程。 重试日程、宽限期与降级策略要在第一版就有,不能等第一次扣款失败再补。
每月留四十五分钟对账。 不是月底补账,而是固定一天把结算单与内部表逐行比;差异超过 1 行就开始查。
发票字段先于发票模板。 七个字段定不下来,模板换十次也不合规。
本组的证据与使用方法
证据类型。 本组用的是「订阅台账 + 账单流水 + 结算单 + 贷记单 + 事故记录」:五个状态的实际分布、每月 105 笔账单、420 个 webhook、三次计费事故的金额与根因、14 个月的差错率。没有「最佳实践」式的断言。
如何使用。 先用 01 的九条迁移对照自己的状态字段,再用 03 的公式复算最近三笔升降级,用 05 的重试日程检查失败扣款是否被当成异常,最后用 10 的十二项检查做一次季度体检。
如何复核。 取最近一个月,把结算单的每一行与内部 payments 表对上;再取最近十笔退款,看是否都开了贷记单。两项都能对上,这套基线才适用。