跳转至

积分与会员 · 账本可回溯与对账保障方案

IT 开发 / 运营日查用 · 2026-07-21 产品规则依据:家纺 AI 生图平台《积分与会员系统规则》v1.0(1 元 = 10 积分;三类积分;版本化价目与购时快照;追加式账本)。 现状对照:现行实现为「会员方案 → 单一 usage_quotas 扣点 + 订单分佣」,见 membership-agent-sales-guide.md。本文描述目标账务架构,用于改造设计与验收,不代表已全部落地。


0. 目标一句话

钱怎么来、积分怎么到、怎么扣、怎么提成——每一步都有不可改写的凭证;余额可由账本重放得出;每天能对上「支付通道 / 积分总账 / 提成」三本账。


1. 与现行系统的差距(改造必知)

维度 现行 目标规则
汇率 隐式「买方案送配额」 显式 1 元 = 10 积分
积分桶 单一 generation 配额 登录 / 充值 / 赠送 三桶,消耗优先级固定
单价 按 task_type + 分辨率附加 价目表版本:1K=12、2K=18、视频=84/10s
会员权益 方案字段即时读 购时权益快照;到期降级体验档
提成 购会员订单比例分佣 仅充值积分消耗 计提成 + 首两单实付提成
账本 transaction_ledger 偏流水 追加式、幂等、可回放、可对账

改造原则:先立账本与价目版本,再迁余额;禁止直接 UPDATE 余额而不写分录。


2. 核心设计原则(必须全部满足)

# 原则 含义
P1 追加式账本(Append-only) 余额变动只 INSERT 分录;禁止改历史行;纠错用冲正分录(reversal)
P2 余额可派生 balance = Σ(entries)(或按桶聚合);库内余额字段仅为物化缓存,对账以账本为准
P3 价目版本化 单价、套餐权益、赠送比例存在 price_catalog_version;改价只发新版本,旧单仍按旧版
P4 购时权益快照 支付成功瞬间固化 entitlement_snapshot;运行期权益读快照,不读「当前价目最新版」
P5 业务幂等 支付回调、扣点、签到、提成计提均带 idempotency_key;重复请求返回同一结果
P6 双凭证 人民币侧有 payment_records;积分侧有 point_ledger;提成有 commission_ledger;三者可交叉引用
P7 日切与冻结 自然日(建议业务时区 Asia/Shanghai)切日后只允许当日及未结账期间的业务;已日结批次只读

3. 版本化价目表(Price Catalog Versioning)

3.1 表设计建议

price_catalog_versions
  id / version_code (如 2026.07.21.1) / status(draft|active|retired)
  effective_from / effective_to / published_at / published_by
  note

price_catalog_items          # 某一版本下的计价项
  version_id / item_key (image_1k|image_2k|video_10s|…)
  unit / points_cost / amount_cny_display
  cost_ref_usd / cost_ref_cny   # 仅核算,不参与扣费

member_plan_versions         # 会员档位版本(可与价目同版本或独立)
  version_id / plan_tier (trial|basic|…)
  price_cny / cycle (month|quarter|year) / cycle_days
  bonus_rate / login_points_per_day
  sub_accounts / concurrency / storage_gb
  priority_generate / cs_level
  feature_flags (JSONB: image_all, video_seed, video_story, premium_video_quota…)
  first_purchase_points / cycle_login_points / cycle_total_points  # 可存校验用计算结果

3.2 规则

  1. 同时仅一个 active 价目版本对外售卖;draft 供运营预览。
  2. 改价 / 改套餐 = 发布新版本,旧版本 retired,历史订单 catalog_version_id 不变。
  3. 扣费时读取:优先用「用户当前权益快照上的 catalog_version_id」;若无快照(极端兜底)禁止静默用最新价,应告警。
  4. 种子数据写入版本表,验收用固定 version_code,避免环境间价差。

3.3 校验公式(发布前自动跑)

首充到账积分 = round(价格 × 10 × (1 + 赠送%))
周期登录积分 = 登录积分/天 × 周期天数
周期总积分 = 首充 + 周期登录

发布 member_plan_versions 时 CI/Admin 校验与规则表一致,失败禁止发布。


4. 购时权益快照(Entitlement Snapshot)

支付成功(或 Admin 补发)时一次写入、永不改写

user_entitlement_snapshots
  id / user_id / order_id (可空=运营补发)
  catalog_version_id / plan_version_id
  snapshot_json   # 完整权益拷贝:档位、赠送%、登录点/天、子账号、并发、存储、功能开关、客服等级…
  starts_at / expires_at
  status (active|superseded|expired)
  created_at

运行期读法

场景 读什么
能否用种草视频 / 并发上限 / 存储 当前 active 快照(若过期则合成「体验档默认快照」)
充值赠送比例 下单瞬间的快照或当时 active 价目(写进订单行)
每日登录积分额度 active 快照的 login_points_per_day
扣费单价 快照绑定的 catalog_version_idprice_catalog_items

升级 / 续费:旧快照 superseded,新快照 active不修改旧快照 JSON

到期:定时任务将快照标 expired;权益降级为系统内置体验档模板(仍建议落一条「降级虚拟快照」便于审计)。


5. 三类积分账户 + 追加式账本

5.1 账户桶(Point Buckets)

bucket ID 来源 有效期 计提成 消耗优先级
login 1 每日签到 到账后 24h
purchase 2 实付兑换 终生
bonus 3 充值/套餐附赠 终生

物化余额(缓存):

user_point_balances
  user_id
  login_points / login_expire_at
  purchase_points
  bonus_points
  version (乐观锁) / updated_at

真相源仍是账本;日对账发现不一致时以账本回放修复余额。

5.2 追加式积分账本

point_ledger_entries          # 禁止 UPDATE/DELETE(DB 权限或触发器)
  id (UUID)
  entry_no (全局单调雪花/序列,便于回放排序)
  user_id / master_user_id    # 子账号消耗记 master
  bucket (1|2|3)
  direction (credit|debit)
  points (正整数)
  balance_after_bucket        # 该桶变动后余额(便于抽查)
  biz_type   # login_claim|purchase_grant|bonus_grant|consume|expire|reversal|adjust…
  biz_id     # 关联业务主键
  idempotency_key  UNIQUE     # 全局或 (user_id, key) 唯一
  catalog_version_id          # 消耗类必填
  price_item_key              # image_1k / image_2k / video_10s…
  ref_order_id / ref_task_id / ref_payment_id
  actor_type / actor_id       # user|admin|system
  memo / created_at

一笔业务消耗若跨桶,拆成多行分录 + 一行汇总消耗单:

point_consume_tickets
  id / user_id / master_user_id
  product_type (image_1k|image_2k|video)
  total_points
  login_used / purchase_used / bonus_used   # 与规则文档一致,供提成
  catalog_version_id / unit_points / quantity
  task_id / idempotency_key UNIQUE
  status (held|posted|reversed)
  created_at / posted_at

流程建议(可审计):

请求(idempotency_key)
  → 预检余额(三桶按优先级模拟)
  → INSERT ticket(held) + 预占分录 或 行锁余额
  → 上游生图成功
  → ticket.posted + 正式 debit 分录
  → 失败则 reversal 冲正(仍追加,不删 held)

登录积分过期:定时任务扫描 login_expire_at,写 biz_type=expire 的 debit,金额=剩余 login;禁止直接把余额改 0

5.3 人民币侧仍追加

orders / payment_records     # 现状可保留并强化
money_ledger_entries         # 可选:实付、退款、冲正同样追加式
  amount_cny / direction / payment_channel / transaction_id
  idempotency_key / order_id

积分发放必须挂支付成功凭证

支付 success
  → money 入账(若有)
  → purchase_points credit = floor(实付元 × 10)
  → bonus_points credit = floor(实付元 × 10 × 赠送%) 或套餐表约定
  → 写 entitlement_snapshot
同一 payment.notify 的 idempotency_key 保证只入账一次

6. 幂等性设计

场景 idempotency_key 建议
支付回调 pay:{channel}:{transaction_id}
下单 Header Idempotency-Keyclient_request_id(现状已有)
签到领登录分 login_claim:{user_id}:{biz_date}
生图扣点 consume:{task_id}consume:{client_request_id}
登录分过期 expire_login:{user_id}:{claim_entry_id}
提成计提 comm:{consume_ticket_id}:{beneficiary_id}:{role}
退款冲正 reversal:{original_entry_id}refund:{order_id}

实现要点:

  1. 唯一约束在账本表;冲突则返回原结果(查询同 key)。
  2. 业务事务:先插幂等占位 / 账本,再改余额缓存;失败整单回滚。
  3. 支付通道验签 + 本地幂等,防止重放攻击导致双倍加点。

7. 账本回放(Replay)

7.1 用途

  • 余额修复、迁移校验、纠纷举证、灾备演练。

7.2 算法

输入: user_id, [from_entry_no, to_entry_no]
初始化三桶 = 0(或从某 checkpoint 快照)
按 entry_no ASC 回放 credit/debit
输出: 三桶余额 + 与 user_point_balances 差异

7.3 Checkpoint(加速日查)

point_balance_checkpoints
  user_id / as_of_entry_no / as_of_time
  login / purchase / bonus
  checksum

每日日切后对活跃用户写 checkpoint;回放从最近 checkpoint 开始。

7.4 只读 API / Admin

  • POST /admin/ledger/replay:指定用户回放并返回差异。
  • 禁止生产环境「静默改余额」;修复必须出 adjust 分录(双人审批)。

8. 三方对账(Reconciliation)

每日(建议 T+0 日切后 + T+1 上午复核)三本账对齐:

账本 数据源 对什么
A 支付通道 微信/支付宝对账单 payment_records.success 实付合计
B 积分总账 point_ledger_entries 当日 purchase credit ≈ 实付×10;bonus ≈ 赠送规则
C 提成账 commission_ledger 当日 purchase_used÷10×费率 与消耗票一致

8.1 对账批次表

recon_batches
  id / biz_date / type (payment|points|commission|cross)
  status (running|matched|mismatch|resolved)
  expected_json / actual_json / diff_json
  created_at / resolved_by / resolved_at

8.2 交叉勾稽恒等式(示例)

Σ payment.success.amount_cny(日) × 10
  == Σ point_ledger.purchase.credit(日, biz_type in purchase_grant)

Σ consume_tickets.purchase_used(日)
  == Σ point_ledger.purchase.debit(日, biz_type=consume)
  == Σ commission_ledger.purchase_points_consumed(日)   # 若每人一笔

Σ user_point_balances.purchase
  == Σ ledger.purchase (全量回放或 checkpoint+增量)

差异分类:missing_credit / double_credit / balance_drift / rate_mismatch / orphan_commission


9. 提成账本(与消耗拆分绑定)

commission_ledger_entries
  id / idempotency_key
  beneficiary_id / role (sales|agent_a|agent_b)
  user_id / consume_ticket_id / order_id(首两单)
  basis (first_two_orders|purchase_consume)
  purchase_points_consumed / amount_cny_basis
  rate / commission_amount_cny
  month / status (accrued|payable|paid|clawed_back)
  created_at

规则强制:

  • purchase_used > 0 的消耗票计提消耗提成。
  • login_used / bonus_used 不得产生消耗提成行。
  • 退款 / 消耗冲正 → 追加 clawed_back 分录,不改历史 accrued 行金额。

10. 研发与运营「日查」清单

10.1 自动日任务(建议 每日 00:30 / 09:00)

检查项 通过标准 告警
支付↔购点 实付×10 = purchase credit(容差 0) P0
赠送比例 bonus credit 符合订单快照赠送% P0
余额漂移 抽样 N 用户回放 = 物化余额 P0
登录分过期 expire 分录覆盖所有超 24h 未清零 P1
消耗拆分 ticket 三桶之和 = total_cost P0
提成勾稽 purchase_used 与 commission 一致 P0
价目一致性 当日消耗 catalog_version 均已 retired/active 合法 P1
快照过期 expires_at 已过仍 active 的快照数 = 0 P1

10.2 运营日查看板(Admin)

  1. 昨日实收 / 购点 / 赠点 / 消耗(三桶拆分) / 提成计提
  2. 对账批次状态:绿灯 / 红灯差异列表
  3. 异常用户:余额为负、login 过期未清、重复幂等冲突次数
  4. 一键「导出差异 CSV」给财务

10.3 研发日查

  1. 失败重试是否产生双分录(查同 idempotency_key)
  2. 死信队列:支付已成功但积分未到账
  3. 回放任务耗时与 checkpoint 覆盖率

11. 其他保障账目准确的方案(建议一并落地)

方案 作用
冲正而非修改 一切纠错追加 reversal;保留审计链
双人审批调账 Admin adjust 需 maker-checker;强制 memo + 工单号
行级乐观锁 / 账户锁 user_point_balances.versionSELECT FOR UPDATE,防并发超扣
消耗两阶段 held → posted,失败冲正,避免「图没出却扣点」或「图出了没扣点」长期不一致
子账号共用主账户 所有分录 master_user_id 指向主账号;子账号禁止独立充值(接口层拒绝)
业务日 + 时区统一 签到、提成月结、对账统一 Asia/Shanghai
不可变存储 账本表 PG 权限撤销 UPDATE;或同步写对象存储 WORM 备份
哈希链 / 日终 Merkle(可选增强) 每日对 entry 做链式 hash,防篡改举证
影子记账 / 双写校验期 迁移期旧配额与新三桶并行,每日 diff,达标后切流
财务关账 月结后锁定该月 commission 批次,补提只能记入下月调整
合同级验收用例 用规则文档中的数值(如基础档 6468/900/7368)做 golden test
成本核算旁路 成本参考($0.027 等)只进核算报表,永不进入用户扣费路径
告警与值班 对账 mismatch → Alertmanager;超时未 resolve 升级
定期外部审计导出 标准格式:分录全量 + 价目版本 + 快照,交财务/审计

12. 关键状态机(摘要)

stateDiagram-v2
  [*] --> OrderPending: 下单
  OrderPending --> Paid: 支付成功(幂等)
  Paid --> PointsCredited: 购点+赠点分录
  PointsCredited --> Entitled: 写入权益快照
  Entitled --> Consuming: 生图/视频
  Consuming --> TicketHeld: 预占
  TicketHeld --> TicketPosted: 成功入账三桶拆分
  TicketHeld --> TicketReversed: 失败冲正
  TicketPosted --> CommissionAccrued: 仅purchase_used>0
  Entitled --> Expired: 到期降级体验档

13. 落地节奏建议

阶段 内容
M1 价目版本表 + 权益快照 + 三桶余额 + 追加式 point_ledger + 幂等键
M2 消耗票拆分 + 登录分领取/24h过期 + 扣费走价目版本
M3 提成改「充值积分消耗」+ 首两单实付;commission 账本
M4 日对账任务 + Admin 日查看板 + 回放修复工具
M5 usage_quotas 迁移脚本 + 影子对账 + 切流

14. 验收标准(账务)

  1. 任意用户任意时刻:回放三桶 = 物化余额。
  2. 重复支付回调 / 重复扣点请求:积分与提成不双记。
  3. 改价后:旧用户按旧快照单价扣;新购按新版。
  4. 仅消耗登录/赠送分:提成表无新增消耗提成。
  5. 日对账三方恒等式连续 7 天无 P0 差异。
  6. 人工调账必有冲正分录 + 审批记录。

15. 版本记录

版本 日期 说明
v1.0 2026-07-21 初版:版本化价目、购时快照、追加式三桶账本、幂等、回放、三方对账、日查与其它保障项