支撑单卡
All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 8m16s

This commit is contained in:
Break
2026-06-04 14:29:20 +08:00
parent cce27975a1
commit 6ac19d6565
3 changed files with 40 additions and 11 deletions

View File

@@ -38,7 +38,8 @@ type AgentOpenAPIPackageTrafficItem struct {
// AgentOpenAPICardTrafficResponse 开放接口卡流量响应
type AgentOpenAPICardTrafficResponse struct {
CardNo string `json:"card_no" description:"卡标识"`
CardNo string `json:"card_no" description:"卡标识(原始传入值)"`
DeviceNo string `json:"device_no,omitempty" description:"设备虚拟号(当入参被识别为设备维度时返回,表示该卡/标识关联的设备)"`
ActiveRemainingFlowMB int64 `json:"active_remaining_flow_mb" description:"当前生效套餐剩余流量(MB)"`
ActiveTotalFlowMB int64 `json:"active_total_flow_mb" description:"当前生效套餐总流量(MB)"`
ActiveUsedFlowMB int64 `json:"active_used_flow_mb" description:"当前生效套餐已用流量(MB)"`

View File

@@ -74,8 +74,8 @@ function buildAgentSign({ method, path, query, body, timestamp, nonce, account,
` + "```"
Register(router, doc, basePath, "GET", "/cards/traffic", handler.GetCardTraffic, RouteSpec{
Summary: "查询单卡流量",
Description: authDescription + "\n\n按 card_no 查询单卡流量、当前套餐和待生效套餐。card_no 支持 ICCID虚拟号MSISDN。",
Summary: "查询单卡或设备流量",
Description: authDescription + "\n\n按 card_no 查询流量、当前套餐和待生效套餐。card_no 支持三种解析路径1) ICCID/虚拟号/MSISDN 对应独立卡查卡维度流量2) 已绑定设备的卡,自动反查绑定设备,查设备维度流量(响应含 device_no3) IMEI 或设备虚拟号,直接查设备维度流量(响应含 device_no。",
Input: new(dto.AgentOpenAPICardQueryRequest),
Output: new(dto.AgentOpenAPICardTrafficResponse),
Tags: []string{tag},

View File

@@ -72,20 +72,48 @@ func New(
}
}
// GetCardTraffic 查询开放接口单卡流量
// GetCardTraffic 查询开放接口流量
// 支持三种解析路径:
// 1. card_no 解析为独立卡 → 查卡维度流量
// 2. card_no 解析为已绑定设备的卡 → 反查绑定设备 → 查设备维度流量
// 3. card_no 无法解析为卡 → 尝试作为设备标识IMEI/虚拟号)→ 查设备维度流量
func (s *Service) GetCardTraffic(ctx context.Context, req *dto.AgentOpenAPICardQueryRequest) (*dto.AgentOpenAPICardTrafficResponse, error) {
card, err := s.resolveOpenAPICard(ctx, req.CardNo)
if err != nil {
return nil, err
card, cardErr := s.resolveOpenAPICard(ctx, req.CardNo)
if cardErr == nil {
// 独立卡:直接查卡维度流量
if card.IsStandalone {
return s.buildCardTrafficResponse(ctx, req.CardNo, "iot_card", card.ID, "")
}
// 已绑定设备的卡:反查设备后查设备维度流量
binding, err := s.deviceSimBindingStore.GetActiveBindingByCardID(ctx, card.ID)
if err != nil {
return nil, errors.Wrap(errors.CodeInternalError, err, "查询卡绑定设备失败")
}
device, err := s.deviceStore.GetByID(ctx, binding.DeviceID)
if err != nil {
return nil, errors.Wrap(errors.CodeInternalError, err, "查询绑定设备信息失败")
}
return s.buildCardTrafficResponse(ctx, req.CardNo, "device", device.ID, device.VirtualNo)
}
// 兜底:尝试解析为设备标识(支持 IMEI/虚拟号)
device, err := s.resolveOpenAPIDevice(ctx, req.CardNo)
if err != nil {
// 两种解析都失败,返回原始卡解析错误(语义更贴近入参)
return nil, cardErr
}
return s.buildCardTrafficResponse(ctx, req.CardNo, "device", device.ID, device.VirtualNo)
}
// buildCardTrafficResponse 统一构造卡流量响应,支持卡和设备两种载体维度
func (s *Service) buildCardTrafficResponse(ctx context.Context, cardNo, carrierType string, carrierID uint, deviceNo string) (*dto.AgentOpenAPICardTrafficResponse, error) {
activeStatus := constants.PackageUsageStatusActive
pendingStatus := constants.PackageUsageStatusPending
activeUsages, err := s.packageUsageStore.ListByCarrier(ctx, "iot_card", card.ID, &activeStatus)
activeUsages, err := s.packageUsageStore.ListByCarrier(ctx, carrierType, carrierID, &activeStatus)
if err != nil {
return nil, errors.Wrap(errors.CodeInternalError, err, "查询生效套餐失败")
}
pendingUsages, err := s.packageUsageStore.ListByCarrier(ctx, "iot_card", card.ID, &pendingStatus)
pendingUsages, err := s.packageUsageStore.ListByCarrier(ctx, carrierType, carrierID, &pendingStatus)
if err != nil {
return nil, errors.Wrap(errors.CodeInternalError, err, "查询待生效套餐失败")
}
@@ -96,7 +124,8 @@ func (s *Service) GetCardTraffic(ctx context.Context, req *dto.AgentOpenAPICardQ
}
resp := &dto.AgentOpenAPICardTrafficResponse{
CardNo: req.CardNo,
CardNo: cardNo,
DeviceNo: deviceNo,
ActivePackages: make([]dto.AgentOpenAPIPackageTrafficItem, 0, len(activeUsages)),
PendingPackages: make([]dto.AgentOpenAPIPackageTrafficItem, 0, len(pendingUsages)),
}
@@ -113,7 +142,6 @@ func (s *Service) GetCardTraffic(ctx context.Context, req *dto.AgentOpenAPICardQ
for _, usage := range pendingUsages {
resp.PendingPackages = append(resp.PendingPackages, s.buildTrafficItem(usage, packageMap, seriesMap, false))
}
return resp, nil
}