package opensdk import ( "bytes" "crypto/sha256" "crypto/tls" "encoding/base64" "encoding/hex" "encoding/json" "fmt" "io" "io/ioutil" "log" "math/rand" "mime/multipart" "net/http" "net/url" "os" "path/filepath" "qteam/app/third/dfpOpenSdk/config" "qteam/app/third/dfpOpenSdk/exception" "qteam/app/third/dfpOpenSdk/util" "reflect" "sort" "strings" "time" ) type OpenSDK struct { Configure config.OpenSdkConfigure KeyConfigure config.KeyConfigure } func (sdk OpenSDK) Gateway(reqUri string, reqMethod string, headParams map[string]string, urlParams map[string]string, bodyParams map[string]string) { //sdk.Configure.GetKeyConfigure() } func (sdk OpenSDK) GateWayWithKeyId(reqUri string, reqMethod string, headParams map[string]string, urlParams map[string]string, bodyParams map[string]string, keyId string) (string, error) { if keyId == "" { return "", nil } keyConfigure := sdk.Configure.KeyConfigures[keyId] if keyConfigure == nil { return "", &exception.SdkError{Code: "", Msg: ""} } result := sdk.exec(reqUri, reqMethod, headParams, urlParams, bodyParams, "", *keyConfigure, "") return result, nil } func (sdk OpenSDK) GatewayJsonWithKeyId(reqUri string, reqMethod string, headParams map[string]string, urlParams map[string]string, bodyJson string, keyId string) (string, error) { keyConfigure := sdk.Configure.GetKeyConfigure(keyId) if keyConfigure == nil { return "", &exception.SdkError{Code: "", Msg: ""} } if !json.Valid([]byte(bodyJson)) { return "", exception.PARAM_ERR() } // 发送请求 exec := sdk.exec(reqUri, reqMethod, headParams, urlParams, nil, "", *keyConfigure, bodyJson) return exec, nil } // 文件下载 func (sdk OpenSDK) DownloadFile(fileId string) (string, error) { urlParams := make(map[string]string) urlParams["fileId"] = fileId // 发送请求 nonce := getNonce(32) authorization := sdk.getAuthInfo("GET", "/api/open/downloadFile", nonce, urlParams, sdk.KeyConfigure) postUrl := sdk.getPostUrl() + "/api/open/downloadFile" request, _ := http.NewRequest(http.MethodGet, postUrl, nil) request.Header.Add("Authorization", authorization) client := &http.Client{} response, err := client.Do(request) if err != nil { return response.Status, nil } body := &bytes.Buffer{} writer := multipart.NewWriter(body) file, err := os.Open(fileId) if err != nil { panic(err) } part, err := writer.CreateFormFile(fileId, fileId) _, err = io.Copy(part, file) defer func(file *os.File) { err := file.Close() if err != nil { log.Fatal(err) } }(file) var result string return result, nil } func (sdk OpenSDK) UploadFileWithKeyId(path string, keyId string) (string, error) { keyConfigure := sdk.Configure.GetKeyConfigure(keyId) if keyConfigure == nil { return "", &exception.SdkError{Code: "", Msg: ""} } reqUri := "/api/open/uploadFile" hash := util.FileHash(path) if util.EmptyString(hash) { return "", exception.FILE_ERROR_RESULT() } var bodyParamMap = map[string]string{ "fileHashValue": hash, } exec := sdk.exec(reqUri, http.MethodPost, nil, nil, bodyParamMap, path, *keyConfigure, "") return exec, nil } // UploadFile 文件上传 func (sdk OpenSDK) UploadFile(path string) (string, error) { file, err := ioutil.ReadFile(path) if err != nil { return "", err } // 计算文件hash h := sha256.New() h.Write(file) hash := h.Sum(nil) bodyParams := make(map[string]string) bodyParams["fileHashValue"] = hex.EncodeToString(hash) buf := new(bytes.Buffer) bw := multipart.NewWriter(buf) formFile, err := bw.CreateFormFile("file", path) open, err := os.Open(path) io.Copy(formFile, open) defer func(bw *multipart.Writer) { err := bw.Close() if err != nil { } }(bw) nonce := getNonce(32) authorization := sdk.getAuthInfo("POST", "/api/open/uploadFile", nonce, bodyParams, sdk.KeyConfigure) // 创建request postUrl := sdk.getPostUrl() + "/api/open/uploadFile" request, _ := http.NewRequest(http.MethodPost, postUrl, buf) request.Header.Add("Authorization", authorization) request.Header.Set("Content-Type", "multipart/form-data") client := &http.Client{} response, err := client.Do(request) fmt.Println(response.Body) // 发送请求 return "", err } func (sdk OpenSDK) DownloadFileWithKeyId(fileId string, saveFilePath, keyId string) (string, error) { keyConfigure := sdk.Configure.GetKeyConfigure(keyId) if keyConfigure == nil { return "", &exception.SdkError{Code: "", Msg: ""} } reqUri := "/api/open/downloadFile" var urlParamMap = map[string]string{ "fileId": fileId, } body := sdk.exec(reqUri, http.MethodGet, nil, urlParamMap, nil, "", *keyConfigure, "") if reflect.TypeOf(body).Kind() == reflect.String { return body, nil } saveFile, err := os.Create(saveFilePath) if err != nil { fmt.Println(err) } defer func(saveFile *os.File) { err := saveFile.Close() if err != nil { log.Fatal(err) } }(saveFile) content := []byte(body) write, err := saveFile.Write(content) if err != nil { return "", err } if len(content) != write { return "", nil } return "", nil } func (sdk OpenSDK) exec(url string, method string, headParams map[string]string, urlParams map[string]string, bodyParamMap map[string]string, filePath string, keyConfigure config.KeyConfigure, bodyJson string) string { signParams := make(map[string]string) if headParams != nil { for k, v := range headParams { signParams[k] = v } } if urlParams != nil { for k, v := range urlParams { signParams[k] = v } } if bodyParamMap != nil { for k, v := range bodyParamMap { signParams[k] = v } } if !util.EmptyString(bodyJson) { signParams["BODY"] = bodyJson } reqUri := util.CheckReqUri(url) nonce := getNonce(32) authorization := sdk.getAuthInfo(method, reqUri, nonce, signParams, keyConfigure) // 拼接请求参数并进行编码 urlParamString := util.JointMap(urlParams) buffer := bytes.Buffer{} buffer.WriteString(sdk.getPostUrl()) buffer.WriteString(reqUri) switch method { case http.MethodGet, http.MethodPost: if urlParamString != "" { if strings.Contains(buffer.String(), "?") { buffer.WriteString("&") } else { buffer.WriteString("?") } buffer.WriteString(urlParamString) } break default: break } response := sdk.send(buffer.String(), method, authorization, headParams, filePath, bodyParamMap, keyConfigure, bodyJson) return response } // 获取签名信息 func (sdk OpenSDK) getAuthInfo(method string, reqUri string, nonce string, signParams map[string]string, keyConfigure config.KeyConfigure) string { timestamp := time.Now().Format("20060102150405") signstr := keyConfigure.KeyId + "&" + timestamp + "&" + nonce + "&" + method + "&" + reqUri keys := make([]string, 0, len(signParams)) for k := range signParams { keys = append(keys, k) } sort.Strings(keys) for _, k := range keys { signstr = signstr + "&" + k + "=" + signParams[k] } user := keyConfigure.KeyId + "_" + timestamp + "_" + nonce pwd, _ := util.SignatureBySM2(signstr, keyConfigure.PriKey) return "Basic " + base64.StdEncoding.EncodeToString([]byte(user+":"+pwd)) } var letters = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ") // 获取n位随机字符串 func getNonce(n int) string { b := make([]rune, n) rand.Seed(time.Now().UnixNano()) for i := range b { b[i] = letters[rand.Intn(len(letters))] } return string(b) } // 发送请求 func (sdk OpenSDK) send(urlPath string, method string, authInfo string, headParams map[string]string, filePath string, bodyParamMap map[string]string, keyConfigure config.KeyConfigure, bodyJson string) string { var client *http.Client // 测试环境跳过证书校验 if sdk.Configure.DevEnv { tr := &http.Transport{ TLSClientConfig: &tls.Config{InsecureSkipVerify: true}, } client = &http.Client{Transport: tr} } else { client = &http.Client{} } var request *http.Request if method == http.MethodGet { request, _ = http.NewRequest(http.MethodGet, urlPath, nil) } else { if filePath != "" { file, _ := os.Open(filePath) defer func(file *os.File) { err := file.Close() if err != nil { log.Fatal(err) } }(file) var requestBody bytes.Buffer multipartWriter := multipart.NewWriter(&requestBody) part, err := multipartWriter.CreateFormFile("file", filepath.Base(filePath)) if err != nil { fmt.Println("Failed to create form file:", err) } // 将文件内容复制到multipart.Part中 _, err = io.Copy(part, file) if err != nil { fmt.Println("Failed to copy file content:", err) } // 添加其他表单字段 for k, v := range bodyParamMap { err := multipartWriter.WriteField(k, v) if err != nil { return "" } } err = multipartWriter.Close() if err != nil { return "" } request, _ = http.NewRequest(method, urlPath, &requestBody) request.Header.Set("Content-Type", multipartWriter.FormDataContentType()) } else { if bodyJson != "" { request, _ = http.NewRequest(method, urlPath, bytes.NewReader([]byte(bodyJson))) request.Header.Add("Content-Type", "application/json; charset=UTF-8") } else { urlValues := url.Values{} if bodyParamMap != nil { for key, val := range bodyParamMap { urlValues.Set(key, val) } } request, _ = http.NewRequest(method, urlPath, strings.NewReader(urlValues.Encode())) } } } client.Timeout = time.Second * 30 // 设置请求头信息 sdk.setHeader(authInfo, keyConfigure, request, headParams) // 发送HTTP请求 response, err := client.Do(request) defer func(Body io.ReadCloser) { err := Body.Close() if err != nil { log.Println(err) } }(response.Body) if err != nil { log.Println(err) } // 获取返回结果 body, err := ioutil.ReadAll(response.Body) if err != nil { log.Fatal(err) } var result = string(body) timestamp := response.Header.Get("Timestamp") nonce := response.Header.Get("Nonce") signature := response.Header.Get("Signature") if strings.HasPrefix(result, "\"code\":\"OPEN") { return result } // 响应报文验签 if keyConfigure.RespSignSwitch && !strings.HasPrefix(result, "\"code\":\"OPEN") { verify, _ := util.VerifyBySM2([]byte(keyConfigure.KeyId+"&"+timestamp+"&"+nonce+"&"+result), signature, keyConfigure.RespPubKey) if !verify { return "" } } return result } //func (sdk OpenSDK) Get(reqUrl string, reqParams map[string]string, headers map[string]string) string { // urlParams := url.Values{} // Url, _ := url.Parse(reqUrl) // for key, val := range reqParams { // urlParams.Set(key, val) // } // // //如果参数中有中文参数,这个方法会进行URLEncode // Url.RawQuery = urlParams.Encode() // urlPath := Url.String() // // httpRequest, _ := http.NewRequest("GET", urlPath, nil) // // 添加请求头 // if headers != nil { // for k, v := range headers { // httpRequest.Header.Add(k, v) // } // } // // 发送请求 // resp, err := httpClient.Do(httpRequest) // if err != nil { // panic(err) // } // defer resp.Body.Close() // response, _ := ioutil.ReadAll(resp.Body) // return string(response) //} // 设置请求头 func (sdk OpenSDK) setHeader(authInfo string, configure config.KeyConfigure, request *http.Request, headParams map[string]string) { if configure.EnterpriseBearer != "" { authInfo = authInfo + "," + configure.EnterpriseBearer } request.Header.Add("Authorization", authInfo) if configure.XCfcaBasic != "" { request.Header.Add("X-Cfca-Basic", configure.XCfcaBasic) } if headParams != nil { for k, v := range headParams { request.Header.Add(k, v) } } // 灰度发布配置 if configure.GrayConfigure != nil && len(configure.GrayConfigure) != 0 { for k, v := range configure.GrayConfigure { request.Header.Add(k, v) } } } //func (sdk OpenSDK) createRequest(urlPath string, method string, bodyJson string) *http.Request { // if method == http.MethodGet { // //request, err := http.NewRequest(http.MethodGet, urlPath, nil) // } else if method == http.MethodPost { // if bodyJson != "" { // request, _ = http.NewRequest(method, urlPath, bytes.NewReader([]byte(bodyJson))) // request.Header.Add("Content-Type", "application/json; charset=UTF-8") // } else { // request, _ = http.NewRequest(method, urlPath, strings.NewReader(urlValues.Encode())) // } // } // return nil //} func (sdk OpenSDK) getPostUrl() string { var urlPath = "" if sdk.Configure.DevEnv { urlPath = sdk.Configure.DevUrl } else { urlPath = sdk.Configure.ProdUrl } if urlPath != "" && strings.HasSuffix(urlPath, "/") { return urlPath[0 : len(urlPath)-1] } return urlPath }