Compare commits

..

2 Commits

Author SHA1 Message Date
86f8d0b644 fix: 适配 Gateway 响应模型变更,更新轮询处理器和 Mock 服务
All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 7m25s
- polling_handler: Status→RealStatus, UsedFlow→Used, parseRealnameStatus 参数改为 bool
- mock_gateway: 同步接口路径和响应结构与上游文档一致
2026-03-07 11:29:40 +08:00
a83dca2eb2 fix: 修复 Gateway 流量卡接口路径、响应模型和时间戳与上游文档不一致
- 时间戳从 UnixMilli (13位) 改为 Unix (10位秒级)
- 实名状态接口路径 /realname-status → /realName
- 实名链接接口路径 /realname-link → /RealNameVerification
- RealnameStatusResp: status string → realStatus bool + iccid
- FlowUsageResp: usedFlow int64 → used float64 + iccid
- RealnameLinkResp: link → url
2026-03-07 11:29:34 +08:00
5 changed files with 23 additions and 28 deletions

View File

@@ -72,7 +72,7 @@ func (c *Client) doRequest(ctx context.Context, path string, businessData interf
return nil, err return nil, err
} }
timestamp := time.Now().UnixMilli() timestamp := time.Now().Unix()
sign := generateSign(c.appID, encryptedData, timestamp, c.appSecret) sign := generateSign(c.appID, encryptedData, timestamp, c.appSecret)
reqBody := map[string]interface{}{ reqBody := map[string]interface{}{

View File

@@ -58,7 +58,7 @@ func (c *Client) QueryRealnameStatus(ctx context.Context, req *CardStatusReq) (*
}, },
} }
resp, err := c.doRequest(ctx, "/flow-card/realname-status", businessData) resp, err := c.doRequest(ctx, "/flow-card/realName", businessData)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -109,7 +109,7 @@ func (c *Client) GetRealnameLink(ctx context.Context, req *CardStatusReq) (*Real
}, },
} }
resp, err := c.doRequest(ctx, "/flow-card/realname-link", businessData) resp, err := c.doRequest(ctx, "/flow-card/RealNameVerification", businessData)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@@ -32,9 +32,9 @@ type FlowQueryReq struct {
// FlowUsageResp 是查询流量使用的响应 // FlowUsageResp 是查询流量使用的响应
type FlowUsageResp struct { type FlowUsageResp struct {
UsedFlow int64 `json:"usedFlow" description:"已用流量"` ICCID string `json:"iccid" description:"ICCID"`
Used float64 `json:"used" description:"当月已用流量MB"`
Unit string `json:"unit" description:"流量单位MB"` Unit string `json:"unit" description:"流量单位MB"`
Extend string `json:"extend,omitempty" description:"扩展字段(广电国网特殊参数)"`
} }
// CardOperationReq 是停机/复机请求 // CardOperationReq 是停机/复机请求
@@ -45,14 +45,13 @@ type CardOperationReq struct {
// RealnameStatusResp 是实名认证状态的响应 // RealnameStatusResp 是实名认证状态的响应
type RealnameStatusResp struct { type RealnameStatusResp struct {
Status string `json:"status" description:"实名认证状态"` ICCID string `json:"iccid" description:"ICCID"`
Extend string `json:"extend,omitempty" description:"扩展字段(广电国网特殊参数"` RealStatus bool `json:"realStatus" description:"实名状态true=已实名, false=未实名"`
} }
// RealnameLinkResp 是实名认证链接的响应 // RealnameLinkResp 是实名认证链接的响应
type RealnameLinkResp struct { type RealnameLinkResp struct {
Link string `json:"link" description:"实名认证跳转链接HTTPS URL"` URL string `json:"url" description:"实名认证跳转链接HTTPS URL"`
Extend string `json:"extend,omitempty" description:"扩展字段(广电国网特殊参数)"`
} }
// BatchQueryReq 是批量查询的请求 // BatchQueryReq 是批量查询的请求

View File

@@ -123,11 +123,11 @@ func (h *PollingHandler) HandleRealnameCheck(ctx context.Context, t *asynq.Task)
} }
// 解析实名状态 // 解析实名状态
newRealnameStatus = h.parseRealnameStatus(result.Status) newRealnameStatus = h.parseRealnameStatus(result.RealStatus)
h.logger.Info("实名检查完成", h.logger.Info("实名检查完成",
zap.Uint64("card_id", cardID), zap.Uint64("card_id", cardID),
zap.String("iccid", card.ICCID), zap.String("iccid", card.ICCID),
zap.String("gateway_status", result.Status), zap.Bool("gateway_real_status", result.RealStatus),
zap.Int("new_status", newRealnameStatus), zap.Int("new_status", newRealnameStatus),
zap.Int("old_status", card.RealNameStatus)) zap.Int("old_status", card.RealNameStatus))
} else { } else {
@@ -236,7 +236,7 @@ func (h *PollingHandler) HandleCarddataCheck(ctx context.Context, t *asynq.Task)
} }
// Gateway 返回的是 MB 单位的流量 // Gateway 返回的是 MB 单位的流量
gatewayFlowMB = float64(result.UsedFlow) gatewayFlowMB = result.Used
h.logger.Info("流量检查完成", h.logger.Info("流量检查完成",
zap.Uint64("card_id", cardID), zap.Uint64("card_id", cardID),
zap.String("iccid", card.ICCID), zap.String("iccid", card.ICCID),
@@ -692,15 +692,12 @@ func (h *PollingHandler) stopCards(ctx context.Context, cards []*model.IotCard,
} }
// parseRealnameStatus 解析实名状态 // parseRealnameStatus 解析实名状态
func (h *PollingHandler) parseRealnameStatus(gatewayStatus string) int { // Gateway 返回 bool 类型true=已实名, false=未实名
switch gatewayStatus { func (h *PollingHandler) parseRealnameStatus(realStatus bool) int {
case "已实名", "realname", "1": if realStatus {
return 2 // 已实名 return 2 // 已实名
case "实名中", "processing":
return 1 // 实名中
default:
return 0 // 未实名
} }
return 0 // 未实名
} }
// extractTaskType 从完整的任务类型中提取简短的类型名 // extractTaskType 从完整的任务类型中提取简短的类型名

View File

@@ -45,7 +45,7 @@ func main() {
} }
// 实名查询接口(匹配 gateway client 的路径) // 实名查询接口(匹配 gateway client 的路径)
http.HandleFunc("/flow-card/realname-status", handleRealnameQuery) http.HandleFunc("/flow-card/realName", handleRealnameQuery)
// 流量查询接口 // 流量查询接口
http.HandleFunc("/flow-card/flow", handleFlowQuery) http.HandleFunc("/flow-card/flow", handleFlowQuery)
@@ -67,7 +67,7 @@ func main() {
fmt.Println("模拟响应时间: 200ms - 4s") fmt.Println("模拟响应时间: 200ms - 4s")
fmt.Println("") fmt.Println("")
fmt.Println("接口列表:") fmt.Println("接口列表:")
fmt.Println(" POST /flow-card/realname-status - 实名查询") fmt.Println(" POST /flow-card/realName - 实名查询")
fmt.Println(" POST /flow-card/flow - 流量查询") fmt.Println(" POST /flow-card/flow - 流量查询")
fmt.Println(" POST /flow-card/status - 卡状态查询") fmt.Println(" POST /flow-card/status - 卡状态查询")
fmt.Println(" POST /flow-card/cardStop - 停机操作") fmt.Println(" POST /flow-card/cardStop - 停机操作")
@@ -112,14 +112,13 @@ func handleRealnameQuery(w http.ResponseWriter, r *http.Request) {
// 90% 成功10% 失败 // 90% 成功10% 失败
if rand.Float64() < 0.90 { if rand.Float64() < 0.90 {
atomic.AddInt64(&successRequests, 1) atomic.AddInt64(&successRequests, 1)
// 随机返回实名状态 // 随机返回实名状态匹配文档realStatus 为 bool 类型)
statuses := []string{"未实名", "实名中", "已实名"} realStatus := rand.Float64() < 0.5
status := statuses[rand.Intn(3)]
resp := GatewayResponse{ resp := GatewayResponse{
Code: 200, Code: 200,
Msg: "success", Msg: "success",
TraceID: fmt.Sprintf("trace-%d", time.Now().UnixNano()), TraceID: fmt.Sprintf("trace-%d", time.Now().UnixNano()),
Data: json.RawMessage(fmt.Sprintf(`{"status": "%s"}`, status)), Data: json.RawMessage(fmt.Sprintf(`{"iccid": "mock-iccid", "realStatus": %t}`, realStatus)),
} }
json.NewEncoder(w).Encode(resp) json.NewEncoder(w).Encode(resp)
} else { } else {
@@ -140,13 +139,13 @@ func handleFlowQuery(w http.ResponseWriter, r *http.Request) {
if rand.Float64() < 0.90 { if rand.Float64() < 0.90 {
atomic.AddInt64(&successRequests, 1) atomic.AddInt64(&successRequests, 1)
// 随机返回流量数据(匹配 FlowUsageResp 结构 // 随机返回流量数据(匹配文档used 字段
usedFlow := rand.Intn(10000) usedFlow := rand.Intn(10000)
resp := GatewayResponse{ resp := GatewayResponse{
Code: 200, Code: 200,
Msg: "success", Msg: "success",
TraceID: fmt.Sprintf("trace-%d", time.Now().UnixNano()), TraceID: fmt.Sprintf("trace-%d", time.Now().UnixNano()),
Data: json.RawMessage(fmt.Sprintf(`{"usedFlow": %d, "unit": "MB"}`, usedFlow)), Data: json.RawMessage(fmt.Sprintf(`{"iccid": "mock-iccid", "used": %d, "unit": "MB"}`, usedFlow)),
} }
json.NewEncoder(w).Encode(resp) json.NewEncoder(w).Encode(resp)
} else { } else {