68 lines
3.9 KiB
Markdown
68 lines
3.9 KiB
Markdown
## Context
|
||
|
||
现有代理开放接口(`internal/service/agent_open_api/service.go`)已实现卡维度的流量查询、状态查询、实名查询和钱包购买。设备维度的 Gateway 操作(切网、重启、恢复出厂)已在 `internal/service/device/gateway_service.go` 中实现,设备级套餐流量查询通过 `PackageUsageStore.ListByCarrier(ctx, "device", deviceID, ...)` 支持。
|
||
|
||
本次变更在现有 `agent_open_api` service 中扩展设备维度能力,复用已有的 device service 和 package usage store,不引入新的数据模型或迁移。
|
||
|
||
## Goals / Non-Goals
|
||
|
||
**Goals:**
|
||
- 新增 4 个代理开放接口:设备流量查询、切网、重启、恢复出厂
|
||
- 复用现有 device service 的 Gateway 调用逻辑,不重复实现
|
||
- 权限校验与卡接口保持一致(`shop_id IN SubordinateShopIDs`)
|
||
- 设备标识符支持虚拟号和 IMEI
|
||
|
||
**Non-Goals:**
|
||
- 不新增数据库表或迁移
|
||
- 不修改现有卡接口
|
||
- 不支持 SN 作为设备标识符(开放接口只暴露虚拟号/IMEI)
|
||
- 不支持批量设备操作
|
||
|
||
## Decisions
|
||
|
||
### 决策一:agent_open_api service 注入 device.Service 依赖
|
||
|
||
**选择**:在 `agent_open_api.Service` 结构体中新增 `deviceService *device.Service` 字段,通过构造函数注入。
|
||
|
||
**理由**:device service 已封装了 Gateway 调用、审计日志和设备查询逻辑,直接复用避免重复实现。相比新建独立函数,注入 service 更符合项目分层规范。
|
||
|
||
**替代方案**:在 agent_open_api service 中直接注入 deviceStore 和 gatewayClient,自行实现权限校验和 Gateway 调用。缺点是重复了 device service 中已有的审计日志和错误处理逻辑。
|
||
|
||
### 决策二:设备权限校验方式
|
||
|
||
**选择**:查询设备后,手动检查 `device.ShopID != nil && SubordinateShopIDs 包含 *device.ShopID`。
|
||
|
||
**理由**:`ApplyShopFilter` 作用于 GORM query,而 device service 的 `GetByIdentifier` 内部已有自己的查询逻辑。为避免侵入 device service,在 agent_open_api service 层做显式权限校验,与卡接口的 `resolveOpenAPICard` 模式一致。
|
||
|
||
**实现**:新增 `resolveOpenAPIDevice(ctx, deviceNo)` 私有方法,复用 `device.Service.GetDeviceByIdentifier`,然后校验 shop_id。
|
||
|
||
### 决策三:设备流量查询复用 PackageUsageStore
|
||
|
||
**选择**:直接在 `agent_open_api.Service` 中调用已注入的 `packageUsageStore.ListByCarrier(ctx, "device", device.ID, &status)`。
|
||
|
||
**理由**:`packageUsageStore` 已在 agent_open_api service 中注入(用于卡流量查询),`ListByCarrier` 支持 `"device"` 类型,无需额外改动 store 层。
|
||
|
||
### 决策四:切网接口调用 device.Service.GatewaySwitchCard
|
||
|
||
**选择**:agent_open_api service 调用 `deviceService.GatewaySwitchCard(ctx, identifier, &dto.SwitchCardRequest{ICCID: req.ICCID})`。
|
||
|
||
**理由**:`GatewaySwitchCard` 已包含审计日志记录,开放接口复用可保证操作可追溯。
|
||
|
||
**注意**:`GatewaySwitchCard` 内部通过 `getGatewayDevice` 再次查询设备,存在两次查询。考虑到操作频率低,接受此开销,不做优化。
|
||
|
||
## Risks / Trade-offs
|
||
|
||
- **[风险] device service 审计日志中的操作者信息**:`GatewaySwitchCard` 等方法通过 `middleware.GetUserIDFromContext` 获取操作者 ID。开放接口认证中间件已将代理账号 ID 写入 `ContextKeyUserID`,审计日志可正确记录操作者。→ 无需额外处理。
|
||
|
||
- **[风险] 设备标识符两次查询**:`resolveOpenAPIDevice` 查一次,`GatewaySwitchCard` 内部再查一次。→ 接受,操作类接口频率低,影响可忽略。
|
||
|
||
- **[Trade-off] 不支持 SN**:admin 接口支持虚拟号/IMEI/SN,开放接口只支持虚拟号/IMEI。→ 简化外部接口,SN 是内部管理标识,不适合对外暴露。
|
||
|
||
## Migration Plan
|
||
|
||
无数据库变更,无需迁移。直接部署新版本即可。
|
||
|
||
## Open Questions
|
||
|
||
(无)
|