All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 9m33s
- 新增网关限流:按本系统运营商账户(卡 carrier_id)→ 限流组 → 操作限制每秒请求数,每次 HTTP 尝试计量,默认限流、仅后台人工点击/通道阈值/自动续费/手动刷新豁免;支持只统计与拦截两种模式,默认只统计 - Asynq 遇限流不计失败、固定短延迟重试;轮询任务与停复机业务重试遇限流短延迟重排 - 停机、复机不再使用网关内部重试,只发一次请求 - 网关返回结构化错误;新增上游错误分类规则表与测试接口 - 新增按月分区的停复机记录表:系统自动停复机只写记录,不再写统一审计与集成日志;普通轮询查询不再写集成日志 - 新增限流组、错误分类、停复机记录、按账户调用统计与枚举后台接口 - 迁移 000243~000246;同步 OpenSpec 提案(含后续 6 个 change)与技术方案、工程约束
98 lines
3.5 KiB
Go
98 lines
3.5 KiB
Go
// Package gateway 提供流量卡相关的 7 个 API 方法封装
|
|
package gateway
|
|
|
|
import (
|
|
"context"
|
|
|
|
"github.com/break/junhong_cmp_fiber/pkg/constants"
|
|
"github.com/break/junhong_cmp_fiber/pkg/errors"
|
|
)
|
|
|
|
// QueryCardStatus 查询流量卡状态
|
|
// POST /flow-card/status
|
|
func (c *Client) QueryCardStatus(ctx context.Context, req *CardStatusReq) (*CardStatusResp, error) {
|
|
ctx = withCardCall(ctx, constants.GatewayOpQueryStatus, cardNoOf(req))
|
|
return doRequestWithResponse[CardStatusResp](c, ctx, "/flow-card/status", req)
|
|
}
|
|
|
|
// QueryFlow 查询流量使用情况
|
|
// POST /flow-card/flow
|
|
func (c *Client) QueryFlow(ctx context.Context, req *FlowQueryReq) (*FlowUsageResp, error) {
|
|
ctx = withCardCall(ctx, constants.GatewayOpQueryFlow, flowCardNoOf(req))
|
|
return doRequestWithResponse[FlowUsageResp](c, ctx, "/flow-card/flow", req)
|
|
}
|
|
|
|
// QueryRealnameStatus 查询实名认证状态
|
|
// POST /flow-card/realName
|
|
func (c *Client) QueryRealnameStatus(ctx context.Context, req *CardStatusReq) (*RealnameStatusResp, error) {
|
|
ctx = withCardCall(ctx, constants.GatewayOpQueryRealname, cardNoOf(req))
|
|
return doRequestWithResponse[RealnameStatusResp](c, ctx, "/flow-card/realName", req)
|
|
}
|
|
|
|
// StopCard 流量卡停机
|
|
// POST /flow-card/cardStop
|
|
// 停机是外部状态写入:超时或连接失败时上游可能已受理,内部重试会对同一张卡连发并撞上游单卡频率限制,故只发一次请求。
|
|
func (c *Client) StopCard(ctx context.Context, req *CardOperationReq) error {
|
|
ctx = withCardCall(ctx, constants.GatewayOpStop, operationCardNoOf(req))
|
|
requestClient := *c
|
|
requestClient.maxRetries = 0
|
|
_, err := requestClient.doRequest(ctx, "/flow-card/cardStop", req)
|
|
return err
|
|
}
|
|
|
|
// StartCard 流量卡复机
|
|
// POST /flow-card/cardStart
|
|
// 复机同停机,只发一次请求,不使用内部重试。
|
|
func (c *Client) StartCard(ctx context.Context, req *CardOperationReq) error {
|
|
ctx = withCardCall(ctx, constants.GatewayOpStart, operationCardNoOf(req))
|
|
requestClient := *c
|
|
requestClient.maxRetries = 0
|
|
_, err := requestClient.doRequest(ctx, "/flow-card/cardStart", req)
|
|
return err
|
|
}
|
|
|
|
func cardNoOf(req *CardStatusReq) string {
|
|
if req == nil {
|
|
return ""
|
|
}
|
|
return req.CardNo
|
|
}
|
|
|
|
func flowCardNoOf(req *FlowQueryReq) string {
|
|
if req == nil {
|
|
return ""
|
|
}
|
|
return req.CardNo
|
|
}
|
|
|
|
func operationCardNoOf(req *CardOperationReq) string {
|
|
if req == nil {
|
|
return ""
|
|
}
|
|
return req.CardNo
|
|
}
|
|
|
|
// GetRealnameLink 获取实名认证跳转链接
|
|
// POST /flow-card/RealNameVerification
|
|
func (c *Client) GetRealnameLink(ctx context.Context, req *CardStatusReq) (*RealnameLinkResp, error) {
|
|
return doRequestWithResponse[RealnameLinkResp](c, ctx, "/flow-card/RealNameVerification", req)
|
|
}
|
|
|
|
// SetCardSpeedTier 设置或恢复流量卡固定限速档位。
|
|
// POST /flow-card/speedLimit
|
|
func (c *Client) SetCardSpeedTier(ctx context.Context, req *CardSpeedTierReq) error {
|
|
if req == nil || req.CardNo == "" || req.Code == "" {
|
|
return errors.New(errors.CodeInvalidParam, "流量卡号和限速档位不能为空")
|
|
}
|
|
// 限速是外部状态写入,网络错误或超时后实际结果不可确定,禁止沿用查询接口的自动重试。
|
|
requestClient := *c
|
|
requestClient.maxRetries = 0
|
|
_, err := requestClient.doRequest(ctx, "/flow-card/speedLimit", req)
|
|
return err
|
|
}
|
|
|
|
// BatchQuery 批量查询(预留接口,暂未实现)
|
|
func (c *Client) BatchQuery(ctx context.Context, req *BatchQueryReq) (*BatchQueryResp, error) {
|
|
return nil, errors.New(errors.CodeGatewayError, "批量查询接口暂未实现")
|
|
}
|