设备的部分改造
All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 7m34s

This commit is contained in:
2026-03-10 10:34:08 +08:00
parent 86f8d0b644
commit b5147d1acb
34 changed files with 1680 additions and 485 deletions

View File

@@ -14,12 +14,15 @@ Gateway API 统一客户端,提供 14 个接口的类型安全封装。
- `appSecret string` - 应用密钥
- `httpClient *http.Client` - HTTP 客户端(支持连接复用)
- `timeout time.Duration` - 请求超时时间
- `logger *zap.Logger` - 日志记录器
- `maxRetries int` - 最大重试次数
#### Scenario: 创建 Gateway 客户端
- **WHEN** 调用 `gateway.NewClient(baseURL, appID, appSecret)`
- **WHEN** 调用 `gateway.NewClient(baseURL, appID, appSecret, logger)`
- **THEN** 返回已初始化的 `Client` 实例
- **AND** HTTP 客户端配置正确(支持 Keep-Alive
- **AND** 默认最大重试次数为 2
#### Scenario: 配置超时时间
@@ -29,15 +32,21 @@ Gateway API 统一客户端,提供 14 个接口的类型安全封装。
### Requirement: 统一请求方法
系统 SHALL 提供 `doRequest` 方法统一处理加密、签名、HTTP 请求和响应解析。
系统 SHALL 提供 `doRequest` 方法统一处理加密、签名、HTTP 请求和响应解析。请求参数 SHALL 直接接收结构体,内部自动序列化并包装为 `{"params": <JSON>}` 格式。
#### Scenario: 请求参数自动序列化
- **WHEN** 调用 `doRequest(ctx, "/device/speed-limit", &SpeedLimitReq{CardNo: "xxx", SpeedLimit: 1024})`
- **THEN** 请求结构体自动通过 `sonic.Marshal` 序列化
- **AND** 序列化结果嵌入 `{"params": <序列化JSON>}` 中进行加密和签名
#### Scenario: 成功的 API 调用
- **WHEN** 调用 `doRequest(ctx, "/flow-card/status", businessData)`
- **WHEN** 调用 `doRequest(ctx, "/flow-card/status", req)`
- **THEN** 业务数据使用 AES-128-ECB 加密
- **AND** 请求使用 MD5 签名
- **AND** HTTP POST 发送到 `{baseURL}/flow-card/status`
- **AND** 响应中的 `data` 字段解密并返回
- **AND** 响应中的 `data` 字段返回`json.RawMessage`
#### Scenario: 网络错误
@@ -55,7 +64,7 @@ Gateway API 统一客户端,提供 14 个接口的类型安全封装。
- **WHEN** Gateway 响应无法解析为 JSON
- **THEN** 返回 `CodeGatewayInvalidResp` 错误
- **AND** 错误信息包含原始响应内容(限制 200 字符)
- **AND** 错误信息包含原始响应内容
#### Scenario: Gateway 业务错误
@@ -63,6 +72,37 @@ Gateway API 统一客户端,提供 14 个接口的类型安全封装。
- **THEN** 返回 `CodeGatewayError` 错误
- **AND** 错误信息包含 Gateway 的 code 和 msg
### Requirement: 泛型响应解析方法
系统 SHALL 提供 `doRequestWithResponse[T any]` 泛型方法,自动完成请求发送和响应反序列化。
#### Scenario: 自动反序列化响应
- **WHEN** 调用 `doRequestWithResponse[CardStatusResp](ctx, "/flow-card/status", req)`
- **THEN** 返回 `*CardStatusResp` 类型的结构体
- **AND** 内部调用 `doRequest` 获取 `json.RawMessage` 后自动 unmarshal
#### Scenario: 反序列化失败
- **WHEN** Gateway 返回的 JSON 无法匹配目标结构体
- **THEN** 返回 `CodeGatewayInvalidResp` 错误
- **AND** 错误信息为 "解析 Gateway 响应失败"
### Requirement: 请求结构体直接序列化
系统 SHALL 消除手动 `map[string]interface{}` 构建,所有业务方法直接将请求结构体传递给 `doRequest``doRequestWithResponse`
#### Scenario: 设备限速请求
- **WHEN** 调用 `SetSpeedLimit(ctx, &SpeedLimitReq{CardNo: "xxx", SpeedLimit: 1024})`
- **THEN** `SpeedLimitReq` 结构体直接序列化为 JSON
- **AND** 不再手动构建 `map[string]interface{}`
#### Scenario: 流量卡停机请求
- **WHEN** 调用 `StopCard(ctx, &CardOperationReq{CardNo: "xxx", Extend: "ext"})`
- **THEN** `CardOperationReq` 结构体直接序列化
- **AND** `Extend` 字段通过 `json:"extend,omitempty"` 标签在为空时自动省略
### Requirement: 流量卡 API 封装
系统 SHALL 提供 7 个流量卡相关的 API 方法。