7.9 KiB
Capability: 资产实名策略
ADDED Requirements
Requirement: 资产实名策略字段定义
系统 SHALL 在 IotCard 和 Device 模型上各新增 realname_policy 字段(VARCHAR(20),NOT NULL,DEFAULT 'none'),用于控制该资产的实名认证要求。
枚举值:
none:无需实名,充值/购买/实名链接均不受限before_order:先实名后充值/购买,充值/购买前若未实名则拦截并返回CodeNeedRealnameafter_order:先充值/购买后实名,充值/购买放行;实名链接在无有效充值/订单记录前拦截
常量定义(pkg/constants/iot.go 或 pkg/constants/realname.go):
const (
RealnmePolicyNone = "none" // 无需实名
RealnmePolicyBeforeOrder = "before_order" // 先实名后充值/购买
RealnmePolicyAfterOrder = "after_order" // 先充值/购买后实名
)
Scenario: 默认值为 none
- WHEN 新建 IotCard 或 Device 时未传入 realname_policy
- THEN 系统自动填充
realname_policy = "none"
Scenario: 存量数据迁移后行为不变
- WHEN 数据库迁移执行后,存量 IotCard 和 Device 的 realname_policy 均为 "none"
- THEN 充值、购买、实名链接行为与迁移前完全相同(均放行)
Requirement: 生效策略优先级(设备卡 vs 单卡)
系统 SHALL 按以下规则确定一张卡的生效实名策略:
- 单卡(该卡未绑定任何设备):使用
IotCard.realname_policy - 设备卡(该卡已绑定设备):使用
Device.realname_policy,忽略IotCard.realname_policy
此规则 SHALL 封装为 Service 层公共方法 GetEffectiveRealnamePolicy,所有需要策略判断的场景均调用该方法,不得在多处重复实现。
Scenario: 设备卡使用设备策略
- WHEN IotCard.realname_policy="none" 且该卡绑定了 Device.realname_policy="before_order"
- THEN 生效策略为 "before_order"(设备策略覆盖卡策略)
Scenario: 单卡使用卡策略
- WHEN IotCard.realname_policy="before_order" 且该卡未绑定任何设备
- THEN 生效策略为 "before_order"
Requirement: C 端充值接口实名策略拦截
系统 SHALL 在 C 端充值预检接口(C3 GET /api/c/v1/wallet/recharge-check)和充值下单接口(C4 POST /api/c/v1/wallet/recharge)中,按生效实名策略执行以下逻辑:
before_order+real_name_status=0(未实名):MUST 拦截,返回CodeNeedRealname(错误码 1187)before_order+real_name_status=1(已实名):放行after_order:放行(不检查实名状态)none:放行
Scenario: before_order 模式未实名时充值被拦截
- WHEN 资产 realname_policy="before_order" 且 real_name_status=0,用户调用充值下单接口
- THEN 系统返回错误码 1187(CodeNeedRealname)
Scenario: before_order 模式已实名时充值放行
- WHEN 资产 realname_policy="before_order" 且 real_name_status=1,用户调用充值下单接口
- THEN 系统正常创建充值订单
Scenario: after_order 模式充值放行
- WHEN 资产 realname_policy="after_order" 且 real_name_status=0,用户调用充值下单接口
- THEN 系统正常创建充值订单,不检查实名状态
Requirement: C 端购买套餐/订单接口实名策略拦截
系统 SHALL 在 C 端创建订单接口(D1 POST /api/c/v1/orders/create)和支付接口(D4 POST /api/c/v1/orders/:id/pay)中,按生效实名策略执行与充值相同的拦截规则。D1 中原 REALNAME-03 注释代码 SHALL 被删除,由新策略逻辑替代。
Scenario: before_order 模式未实名时购买套餐被拦截
- WHEN 资产 realname_policy="before_order" 且 real_name_status=0,用户调用创建订单接口
- THEN 系统返回错误码 1187(CodeNeedRealname),订单不创建
Scenario: none 模式购买套餐放行
- WHEN 资产 realname_policy="none",用户调用创建订单接口
- THEN 系统正常创建订单,不检查实名状态
Requirement: C 端实名链接接口策略拦截
系统 SHALL 在 C 端实名链接接口(E1 GET /api/c/v1/realname/link)中,按生效实名策略执行以下逻辑:
none:放行,正常返回实名链接(用户可自愿实名)before_order:放行,正常返回实名链接(引导用户先实名再充值)after_order:检查该资产当前 generation 内是否存在有效充值(status=2)或已支付订单(payment_status=2)- 有记录 → 放行
- 无记录 → 拦截,返回错误码(新错误码
CodeRealnameNotAvailable),消息为"请先完成充值或购买套餐后再进行实名认证"
Scenario: after_order 模式有充值记录时实名链接放行
- WHEN 资产 realname_policy="after_order" 且当前 generation 内存在 status=2 的充值记录
- THEN 系统正常返回实名链接
Scenario: after_order 模式无充值/订单记录时实名链接被拦截
- WHEN 资产 realname_policy="after_order" 且当前 generation 内无任何有效充值或已支付订单
- THEN 系统返回错误,消息为"请先完成充值或购买套餐后再进行实名认证"
Scenario: before_order 模式正常返回实名链接
- WHEN 资产 realname_policy="before_order"
- THEN 系统正常返回实名链接(引导用户完成实名)
Requirement: 后台管理更新资产实名策略接口
系统 SHALL 提供 PATCH /api/admin/assets/:identifier/realname-mode,仅限后台管理端认证用户访问。接口通过 assetService.Resolve() 将标识符(ICCID/虚拟号)解析为具体资产,按 asset_type 分别更新 IotCard.realname_policy 或 Device.realname_policy。
请求体:
{ "realname_policy": "none | before_order | after_order" }
响应体:
{ "asset_type": "card | device", "asset_id": 123, "realname_policy": "before_order" }
Scenario: 通过 ICCID 更新单卡策略
- WHEN 管理员传入 identifier=ICCID,realname_policy="before_order"
- THEN 系统更新对应 IotCard 的 realname_policy 为 "before_order",返回 asset_type="card"
Scenario: 通过设备号更新设备策略
- WHEN 管理员传入 identifier=设备虚拟号,realname_policy="after_order"
- THEN 系统更新对应 Device 的 realname_policy 为 "after_order",返回 asset_type="device"
Scenario: 传入无效枚举值被拒绝
- WHEN 管理员传入 realname_policy="invalid_value"
- THEN 系统返回参数校验错误,提示实名策略值无效
Requirement: 所有查询接口返回 realname_policy 字段
以下所有 DTO SHALL 新增 realname_policy 字段(string)及对应的 description 标签:
后台管理端 DTO:
StandaloneIotCardResponse(IoT 卡详情/列表)DeviceResponse(设备详情/列表)AssetResolveResponse(统一资产解析)AssetRealtimeStatusResponse(资产实时状态)DeviceCardBindingResponse(设备绑卡记录)BoundCardInfo(asset_dto.go 中的通用子结构)ImportTaskResponse(iot 卡导入任务)DeviceImportTaskResponse(设备导入任务)
C 端 DTO:
AssetInfoResponse(B1 资产信息)BoundCardInfo(client_asset_dto.go 中的 C 端子结构)DeviceCardItem(F1 设备卡列表项)
description 标签统一格式:
RealnamePolicy string `json:"realname_policy" description:"实名认证策略 (none:无需实名, before_order:先实名后充值/购买, after_order:先充值/购买后实名)"`
Scenario: 资产详情接口返回 realname_policy
- WHEN 后台管理员查询 IoT 卡详情或资产解析
- THEN 响应中包含 realname_policy 字段
Scenario: C 端资产信息接口返回 realname_policy
- WHEN C 端用户调用 GET /api/c/v1/asset/info
- THEN 响应中包含 realname_policy 字段(前端可据此展示提示)