Files
2026-06-02 16:56:18 +08:00

68 lines
3.9 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
## 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
(无)