package tencentvod import ( "bytes" "crypto/hmac" "crypto/sha256" "encoding/hex" "fmt" "net/http" "net/url" "strconv" "strings" "time" "github.com/QuantumNous/new-api/common" "github.com/QuantumNous/new-api/service" ) const vodService = "vod" const vodAPIVersion = "2018-07-17" func sha256hex(s string) string { b := sha256.Sum256([]byte(s)) return hex.EncodeToString(b[:]) } func hmacSha256(s, key string) []byte { h := hmac.New(sha256.New, []byte(key)) _, _ = h.Write([]byte(s)) return h.Sum(nil) } func tc3Authorization(secretID, secretKey, host, action string, timestamp int64, payloadJSON []byte) string { httpRequestMethod := "POST" canonicalURI := "/" canonicalQueryString := "" actionLower := strings.ToLower(action) canonicalHeaders := fmt.Sprintf("content-type:%s\nhost:%s\nx-tc-action:%s\n", "application/json", host, actionLower) signedHeaders := "content-type;host;x-tc-action" hashedRequestPayload := sha256hex(string(payloadJSON)) canonicalRequest := fmt.Sprintf("%s\n%s\n%s\n%s\n%s\n%s", httpRequestMethod, canonicalURI, canonicalQueryString, canonicalHeaders, signedHeaders, hashedRequestPayload) algorithm := "TC3-HMAC-SHA256" requestTimestamp := strconv.FormatInt(timestamp, 10) ts, _ := strconv.ParseInt(requestTimestamp, 10, 64) t := time.Unix(ts, 0).UTC() date := t.Format("2006-01-02") credentialScope := fmt.Sprintf("%s/%s/tc3_request", date, vodService) hashedCanonicalRequest := sha256hex(canonicalRequest) string2sign := fmt.Sprintf("%s\n%s\n%s\n%s", algorithm, requestTimestamp, credentialScope, hashedCanonicalRequest) secretDate := hmacSha256(date, "TC3"+secretKey) secretService := hmacSha256(vodService, string(secretDate)) signingKey := hmacSha256("tc3_request", string(secretService)) signature := hex.EncodeToString(hmacSha256(string2sign, string(signingKey))) return fmt.Sprintf("%s Credential=%s/%s, SignedHeaders=%s, Signature=%s", algorithm, secretID, credentialScope, signedHeaders, signature) } func SignedPOSTJSON(proxy string, endpoint string, region string, cred Credentials, action string, payloadJSON []byte) (*http.Response, error) { u, err := url.Parse(strings.TrimSpace(endpoint)) if err != nil || u.Host == "" { return nil, fmt.Errorf("invalid endpoint URL") } if u.Scheme == "" { u.Scheme = "https" } fullURL := u.Scheme + "://" + u.Host + "/" host := u.Host ts := common.GetTimestamp() auth := tc3Authorization(cred.SecretID, cred.SecretKey, host, action, ts, payloadJSON) req, err := http.NewRequest(http.MethodPost, fullURL, bytes.NewReader(payloadJSON)) if err != nil { return nil, err } req.Header.Set("Content-Type", "application/json") req.Header.Set("Authorization", auth) req.Header.Set("X-TC-Action", action) req.Header.Set("X-TC-Version", vodAPIVersion) req.Header.Set("X-TC-Timestamp", strconv.FormatInt(ts, 10)) if strings.TrimSpace(region) != "" { req.Header.Set("X-TC-Region", strings.TrimSpace(region)) } var client *http.Client if strings.TrimSpace(proxy) != "" { client, err = service.NewProxyHttpClient(strings.TrimSpace(proxy)) if err != nil { return nil, err } } else { client = service.GetHttpClient() } return client.Do(req) }