Files
iotlcm/internal/logic/upstreamimpl/sim_daihe.go
T
2026-10-29 14:59:32 +08:00

266 lines
9.3 KiB
Go

package upstreamimpl
import (
"context"
"encoding/json"
"fmt"
"strings"
"time"
"github.com/gogf/gf/v2/frame/g"
"git.5iot.com/iotlcm-public/iotlcm-upstream-chan/internal/consts"
"git.5iot.com/iotlcm-public/iotlcm-upstream-chan/internal/model"
"git.5iot.com/iotlcm-public/iotlcm-upstream-chan/internal/service"
"git.5iot.com/iotlcm-public/iotlcm-upstream-chan/internal/service/daihe"
)
const daiheTemplateKey = "sim_daihe_v1"
type daiheConfig struct {
AppID string `json:"appId"`
AppSecret string `json:"appSecret"`
BaseURL string `json:"baseUrl"`
Timeout string `json:"timeout"`
API struct {
BaseURL string `json:"baseUrl"`
Timeout string `json:"timeout"`
} `json:"api"`
}
type daiheUsage struct {
ICCID string `json:"iccid"`
Month int `json:"month"`
Used float64 `json:"used"`
}
type daiheStatus struct {
ICCID string `json:"iccid"`
Status string `json:"status"`
}
type sSimDaihe struct {
channelConfig *model.SimChannelConfigItemCache
client *daihe.Client
}
func init() { service.UpstreamAPI().RegisterTemp(daiheTemplateKey, NewSimDaihe()) }
func NewSimDaihe() *sSimDaihe { return &sSimDaihe{} }
func parseDaiheConfig(raw string) daiheConfig {
var cfg daiheConfig
_ = json.Unmarshal([]byte(raw), &cfg)
return cfg
}
func pickDaiheConfig(cfg *model.SimChannelConfigItemCache) (daiheConfig, bool) {
if cfg == nil || cfg.Channel == nil || cfg.Template == nil {
return daiheConfig{}, false
}
channel := parseDaiheConfig(cfg.Channel.ChanConfig)
template := parseDaiheConfig(cfg.Template.TempConfig)
out := template
if strings.TrimSpace(channel.AppID) != "" {
out.AppID = channel.AppID
}
if strings.TrimSpace(channel.AppSecret) != "" {
out.AppSecret = channel.AppSecret
}
if strings.TrimSpace(channel.BaseURL) != "" {
out.BaseURL = channel.BaseURL
}
if strings.TrimSpace(channel.API.BaseURL) != "" {
out.BaseURL = channel.API.BaseURL
}
if strings.TrimSpace(channel.Timeout) != "" {
out.Timeout = channel.Timeout
}
if strings.TrimSpace(channel.API.Timeout) != "" {
out.Timeout = channel.API.Timeout
}
if out.AppID == "" {
out.AppID = cfg.Channel.AppKey
}
if out.AppSecret == "" {
out.AppSecret = cfg.Channel.AppSecret
}
if out.BaseURL == "" {
out.BaseURL = "https://open.flymodem.com.cn"
}
return out, out.AppID != "" && out.AppSecret != ""
}
func (s *sSimDaihe) NewTemp(ctx context.Context, cfg *model.SimChannelConfigItemCache) model.SimCardChannelI {
raw, ok := pickDaiheConfig(cfg)
if !ok {
g.Log().Warning(ctx, "daihe.NewTemp: missing appId/appSecret")
return nil
}
timeout := 15 * time.Second
if d, err := time.ParseDuration(raw.Timeout); err == nil && d > 0 {
timeout = d
}
return &sSimDaihe{channelConfig: cfg, client: daihe.NewClient(daihe.Config{BaseURL: raw.BaseURL, AppID: raw.AppID, AppSecret: raw.AppSecret, Timeout: timeout})}
}
func daiheICCID(key *model.SimKey) string {
if key == nil {
return ""
}
return strings.TrimSpace(key.ICCID)
}
func daiheStatusCode(status string) (int, bool) {
switch strings.TrimSpace(status) {
case "库存":
return 7, true
case "可测试", "测试激活", "测试去激活":
return 6, true
case "可激活", "开始":
return 1, true
case "已激活":
return 2, true
case "已停用":
return 4, true
case "预清除":
return 8, true
case "已清除", "已失效", "已更换":
return 9, true
default:
return 0, false
}
}
func daiheUnsupported[T any](keys []*model.SimKey, name string) (out []*model.SimBaseRes[T], err error) {
for _, key := range keys {
out = append(out, &model.SimBaseRes[T]{Code: consts.ApiStatusError, SimKey: key, Message: "daihe does not support " + name})
}
return
}
func (s *sSimDaihe) QuerySimCardStatus(ctx context.Context, in *model.SimCardStatusInput) (out model.SimCardStatusOutput, err error) {
for _, key := range in.SimKeys {
r := &model.SimBaseRes[model.SimCardStatusItem]{SimKey: key}
iccid := daiheICCID(key)
var data daiheStatus
if iccid == "" {
r.Code = consts.ApiStatusError
r.Message = "iccid is required"
} else if e := s.client.QueryStatus(ctx, iccid, &data); e != nil {
r.Code = consts.ApiStatusError
r.Message = e.Error()
} else if status, ok := daiheStatusCode(data.Status); !ok {
r.Code = consts.ApiStatusError
r.Message = fmt.Sprintf("unsupported daihe card status: %s", data.Status)
} else {
r.Code = consts.ApiStatusSuccess
r.ResData.CardStatus = status
}
out = append(out, r)
}
return
}
func (s *sSimDaihe) QuerySimDataUsage(ctx context.Context, in *model.SimDataUsageInput) (out model.SimDataUsageOutput, err error) {
return s.queryUsage(ctx, in, "")
}
func (s *sSimDaihe) QuerySimDataUsageMonthly(ctx context.Context, in *model.SimDataUsageMonthlyInput) (out model.SimDataUsageMonthlyOutput, err error) {
month := ""
if in != nil {
month = strings.TrimSpace(in.ReqData.QueryDate)
}
result := make(model.SimDataUsageMonthlyOutput, 0, len(in.SimKeys))
for _, key := range in.SimKeys {
r := &model.SimBaseRes[model.SimDataUsageMonthlyOutputItem]{SimKey: key}
iccid := daiheICCID(key)
var data daiheUsage
if iccid == "" {
r.Code = consts.ApiStatusError
r.Message = "iccid is required"
} else if e := s.client.QueryUsage(ctx, iccid, month, &data); e != nil {
r.Code = consts.ApiStatusError
r.Message = e.Error()
} else {
r.Code = consts.ApiStatusSuccess
r.ResData.DeadLine = fmt.Sprintf("%06d", data.Month)
r.ResData.DataAmount = data.Used
}
result = append(result, r)
}
return result, nil
}
func (s *sSimDaihe) queryUsage(ctx context.Context, in *model.SimDataUsageInput, month string) (out model.SimDataUsageOutput, err error) {
for _, key := range in.SimKeys {
r := &model.SimBaseRes[model.SimDataUsageItem]{SimKey: key}
iccid := daiheICCID(key)
var data daiheUsage
if iccid == "" {
r.Code = consts.ApiStatusError
r.Message = "iccid is required"
} else if e := s.client.QueryUsage(ctx, iccid, month, &data); e != nil {
r.Code = consts.ApiStatusError
r.Message = e.Error()
} else {
r.Code = consts.ApiStatusSuccess
r.ResData.DataUsage = data.Used
}
out = append(out, r)
}
return
}
func (s *sSimDaihe) ChangeSimStatus(ctx context.Context, in *model.SimCardStatusChangeInput) (out model.SimCardStatusChangeOutput, err error) {
op, ok := normalizeCardStatusChangeOperType(ctx, in.ReqData.OperType)
if !ok {
return newInvalidCardStatusChangeOutput(in.SimKeys), nil
}
for _, key := range in.SimKeys {
r := &model.SimBaseRes[model.SimCardStatusChangeItem]{SimKey: key}
iccid := daiheICCID(key)
var e error
if iccid == "" {
e = fmt.Errorf("iccid is required")
} else if op == consts.CardStatusChangeOperTypeApplyStop {
e = s.client.Deactivate(ctx, iccid)
} else {
e = s.client.Activate(ctx, iccid)
}
if e != nil {
r.Code = consts.ApiStatusError
r.Message = e.Error()
} else {
r.Code = consts.ApiStatusSuccess
}
out = append(out, r)
}
return
}
func (s *sSimDaihe) QuerySimBasicInfo(ctx context.Context, in *model.SimBasicInfoInput) (model.SimBasicInfoOutput, error) {
return daiheUnsupported[model.SimBasicInfoItem](in.SimKeys, "basic info query")
}
func (s *sSimDaihe) QuerySimSession(ctx context.Context, in *model.SimSessionInput) (model.SimSessionOutput, error) {
return daiheUnsupported[model.SimSessionItem](in.SimKeys, "session query")
}
func (s *sSimDaihe) QuerySimStopReason(ctx context.Context, in *model.SimStopReasonInput) (model.SimStopReasonOutput, error) {
return daiheUnsupported[model.SimStopReasonItem](in.SimKeys, "stop reason query")
}
func (s *sSimDaihe) QuerySimFrozenState(ctx context.Context, in *model.SimFrozenStateInput) (model.SimFrozenStateOutput, error) {
return daiheUnsupported[model.SimFrozenStateItem](in.SimKeys, "frozen state query")
}
func (s *sSimDaihe) QuerySimCardBindStatus(ctx context.Context, in *model.SimCardBindStatusInput) (model.SimCardBindStatusOutput, error) {
return daiheUnsupported[model.SimCardBindStatusItem](in.SimKeys, "card binding query")
}
func (s *sSimDaihe) QuerySimDeviceStatus(ctx context.Context, in *model.SimDeviceStatusInput) (model.SimDeviceStatusOutput, error) {
return daiheUnsupported[model.SimDeviceStatusItem](in.SimKeys, "device status query")
}
func (s *sSimDaihe) QuerySimRegionLimitStatus(ctx context.Context, in *model.SimRegionLimitStatusInput) (model.SimRegionLimitStatusOutput, error) {
return daiheUnsupported[model.SimRegionLimitStatusItem](in.SimKeys, "region limit query")
}
func (s *sSimDaihe) QuerySimImei(ctx context.Context, in *model.SimImeiInput) (model.SimImeiOutput, error) {
return daiheUnsupported[model.SimImeiItem](in.SimKeys, "IMEI query")
}
func (s *sSimDaihe) QuerySimDataDiagnosis(ctx context.Context, in *model.SimDataDiagnosisInput) (model.SimDataDiagnosisOutput, error) {
return daiheUnsupported[any](in.SimKeys, "data diagnosis")
}
func (s *sSimDaihe) QuerySimDataUsageDaily(ctx context.Context, in *model.SimDataUsageDailyInput) (model.SimDataUsageDailyOutput, error) {
return daiheUnsupported[model.SimDataUsageDailyOutputItem](in.SimKeys, "daily usage query")
}
func (s *sSimDaihe) QuerySimApnInfo(ctx context.Context, in *model.SimApnInfoInput) (model.SimApnInfoOutput, error) {
return daiheUnsupported[model.SimApnInfoItemList](in.SimKeys, "APN query")
}
func (s *sSimDaihe) ChangeSimApnFunction(ctx context.Context, in *model.SimCardOperateChangeApnInput) (model.SimCardOperateChangeApnOutput, error) {
return daiheUnsupported[model.SimCardOperateChangeApnItem](in.SimKeys, "APN change")
}