package utils import ( "crypto/hmac" "crypto/sha256" "encoding/hex" "encoding/json" "fmt" "git.sxidc.com/student-physical-examination/contract_lock_sdk/commons" "git.sxidc.com/student-physical-examination/contract_lock_sdk/config" "git.sxidc.com/student-physical-examination/contract_lock_sdk/constant" "git.sxidc.com/student-physical-examination/contract_lock_sdk/http" "github.com/tjfoc/gmsm/sm3" "io/ioutil" "log" "os" "reflect" "strconv" "strings" ) type SdkClient struct { ServerUrl string AccessToken string AccessSecret string SignatureVersion string TraceId string IdempotentToken string EnableNonce bool CustomHeaders map[string]string ProxyInfo *config.ProxyInfo } func NewSdkClient(serverUrl string, accessToken string, accessSecret string) *SdkClient { sdkClient := SdkClient{ ServerUrl: serverUrl, AccessToken: accessToken, AccessSecret: accessSecret, SignatureVersion: commons.MD5, EnableNonce: true, } return &sdkClient } // 返回字符串 func (sdk *SdkClient) ServiceAsString(request SdkRequest) string { return sdk.SdkRequest(request) } // 只返回code、message func (sdk *SdkClient) Service(request SdkRequest) *SdkResponse { jsonStr := sdk.SdkRequest(request) response := SdkResponse{} var jsonObj map[string]interface{} if err := json.Unmarshal([]byte(jsonStr), &jsonObj); err != nil { log.Println("Error parsing JSON:", err) return &response } codeStr := fmt.Sprintf("%v", jsonObj["code"]) code, _ := strconv.ParseInt(codeStr, 10, 64) response.Code = code response.Message = jsonObj["message"].(string) response.ResultStream = false return &response } // code、message、result(包括基本类型和对象类型和对象数组类型) func (sdk *SdkClient) ServiceAsModel(request SdkRequest, obj interface{}) *SdkResponse { jsonStr := sdk.SdkRequest(request) response := SdkResponse{} var jsonObj map[string]interface{} if err := json.Unmarshal([]byte(jsonStr), &jsonObj); err != nil { log.Println("Error parsing JSON:", err) return &response } codeStr := fmt.Sprintf("%v", jsonObj["code"]) code, _ := strconv.ParseInt(codeStr, 10, 64) response.Code = code response.Message = jsonObj["message"].(string) response.ResultStream = false delete(jsonObj, "code") delete(jsonObj, "message") num := len(jsonObj) // 返回结果只存在code、message if num == 0 { return &response } //处理返回值为code、message、result(基础类型) basicType := isBasicType(obj) if basicType { // 检查是否存在某个键 value, exists := constant.BASICS_TYPE[request.GetUrl()] if exists { result, _ := jsonObj[value] response.Result = result } else { for _, result := range jsonObj { response.Result = result } } return &response } //处理返回值为code、message、result(对象类型) // 返回结果除去code、message之后,只有一个字段,可能出现的结果如下: // 1、基本类型 // 2、对象类型 var resultData interface{} if num == 1 { for key, value := range jsonObj { valueType := reflect.ValueOf(value).Kind() if valueType == reflect.Map { resultData = value } else { flag := commons.IsPropertyExists(obj, key) if flag { resultData = jsonObj } } jsonBytes, _ := json.Marshal(resultData) json.Unmarshal(jsonBytes, obj) response.Result = obj return &response } } //处理返回值为code、message、result1(任意类型)、result2(任意类型)【将result1、result2封装为一个对象中的两个字段】 if num > 1 { fieldName, exists := constant.EXTRA_FIELD[request.GetUrl()] if exists { result, _ := jsonObj[fieldName] switch reflect.TypeOf(result).Kind() { case reflect.Map: if resultMap, ok := result.(map[string]interface{}); ok { for key, value := range jsonObj { if fieldName != key { resultMap[key] = value } } resultData = resultMap } case reflect.Slice: if resultList, ok := result.([]interface{}); ok { for _, value := range resultList { if resultMap, ok := value.(map[string]interface{}); ok { for key, value := range jsonObj { if fieldName != key { resultMap[key] = value } } } } resultData = result } } } else { resultData = jsonObj } } jsonBytes, _ := json.Marshal(resultData) json.Unmarshal(jsonBytes, obj) response.Result = obj return &response } // 文件下载 func (sdk *SdkClient) Download(request SdkRequest, file *os.File) *SdkResponse { if strings.HasSuffix(sdk.ServerUrl, "/") { sdk.ServerUrl = sdk.ServerUrl[:len(sdk.ServerUrl)-1] } url := sdk.ServerUrl + request.GetUrl() parameter := request.GetHttpParameter() header := sdk.buildHttpHeader(parameter) jsonStr := "" if parameter.IsJson() { jsonStr = http.DoDownloadWithJson(url, parameter, header, file, sdk.ProxyInfo) } else { jsonStr = http.DoDownload(url, parameter, header, file, sdk.ProxyInfo) } response := SdkResponse{} if len(jsonStr) <= 0 { response.Code = 0 response.Message = "SUCCESS" response.ResultStream = true return &response } response.ResultStream = false var jsonObj map[string]interface{} if err := json.Unmarshal([]byte(jsonStr), &jsonObj); err != nil { log.Println("Error parsing JSON:", err) return &response } codeStr := fmt.Sprintf("%v", jsonObj["code"]) code, _ := strconv.ParseInt(codeStr, 10, 64) response.Code = code response.Message = jsonObj["message"].(string) delete(jsonObj, "code") delete(jsonObj, "message") num := len(jsonObj) // 返回结果只存在code、message if num == 0 { return &response } var resultObj interface{} for _, result := range jsonObj { resultObj = result } resultData, _ := json.Marshal(resultObj) reflectObj, exists := constant.STREAM_RESULT[request.GetUrl()] if exists { personValue := reflect.New(reflectObj).Elem() err := json.Unmarshal(resultData, personValue.Addr().Interface()) if err != nil { fmt.Println("Error unmarshalling JSON:", err) return &response } obj := personValue.Interface() response.Result = obj return &response } return &response } func (sdk *SdkClient) SdkRequest(request SdkRequest) string { if strings.HasSuffix(sdk.ServerUrl, "/") { sdk.ServerUrl = sdk.ServerUrl[:len(sdk.ServerUrl)-1] } url := sdk.ServerUrl + request.GetUrl() parameter := request.GetHttpParameter() header := sdk.buildHttpHeader(parameter) if parameter.IsJson() { return http.DoServiceWithJson(url, parameter, header, sdk.ProxyInfo) } return http.DoService(url, parameter, header, sdk.ProxyInfo) } func (sdk *SdkClient) buildHttpHeader(httpParameter *http.HttpParameter) *http.HttpHeader { timestamp := commons.GetTimeStamp() nonce := "" if sdk.EnableNonce { nonce = commons.GetUUID() } var signature string if commons.HMACSHA256 == sdk.SignatureVersion { hmacSignatureList := make([]ParameterBody, 0) hmacSignatureList = append(hmacSignatureList, NewStringParameter(commons.ACCESS_TOKEN, sdk.AccessToken)) hmacSignatureList = append(hmacSignatureList, NewStringParameter(commons.TIMESTAMP, timestamp)) hmacSignatureList = append(hmacSignatureList, NewStringParameter(commons.NONCE, nonce)) hmacSignatureList = append(hmacSignatureList, NewStringParameter(commons.SIGNATURE_VERSION, sdk.SignatureVersion)) hmacSignatureList = append(hmacSignatureList, NewStringParameter(commons.IDEMPOTENTTOKEN, sdk.IdempotentToken)) hmacSignatureList = append(hmacSignatureList, NewStringParameter(commons.TRACEID, sdk.TraceId)) if httpParameter.IsJson() { hmacSignatureList = append(hmacSignatureList, NewStringParameter(commons.BODY, httpParameter.JsonParamer())) } else { hmacSignatureList = append(hmacSignatureList, NewStringParameter(commons.BODY, "")) params := httpParameter.Params() for key, value := range params { if commons.IsNil(value) { continue } switch t := value.(type) { case string: if len(t) != 0 { hmacSignatureList = append(hmacSignatureList, NewStringParameter(key, fmt.Sprintf("%v", t))) } case *int, *int32, *int64: if f, ok := value.(*int64); ok { hmacSignatureList = append(hmacSignatureList, NewStringParameter(key, fmt.Sprintf("%d", *f))) } case *float32, *float64: if f, ok := value.(*float64); ok { hmacSignatureList = append(hmacSignatureList, NewStringParameter(key, fmt.Sprintf("%f", *f))) } case *bool: if f, ok := value.(*bool); ok { hmacSignatureList = append(hmacSignatureList, NewStringParameter(key, fmt.Sprintf("%t", *f))) } default: hmacSignatureList = append(hmacSignatureList, NewStringParameter(key, fmt.Sprintf("%v", value))) } } files := httpParameter.Files() for key, file := range files { defer file.Close() bytes, _ := ioutil.ReadAll(file) hmacSignatureList = append(hmacSignatureList, NewBytesParameter(key, bytes)) } listFiles := httpParameter.ListFiles() for key, fileList := range listFiles { for _, file := range fileList { defer file.Close() bytes, _ := ioutil.ReadAll(file) hmacSignatureList = append(hmacSignatureList, NewBytesParameter(key, bytes)) } } } signature = sdk.CalculateSignature(httpParameter.HttpMethod(), hmacSignatureList) } else if commons.SM3 == sdk.SignatureVersion { rawSig := sdk.AccessToken + sdk.AccessSecret + timestamp + nonce hash := sm3.New() hash.Write([]byte(rawSig)) result := hash.Sum(nil) signature = hex.EncodeToString(result) } else { signature = commons.GetMD5(sdk.AccessToken + sdk.AccessSecret + timestamp + nonce) } header := http.HttpHeader{ AccessToken: sdk.AccessToken, Timestamp: timestamp, Nonce: nonce, Signature: signature, SignatureVersion: sdk.SignatureVersion, TraceId: sdk.TraceId, IdempotentToken: sdk.IdempotentToken, CustomHeaders: sdk.CustomHeaders, } return &header } func (sdk *SdkClient) CalculateSignature(method string, hmacSignatureList []ParameterBody) string { SortParameterBody(hmacSignatureList) mac := hmac.New(sha256.New, []byte(sdk.AccessSecret)) mac.Write([]byte(method)) for _, parameterBody := range hmacSignatureList { str := commons.CONNECTOR + parameterBody.Name + commons.EQUALSIGN mac.Write([]byte(str)) if parameterBody.Bytes != nil { mac.Write(parameterBody.Bytes) } } sum := mac.Sum(nil) hexMac := make([]byte, len(sum)*2) hex.Encode(hexMac, sum) return fmt.Sprintf("%s", hexMac) }