XinYeYouKu/app/third/dfpOpenSdk/opensdk/opensdk.go

488 lines
12 KiB
Go

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
}