Herald
积分

积分账户(Credit Account)

积分账户是 Realm 内积分的隔离单元:每个账户持有独立余额、覆盖一组 Client App,只有被覆盖的应用才能消费。积分按来源分五种类型入账,可用余额由逐笔发放的账本派生——你看到的余额永远就是你能花的余额。

积分账户是 Realm 内积分的隔离单元:每个账户持有独立余额、覆盖一组 Client App,只有被覆盖的应用才能消费。积分按来源分五种类型(充值、会员、注册、免费周期、主动发放)入账,可用余额由逐笔发放的账本派生——你看到的余额永远就是你能花的余额。

它解决的问题是:一个 Realm 下可能同时跑多条业务线,比如一个 AI 对话应用和一个图片生成应用,它们的积分要分开结算、分开消费,不能串。

给谁看

创建和管理积分账户的 Realm Admin,以及在建消费对接前想搞清楚"应用的积分到底放在哪"的开发者。消费侧的完整行为见积分消耗。

账户模型

字段说明
bucket_key标识,匹配 ^[a-z0-9-]{1,64}$,Realm 内唯一
name展示名
description可选描述
display_order展示顺序
enabled是否启用。禁用后对新用户不可见、不可购;已持有该账户的用户仍能消费剩余积分
覆盖集该账户覆盖的 Client App 列表。不能为空;只有被覆盖的应用才能消费这个池

Herald 没有"默认账户"的概念:每一个账户都是管理员显式建出来的,每一笔发放都由显式规则路由。一个 Client App 可以同时被多个账户覆盖——此时消费会跨这些账户扣减(见积分消耗)。

几个会直接报错而不是静默处理的约束:

  • 覆盖集不能为空。创建和更新都校验,空集返回 400。
  • 从一个积分账户移除已挂载的 Entitlement Mapping 会被拒绝,返回 bucket_orphan_mapping。要移动映射,先把它挂到目标积分账户。
  • 改覆盖集只影响未来的路由,不回收已经发出去的余额。

五种积分类型

账户里的积分按来源分别记账。余额、后台概览、流水都沿这五个 key 展开:

key含义
topup充值积分(用户主动购买)
subscription会员积分(订阅套餐赠送)
registration注册积分(注册时一次性赠送,永久有效)
free_periodic免费周期积分(按周期自动发放)
granted主动发放积分(管理员或 SDK 发放)

余额:钱包与积分账本

每个(用户, 账户)对对应一个钱包。钱包只保留终身累计数(按来源累计发放 / 累计消费)和一个状态(active / frozen / closed——冻结或关闭的钱包会拒绝消费),它并不是余额本身。

可用余额由积分账本(credit ledger)派生:每笔发放写一条账本行,带 granted / used / revoked / remaining 四个金额、积分类型、可选的 expires_at(过期时间)与 effective_at(未来生效时间),以及状态(active / revoked / expired / fully_used)。可用余额 = 所有"生效中、未过期、状态 active"的行的 remaining 之和——这个判定谓词与消费时选取账本行的谓词完全一致,所以你看到的余额就是你能花的余额。

带 expires_at 的行过期后由后台任务扫出:行的状态翻成 expired,不再计入余额,并写一条回收记录。一笔发放是否过期,由发放规则的有效期策略决定。

管理积分账户

管理台:/{realmId}/manage/billing/credit-buckets 是账户目录,旁边有余额矩阵概览页。

API(全部需要 Realm Admin 的 points.manage 权限):

方法与路径说明
GET /api/realms/{realmId}/billing/credit-buckets账户列表,带覆盖应用数和规则引用数
POST /api/realms/{realmId}/billing/credit-buckets创建,返回 201
GET /api/realms/{realmId}/billing/credit-buckets/overview余额矩阵:每个账户 × 每种积分类型,外加跨账户合计
GET /api/realms/{realmId}/billing/credit-buckets/{bucketId}详情,含覆盖集
PUT /api/realms/{realmId}/billing/credit-buckets/{bucketId}更新(覆盖集整体替换,不是合并)
DELETE /api/realms/{realmId}/billing/credit-buckets/{bucketId}删除,返回 204

两个常遇到的报错:

  • 400 bucket_key_duplicate:key 在这个 Realm 内已存在。
  • 409 bucket_in_use:账户还有活跃订阅、有余额的持有者,或存在历史引用(任意钱包 / 流水 / 账本行)。响应会分列 activeSubscriptions、holdersWithBalance、historyReferences。有历史的账户应当禁用而不是删除——删除只留给从未使用过的账户。

积分怎么进入账户

  • 支付入账:Entitlement Mapping 的积分发放规则在购买和续费时向映射绑定的账户发放。见付费墙配置和计费架构。
  • 注册与免费周期积分:由 Realm 的发放规则路由(GET/PUT /api/points/{realmId}/registration-rules)。零到多条规则,每条独立指定一个目标账户;一次事件可同时扇出到多个账户。没有启用规则就不发——不存在隐式的兜底账户。
  • 主动发放:管理台走 POST /api/points/{realmId}/grant(granted 类型);你的后端可通过 Client API Key 走 POST /api/ext/points/{realmId}/grant(同为 granted 类型,SDK 来源)。

相关文档

On this page