feat: 实现资产实名认证策略功能 (asset-realname-policy)
All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 6m44s

- 新增 realname_policy 字段到 tb_iot_card、tb_device、tb_iot_card_import_task、tb_device_import_task 四张表
- 策略枚举:none(无需实名)、before_order(先实名后充值/购买)、after_order(先充值/购买后实名)
- C端充值拦截:before_order 策略下未实名用户禁止充值
- C端订单拦截:before_order 策略下未实名用户禁止购买套餐
- C端实名链接拦截:after_order 策略下无充值/订单用户禁止实名认证
- Admin API:PATCH /api/admin/assets/:identifier/realname-mode
- 新增错误码 CodeRealnameNotAvailable=1189
This commit is contained in:
2026-04-17 17:03:41 +08:00
parent e0a37f4a11
commit 505b30aa8f
12 changed files with 623 additions and 0 deletions

View File

@@ -0,0 +1,48 @@
## Why
现有系统对实名认证的要求硬编码在卡业务类型(`card_category`)上,且当前拦截逻辑已被注释(`REALNAME-03`),由网关侧临时托管。业务侧实际存在两种截然不同的场景:**先实名后充值/购买**(实名是充值的前置条件)与**先充值/购买后实名**(充值不受限,实名在事后完成),且行业卡在特定业务下也需要实名。需要在资产(卡和设备)层面引入可配置的实名策略字段,彻底替代原有的硬编码逻辑,支持灵活的运营策略配置。
## What Changes
- **新增 `realname_policy` 字段**`IotCard``Device` 模型),枚举值:
- `none`:无需实名
- `before_order`:先实名后充值/购买(充值/购买前拦截未实名资产)
- `after_order`:先充值/购买后实名(充值/购买放行,实名链接在有订单前拦截)
- **生效优先级**:卡绑定设备时(设备卡)使用 `Device.realname_policy`,单卡使用 `IotCard.realname_policy`
- **C 端拦截**充值C3/C4、购买套餐/订单D1/D4按策略决定是否拦截实名链接E1`after_order` 模式下要求先有充值/订单记录才能获取链接
- **IoT 卡导入** 支持在导入时批量设置 `realname_policy`,并写入每张卡
- **设备导入** 支持在导入时设置 `realname_policy`,并写入每台设备
- **后台管理** 新增接口 `PATCH /api/admin/assets/:identifier/realname-mode` 支持逐资产修改策略
- **所有涉及卡/设备/资产的查询接口**(后台管理端 + C 端)返回 `realname_policy` 字段,便于前端展示和逻辑判断
- **废弃** `REALNAME-03` 注释代码,由新的策略逻辑替代
## Capabilities
### New Capabilities
- `asset-realname-policy`:资产实名认证策略——定义策略枚举、生效规则(单卡 vs 设备卡优先级、C 端三接口拦截逻辑、后台管理更新接口、以及所有查询接口返回该字段的规范
### Modified Capabilities
- `iot-card-import-task`IoT 卡导入请求新增 `realname_policy` 参数,导入任务模型记录该字段,批量初始化卡的策略值
- `device-import`:设备导入请求新增 `realname_policy` 参数,导入任务模型记录该字段,批量初始化设备的策略值
- `client-realname-link`E1 接口在 `after_order` 模式下新增"是否有有效充值/订单"的前置检查;`none` 模式正常返回链接
- `client-order-purchase`D1/D4 接口启用实名策略拦截(替代 REALNAME-03 注释逻辑),`before_order` + 未实名 → 返回 `CodeNeedRealname`
- `client-wallet-recharge`C3/C4 接口新增实名策略拦截,`before_order` + 未实名 → 返回 `CodeNeedRealname`
## Impact
**数据库**`tb_iot_card``tb_device``tb_iot_card_import_task``tb_device_import_task` 各新增 `realname_policy` 字段,迁移默认值 `none`(存量数据不影响现有行为)
**Model 层**`internal/model/iot_card.go``internal/model/device.go``internal/model/iot_card_import_task.go``internal/model/device_import_task.go`
**DTO 层**(新增 `realname_policy` 字段):
- 后台管理:`StandaloneIotCardResponse``DeviceResponse``AssetResolveResponse``AssetRealtimeStatusResponse``DeviceCardBindingResponse``BoundCardInfo``ImportTaskResponse`iot`DeviceImportTaskResponse`
- C 端:`AssetInfoResponse``BoundCardInfo`C端`DeviceCardItem`
- 导入请求:`ImportIotCardRequest``ImportDeviceRequest`
**Service 层**`client_order``client_wallet``client_realname` 新增策略检查逻辑;`iot_card``device` 新增 `UpdateRealnamePolicy` 方法;`iot_card_import``device_import` 传播策略字段至各资产记录
**常量**`pkg/constants/iot.go`(或新文件)新增 `RealnamePolicy*` 枚举常量
**路由 + 文档生成器**:新增 1 个后台管理接口,需同步更新 `cmd/api/docs.go``cmd/gendocs/main.go`