做计费模块时,最容易吵起来的不是单价多少,而是「这一段算谁的」——用量跨了几个档位怎么切、计量单位按次还是按量、余额清零和退订怎么算。这篇不讲某家具体数字,只给一套规则设定与实现规范的写法,让你能拿着一份文档去和研发、财务、客服对齐口径。
做计费模块,真正容易吵起来的往往不是单价,而是「这一段用量算谁的」。一笔请求可能横跨两个档位,一次订阅可能中途改配置,一次退款可能发生在已经用掉大半额度之后。这些边界没写清楚,研发按自己的理解实现,财务按自己的口径对账,客服夹在中间被用户追着问,最后只能靠临时拉群拍板。
这篇不讲某家具体怎么收费,只给一套规则设定与实现规范的写法。目标是你能拿着一份文档,把研发、财务、客服三方叫到一起,半天内把口径对齐,而不是等到第一次月结才发现对不上账。
先把计量单位和计费维度定死
计量单位是整份规范的地基。按次、按量、按时长,这三者只能选一个作为主口径,其他维度比如并发数、模型档位、调用来源,统一当作倍率处理,不要再开第二套账。一旦出现两套账,对账时就必然出现「A 系统说一百、B 系统说九十八」这种扯不清的情况。
- 主口径
- 唯一决定扣费金额的计量方式,其他维度只做系数叠加
- 取整规则
- 向上取整、四舍五入还是截断,必须写死并配测试用例
- 计费单位
- 系统实际扣费的最小颗粒度,可以和展示单位不同
- 展示单位
- 用户界面上看到的数量或时长,换算关系要可追溯
- 取整规则要写进文档并让前端在用户下单前就能看到预估,别等扣完费才发现多算了一格
- 计费单位和展示单位可以不一致,但两者之间的换算公式要固定,不能随场景变
- 倍率一旦引入,要规定倍率的生效时点和叠加顺序,多个倍率相乘还是相加要提前说清
- 主口径之外不是不能统计其他维度,但那些数据只能进报表,不能参与扣费计算
档位怎么切,跨档那一笔算谁的
档位的第一个决策是整段统一价还是分段累进。整段统一价指的是用量落在哪个档,整笔就按那个档的价格算;分段累进指的是把用量切成几段,每段各按所在档计算。同一个用量,两种算法结果差别很大,选完要在文档里写死,不允许同一产品混用两种模式。
第二个决策是边界归属。用量刚好落在档位临界点时,算低档还是高档,必须统一。建议一律归低档,理由是用户视角更自然,也更容易解释,同时要把这个规则写进测试用例,避免研发各写各的。
| 规则点 | 推荐做法 | 什么情况下不适用 |
|---|---|---|
| 档位算法 | 整段统一价或分段累进,二选一写死 | 同一产品线存在历史存量用户时,需按生效时间区分 |
| 边界归属 | 临界点统一归低档 | 监管或合同另有约定的场景需单独列外 |
| 跨档结算 | 先扣旧档额度再进新档,按结算时点判定 | 实时扣费场景需改为逐笔即时判定 |
| 档位数量 | 控制在可解释范围内,便于客服说明 | 用量分布极长尾且波动大的场景可适当增加档位 |
- 确定档位算法在文档里明确写「整段统一价」或「分段累进」,并附一个用量跨两档的计算示例,让研发照着实现。
- 定义边界归属规定临界点归低档,并在测试用例里加至少三个刚好落在临界的输入。
- 写清跨档结算顺序说明是先扣旧档额度再进新档,还是一次性按结算时点判定,并说明月底对账时按哪个时点快照。
- 验证用同一笔用量分别跑一次实现结果和手工计算,两者一致才算通过。
状态与异常:续费、退订、降档、欠费怎么处理
计费系统的麻烦大多不在正常流程,而在状态迁移。新购、续费、升档、降档、暂停、退订、欠费,每一种状态变化都要写清已经产生的用量如何折算。特别是降档,剩余额度是保留、按比例折算还是直接清零,这是投诉高发点,必须单独成条,并给客服准备好统一话术。
- 列出全部状态迁移路径,每种路径标注已用量处理方式
- 降档场景单独定义额度处理规则,并说明生效时点
- 升档时已用量的补差逻辑要明确,是补差价还是从下期起算
- 退订要区分按比例退和按剩余期退,两种口径结果不同
- 欠费要有宽限期和恢复流程,不能让用户在一次失败扣费后立刻断服
- 额度过低要有阈值提醒,提醒触点和扣费触点分开,给用户反应时间
提醒机制值得单独设计。用户不该在毫无预告的情况下被断服,所以额度接近耗尽时要有提醒,提醒渠道可以和账单渠道一致。提醒之后到真正扣费之间留出缓冲,缓冲多久写进规范,不要靠研发临时决定。
实现规范与对账排查顺序
实现层面最重要的一条是:用量记录先落原始流水,再做聚合。聚合结果可以重算,但聚合表不能成为唯一事实来源。否则一旦聚合逻辑有 bug,历史数据就无法回溯,只能承认错误然后人工补账。
每笔扣费要保留可复现的四要素:计量单位、当时档位、边界归属规则版本、生效时间。四要素齐全,任何一笔账都能重放,财务问起来不需要研发翻代码。
- 比原始流水先把双方同期的原始用量记录拉出来对齐,条数和时间戳对不对得上,对不上就停在这一层查采集。
- 比分组聚合流水一致后,按相同维度分组求和,看聚合结果是否一致,不一致就查聚合逻辑和分组维度。
- 比档位映射聚合一致后,检查同一用量映射到的档位是否相同,重点看临界点附近的记录。
- 比应收金额前三层都一致,最后才比总额。总额对不上但前三层都对,基本就是取整或倍率的问题。
排查顺序不要跳步。很多人一上来就比总额,结果发现差了几块钱,然后开始猜原因,浪费一整天。按四层逐层比对,哪一层断了就停在哪一层,效率高很多。具体的历史数据到 价格追踪页(/price-watch) 核对当时的记录口径。
一份能过评审的规范文档该包含什么
规范文档的价值在于减少口头约定。评审时如果缺少以下六块中的任何一块,基本都会被退回补充。写文档的人要清楚,这份文档不是给自己看的,是给以后的自己和接手的人看的。
| 必含板块 | 写什么 | 缺了会怎样 |
|---|---|---|
| 单位定义 | 主口径、取整规则、展示换算 | 研发各自理解,对账口径分裂 |
| 档位表 | 档位划分、算法、临界归属 | 跨档用量结果不一致 |
| 边界规则 | 临界点、跨档结算顺序 | 月底对账找不到差异来源 |
| 状态迁移图 | 七种状态及用量处理 | 降档退订引发集中投诉 |
| 异常处理 | 欠费、失败重试、提醒 | 用户被断服且无预告 |
| 对账口径 | 四层比对顺序和快照时点 | 财务和研发各说各话 |
还有一条常被忽略:把「什么情况下不适用」写进去。比如按次计费不适合用量密集的高频场景,分段累进不适合档位极少且分布均匀的场景。写清楚不适用条件,后面才有人能拿着依据来讨论改规则,而不是靠拍脑袋。
规则版本要编号。改档位、改边界、改取整规则,都算新版本。历史账按当时生效的版本重算,不要就地覆盖旧规则,否则历史对账永久失去依据。版本记录可以放在规范文档附录里,和生效时间一起维护。
最后,如果涉及中转或第三方服务的计费口径差异,建议到 中转站目录(/sites) 看各家的接入说明,并交叉核对 可信度排行(/rankings) 里的稳定性记录,避免把对方的计费口径直接当成自己的标准。
下一步把这份规范当模板,先填单位定义和档位表两块,再去和研发、财务过一遍,比空谈价格有意义得多。→常见问题
分段计费和阶梯计费是同一个东西吗?
日常混用,但落到实现上是两回事。分段累进是把用量切开分别套不同单价再求和;整段计价是看总用量落在哪一档、整个用量都按那一档单价算。两者对同一笔用量的结果差别很大,所以文档里必须先写明是哪一种,不能只写「阶梯」两个字就交付。
跨档的那一笔到底该算低档还是高档?
没有唯一正确答案,关键是全站统一。一般建议把落在临界点的用量归到低档,理由是用户可预期、客诉少,也便于测试用例覆盖。选定后写进规范并标注版本,之后所有新业务都沿用同一条,不要因为某个客户来投诉就单独开口子。
计费规则改了,历史账单要不要重算?
分情况。如果只是新增档位、老档位不变,历史账不动,新规则从生效时间点往后执行;如果边界归属或计量口径变了,属于口径变更,需要按旧版本重算并出差异说明。不管哪种,规则都要带版本号和时间戳,否则出了问题没人能还原当时按的是哪套逻辑。