package cardquery import ( "crypto/subtle" "encoding/json" "net/http" "strings" "git.5iot.com/iotlcm-public/iotlcm-upstream-proxy/internal/model" "git.5iot.com/iotlcm-public/iotlcm-upstream-proxy/internal/service" "github.com/gogf/gf/v2/frame/g" "github.com/gogf/gf/v2/net/ghttp" ) var appDiagnosisQueryPaths = map[string]bool{ "/sim/query/sim-basic-info": true, "/sim/query/sim-status": true, "/sim/query/sim-session": true, "/sim/query/sim-apn-info": true, "/sim/query/sim-imei": true, "/sim/query/sim-device-status": true, "/sim/query/sim-card-bind-status": true, "/sim/query/sim-data-diagnosis": true, "/sim/query/sim-stop-reason": true, "/sim/query/sim-frozen-state": true, "/sim/query/sim-datausage": true, "/sim/query/sim-region-limit-status": true, } // AppDiagnosisQuery bypasses the proxy's local card lookup only for verified // internal, read-only diagnosis requests. The existing /sim/* API is untouched. func AppDiagnosisQuery(r *ghttp.Request) { secret := strings.TrimSpace(g.Cfg().MustGet(r.Context(), "appDiagnosis.internalToken").String()) provided := r.Header.Get("X-App-Diagnosis-Token") if secret == "" || subtle.ConstantTimeCompare([]byte(secret), []byte(provided)) != 1 { appDiagnosisReject(r, http.StatusForbidden, "内部查询未授权") return } path := strings.TrimPrefix(r.URL.Path, "/internal/app-diagnosis") if !appDiagnosisQueryPaths[path] { appDiagnosisReject(r, http.StatusNotFound, "诊断接口不存在") return } if len(r.GetBody()) > 64*1024 { appDiagnosisReject(r, http.StatusRequestEntityTooLarge, "请求内容过大") return } var input model.SimBaseReqJson if err := json.Unmarshal(r.GetBody(), &input); err != nil || len(input.SimKeys) != 1 || input.SimKeys[0] == nil { appDiagnosisReject(r, http.StatusBadRequest, "诊断卡参数无效") return } key := input.SimKeys[0] key.ChanKey = strings.TrimSpace(key.ChanKey) if key.ChanKey == "" || strings.TrimSpace(key.ICCID) == "" { appDiagnosisReject(r, http.StatusBadRequest, "诊断卡通道或ICCID缺失") return } // Channel credentials and gateway routing are loaded by UpstreamAPI from // this proxy's own configured channel, never from the legacy database. channel, ok := service.UpstreamAPI().GetChan(key.ChanKey) if !ok || channel == nil || channel.Instance == nil { appDiagnosisReject(r, http.StatusNotFound, "诊断通道不可用") return } r.URL.Path = path data, err := service.UpstreamAPI().SimBase(r.Context(), &input) if err != nil { r.SetError(err) return } r.Response.WriteJson(g.Map{"code": 0, "data": data}) } func appDiagnosisReject(r *ghttp.Request, status int, message string) { r.Response.WriteStatus(status) r.Response.WriteJson(g.Map{"code": status, "message": message}) }