本域总览见《账号计费中心 · 结构大纲》。本文为该域完整设计:定位与边界 / 角色与依赖 / 数据模型 / 核心流程 / 接口契约 / 关键约束与验收标准。
定位:全仓「这个客户此刻能不能用」的唯一判定者与唯一下发者。本域回答三件事——客户处于五态中的哪一态;状态键里放什么(载荷契约);读侧怎么判、何时放行。它是全仓契约最敏感的一个域:键名、载荷、版本语义与读侧规则是跨服务契约,写侧改了字段而读侧不认,会以「放行欠费客户」或「误封已充值客户」两种相反形式暴露。
核心概念
| 概念 | 承载 | 语义 |
|---|---|---|
| 状态键 | 状态存储中的客户级键 | 对外实时准入媒介,唯一生产者为本域、消费方只读;键缺失或过期一律放行 |
| 派生态 | state |
active / grace / overdue / banned / closed 五值,判定生命周期优先 |
| 封锁位 | blocked 与 block_reason |
拒绝语义的载体:quota 按额度拒绝,status 按状态拒绝 |
| 宽限窗 | grace_until |
仅 grace 态透出;窗是否走完由消费方按自身时钟判定 |
| 准入真相 | available |
唯一公式 = 现金 + Σ(在营未过期赠金剩余) + 信用额度;大于 0 即放行 |
| 状态版本 | state_version |
客户级单调版本,库层在行锁内取全局序列赋值;写侧去旧专用 |
| 欠费标记 | overdue_since |
派生量,供报表、清单与欠款分级使用;不是准入真相 |
关键口径
边界
能力矩阵
| 能力 | 本域 | 计费路由 | 数据面网关 | 运营面 | 门户用户 |
|---|---|---|---|---|---|
| 判定派生态 | ✓(唯一实现) | ✗ | ✗ | ✗ | ✗ |
| 写状态键 | ✓(唯一生产者) | ✗ | ✗ | ✗ | ✗ |
| 读状态键 | ✗ | ✓ | ✓ | 仅投影 | 仅投影 |
| 状态查询端点 | ✓(提供) | ✓ | ✓ | ✓ | ✗ |
| 状态标记与宽限设置 | 语义在本域 | ✗ | ✗ | ✓ | ✗ |
| 派生态展示 | ✗ | ✗ | ✗ | ✓ | ✓(本人) |
上游依赖
| 上游 | 依赖内容 | 语义 |
|---|---|---|
| 钱包与账务域 | 现金余额、赠金剩余、信用额度、宽限截止 | 可用额度公式的唯一输入 |
| 钱包与账务域 | 欠费标记重算结果 | 派生量,供清单与账龄分级 |
| 账号与身份域 | 客户标识与工作区归属 | 状态键的键主体 |
| 订购与支付域 | 客户创建点 | 创建即写键的触发来源 |
下游被引用
| 引用方 | 引用内容 | 语义 |
|---|---|---|
| 数据面网关 | 状态键与封锁语义 | 每请求前置准入,按原因分流到额度拒绝或状态拒绝 |
| 计费路由 | 状态查询端点 | 扣费前判定整批拒绝,在途损失入台账 |
| 门户与自助 | 派生态与宽限截止 | 欠费告知与还款入口的展示口径(详见 D12) |
| 风控与合规域 | 欠款账龄与封锁分级 | 提醒 / 催收 / 冻结的事件输入 |
| 通知与触达域 | 变更事件 | 欠费与解封告知的触发面(投递不在本域) |
| 运营管理 | 状态与宽限的只读投影 | 客户台账与审计索引 |
本域无自有表。事实载体有两个:状态存储中的客户级状态键(键名、载荷与存活期共同构成对外契约)与客户表上的状态与版本列(status / grace_until / grace_granted_at / overdue_since / credit_limit / state_version)。前者是派生态的对外投影,后者是判定输入与版本序的落点;两者都不由本域独立拥有,本节只描述读取关系与派生依赖。
| 表 | 职责(本域视角) | 关键字段 |
|---|---|---|
| customers | 状态与版本的落点:判定输入的来源,版本序的载体 | status / cash_balance / credit_limit / overdue_since / grace_until / grace_granted_at / state_version / created_at |
| customer_grants | 赠金剩余参与可用额度;授权行变更抬高客户版本 | customer_id / amount / expires_at / status |
| customer_transactions | 扣费类流水的写入抬高客户版本;赠金已用量聚合 | customer_id / type / amount / grant_id / created_at |
状态存储中的状态键与变更事件通道不是关系库表,故不入本表清单,其键名与载荷见 4.2 与 4.3。
STATE_KEY_PREFIX:{customer_id}:state——STATE_KEY_PREFIX 是部署内共享的客户状态命名空间常量,取值为两段(平台共享前缀 + 固定客户段 cust);中段为客户标识,尾段为固定后缀 state。变更事件通道常量 STATE_CHANNEL 同属该命名空间(尾段 state-changed)。两者均不得按环境改写,否则消费方读到的是另一片命名空间。customer_id、state、blocked、block_reason、grace_until、available、cash_balance、evaluated_at、state_version;金额一律元字符串、6 位小数。grace_until 仅当派生态为 grace 时非空,其余态一律为空——消费方据此把「窗内服务」写成一次时钟比较。state_version 由客户表上的触发器在行锁内取全局序列(customer_state_version_seq)赋值,应用层只读不写;行锁把同客户的并发写串行化,后取到锁的事务必然取到更大序列值,故版本序 = 提交序。state_key_ttl_seconds(默认 600 秒),封锁态用长存活期 state_blocked_key_ttl_seconds(默认 7200 秒);后者不得低于一个加固周期 state_sweep_interval_seconds(默认 300 秒)。active / banned / closed 三值;closed 为终态,无退出路径。available > 0 即在营态;不大于 0 才进入宽限判断。overdue_grace_days 默认 0)grace 态不出现,等价于额度耗尽即停服。available > 0,单笔费用可完全透支。state_publish_sync_timeout_seconds(默认 2 秒)给出:状态存储挂起不得无限拖住响应,超时即放弃同步写、退回兜底链路。grace_regrant_cooldown_days(默认 30 天,防「最小充值循环刷宽限」)。/internal,计量链令牌)| 方法 | 路径 | 语义 |
|---|---|---|
| GET | /internal/customers/{customer_id}/state |
派生态唯一出口:返回 state / blocked / block_reason / grace_until / available / cash_balance,并附经营状态与两个旧字段 allowed 与 reason(封锁位取反,原因取 customer_disabled 或 insufficient_available) |
grace_until;载荷与写键同源,不存在第二处判定。| 方法 | 路径 | 语义 |
|---|---|---|
| POST | /internal/customers/{customer_id}/deduct-batch |
批量扣费,提交后异步发布(详见 D04) |
| POST | /internal/customers/{customer_id}/deduct |
单笔扣费兼容入口,同上(详见 D04) |
| POST | /internal/customers/{customer_id}/credit |
赠金入账,解封路径同步写键(详见 D04) |
| PATCH | /internal/customers/{customer_id}/status |
状态标记,同步写键(详见 D04) |
| PATCH | /api/account/ops/customers/{customer_id}/status |
运营面状态标记,同步写键(索引见 D11) |
| PATCH | /api/account/ops/customers/{customer_id}/credit-limit |
信用额度配置,抬高额度可解封,同步写键(详见 D04) |
| POST | /api/account/ops/customers/{customer_id}/adjustment |
运营调整含坏账核销,同步写键(详见 D04) |
| PUT | /api/account/ops/customers/{customer_id}/grace |
宽限设置,同步写键(详见 D04) |
closed / banned 直判封锁,closed 为终态;账务态只在经营状态为在营时参与。| # | 验收口径 |
|---|---|
| 1 | 经营状态为封禁或注销时,无论可用额度多高,派生态均为对应封锁态且封锁原因为状态 |
| 2 | 可用额度恰为 0 且宽限关闭时判定为欠费态、原因为额度;最小正数时为在营态 |
| 3 | 宽限窗内为宽限态、封锁位假、截止非空;窗走完后同一客户转为欠费态 |
| 4 | 两笔并发扣费后键内 available 与最后提交那笔一致,不存在旧快照覆盖新值 |
| 5 | 伪造比键内版本更小的发布:键与事件通道均无变化 |
| 6 | 与键内版本相等的重复发布:键被重写(续期)且不报错 |
| 7 | 键内无版本字段的存量键:任何新版本都能覆盖 |
| 8 | 键内被外部写入非合法内容:发布照常覆盖并产生安全告警 |
| 9 | 扣费仅命中赠金、现金差额为 0 时客户版本仍被抬高(语句级生效) |
| 10 | 入账与赠金撞唯一约束时收敛为幂等,不因版本写入变成序列化错误,不返回 5xx |
| 11 | 充值解封后同一请求返回时封锁位已为假;同步写键失败后键至多存活一个长存活期即回落放行 |
| 12 | 长存活期低于一个加固周期时被验收拒绝(封锁人群会在加固间隙失效) |
| 13 | 跑满一个轮转周期后全库每个客户的键都被刷新过至少一次;到表尾后不出现头段重复刷新而中段被跳过 |
| 14 | 新注册且无赠金的账号:创建后立即读键为欠费态,无被放行一次消费的窗口 |
| 15 | 宽限窗内客户在加固轮转中被按当下时钟重新求值:未到期续宽限、已到期固化为欠费态 |
| 16 | 赠金自然过期(无任何钱包事务)后,一个加固周期内键内 available 与派生态被重新导出 |
| 17 | 状态存储连接配置为空时,扣费与充值接口行为不变(发布为幂等空操作),无异常抛出 |
| 18 | 状态查询端点与状态键读出的 state / blocked / available 完全一致(同源判定) |
| 19 | 消费方仅凭封锁位、宽限截止与键存在性即可完成判定,忽略版本字段不影响结果 |