...

Source file src/github.com/alibabacloud-go/openapi-util/service/service.go

Documentation: github.com/alibabacloud-go/openapi-util/service

     1  // This file is auto-generated, don't edit it. Thanks.
     2  /**
     3   * This is for OpenApi Util
     4   */
     5  package service
     6  
     7  import (
     8  	"bytes"
     9  	"crypto"
    10  	"crypto/hmac"
    11  	"crypto/rand"
    12  	"crypto/rsa"
    13  	"crypto/sha1"
    14  	"crypto/sha256"
    15  	"crypto/x509"
    16  	"encoding/base64"
    17  	"encoding/hex"
    18  	"encoding/json"
    19  	"encoding/pem"
    20  	"errors"
    21  	"fmt"
    22  	"hash"
    23  	"io"
    24  	"net/http"
    25  	"net/textproto"
    26  	"net/url"
    27  	"reflect"
    28  	"sort"
    29  	"strconv"
    30  	"strings"
    31  	"time"
    32  
    33  	util "github.com/alibabacloud-go/tea-utils/service"
    34  	"github.com/alibabacloud-go/tea/tea"
    35  	"github.com/tjfoc/gmsm/sm3"
    36  )
    37  
    38  const (
    39  	PEM_BEGIN = "-----BEGIN RSA PRIVATE KEY-----\n"
    40  	PEM_END   = "\n-----END RSA PRIVATE KEY-----"
    41  )
    42  
    43  type Sorter struct {
    44  	Keys []string
    45  	Vals []string
    46  }
    47  
    48  func newSorter(m map[string]string) *Sorter {
    49  	hs := &Sorter{
    50  		Keys: make([]string, 0, len(m)),
    51  		Vals: make([]string, 0, len(m)),
    52  	}
    53  
    54  	for k, v := range m {
    55  		hs.Keys = append(hs.Keys, k)
    56  		hs.Vals = append(hs.Vals, v)
    57  	}
    58  	return hs
    59  }
    60  
    61  // Sort is an additional function for function SignHeader.
    62  func (hs *Sorter) Sort() {
    63  	sort.Sort(hs)
    64  }
    65  
    66  // Len is an additional function for function SignHeader.
    67  func (hs *Sorter) Len() int {
    68  	return len(hs.Vals)
    69  }
    70  
    71  // Less is an additional function for function SignHeader.
    72  func (hs *Sorter) Less(i, j int) bool {
    73  	return bytes.Compare([]byte(hs.Keys[i]), []byte(hs.Keys[j])) < 0
    74  }
    75  
    76  // Swap is an additional function for function SignHeader.
    77  func (hs *Sorter) Swap(i, j int) {
    78  	hs.Vals[i], hs.Vals[j] = hs.Vals[j], hs.Vals[i]
    79  	hs.Keys[i], hs.Keys[j] = hs.Keys[j], hs.Keys[i]
    80  }
    81  
    82  /**
    83   * Convert all params of body other than type of readable into content
    84   * @param body source Model
    85   * @param content target Model
    86   * @return void
    87   */
    88  func Convert(body interface{}, content interface{}) {
    89  	res := make(map[string]interface{})
    90  	val := reflect.ValueOf(body).Elem()
    91  	dataType := val.Type()
    92  	for i := 0; i < dataType.NumField(); i++ {
    93  		field := dataType.Field(i)
    94  		name, _ := field.Tag.Lookup("json")
    95  		name = strings.Split(name, ",omitempty")[0]
    96  		_, ok := val.Field(i).Interface().(io.Reader)
    97  		if !ok {
    98  			res[name] = val.Field(i).Interface()
    99  		}
   100  	}
   101  	byt, _ := json.Marshal(res)
   102  	json.Unmarshal(byt, content)
   103  }
   104  
   105  /**
   106   * Get the string to be signed according to request
   107   * @param request  which contains signed messages
   108   * @return the signed string
   109   */
   110  func GetStringToSign(request *tea.Request) (_result *string) {
   111  	return tea.String(getStringToSign(request))
   112  }
   113  
   114  func getStringToSign(request *tea.Request) string {
   115  	resource := tea.StringValue(request.Pathname)
   116  	queryParams := request.Query
   117  	// sort QueryParams by key
   118  	var queryKeys []string
   119  	for key := range queryParams {
   120  		queryKeys = append(queryKeys, key)
   121  	}
   122  	sort.Strings(queryKeys)
   123  	tmp := ""
   124  	for i := 0; i < len(queryKeys); i++ {
   125  		queryKey := queryKeys[i]
   126  		v := tea.StringValue(queryParams[queryKey])
   127  		if v != "" {
   128  			tmp = tmp + "&" + queryKey + "=" + v
   129  		} else {
   130  			tmp = tmp + "&" + queryKey
   131  		}
   132  	}
   133  	if tmp != "" {
   134  		tmp = strings.TrimLeft(tmp, "&")
   135  		resource = resource + "?" + tmp
   136  	}
   137  	return getSignedStr(request, resource)
   138  }
   139  
   140  func getSignedStr(req *tea.Request, canonicalizedResource string) string {
   141  	temp := make(map[string]string)
   142  
   143  	for k, v := range req.Headers {
   144  		if strings.HasPrefix(strings.ToLower(k), "x-acs-") {
   145  			temp[strings.ToLower(k)] = tea.StringValue(v)
   146  		}
   147  	}
   148  	hs := newSorter(temp)
   149  
   150  	// Sort the temp by the ascending order
   151  	hs.Sort()
   152  
   153  	// Get the canonicalizedOSSHeaders
   154  	canonicalizedOSSHeaders := ""
   155  	for i := range hs.Keys {
   156  		canonicalizedOSSHeaders += hs.Keys[i] + ":" + hs.Vals[i] + "\n"
   157  	}
   158  
   159  	// Give other parameters values
   160  	// when sign URL, date is expires
   161  	date := tea.StringValue(req.Headers["date"])
   162  	accept := tea.StringValue(req.Headers["accept"])
   163  	contentType := tea.StringValue(req.Headers["content-type"])
   164  	contentMd5 := tea.StringValue(req.Headers["content-md5"])
   165  
   166  	signStr := tea.StringValue(req.Method) + "\n" + accept + "\n" + contentMd5 + "\n" + contentType + "\n" + date + "\n" + canonicalizedOSSHeaders + canonicalizedResource
   167  	return signStr
   168  }
   169  
   170  /**
   171   * Get signature according to stringToSign, secret
   172   * @param stringToSign  the signed string
   173   * @param secret accesskey secret
   174   * @return the signature
   175   */
   176  func GetROASignature(stringToSign *string, secret *string) (_result *string) {
   177  	h := hmac.New(func() hash.Hash { return sha1.New() }, []byte(tea.StringValue(secret)))
   178  	io.WriteString(h, tea.StringValue(stringToSign))
   179  	signedStr := base64.StdEncoding.EncodeToString(h.Sum(nil))
   180  	return tea.String(signedStr)
   181  }
   182  
   183  func GetEndpoint(endpoint *string, server *bool, endpointType *string) *string {
   184  	if tea.StringValue(endpointType) == "internal" {
   185  		strs := strings.Split(tea.StringValue(endpoint), ".")
   186  		strs[0] += "-internal"
   187  		endpoint = tea.String(strings.Join(strs, "."))
   188  	}
   189  	if tea.BoolValue(server) && tea.StringValue(endpointType) == "accelerate" {
   190  		return tea.String("oss-accelerate.aliyuncs.com")
   191  	}
   192  
   193  	return endpoint
   194  }
   195  
   196  func HexEncode(raw []byte) *string {
   197  	return tea.String(hex.EncodeToString(raw))
   198  }
   199  
   200  func Hash(raw []byte, signatureAlgorithm *string) []byte {
   201  	signType := tea.StringValue(signatureAlgorithm)
   202  	if signType == "ACS3-HMAC-SHA256" || signType == "ACS3-RSA-SHA256" {
   203  		h := sha256.New()
   204  		h.Write(raw)
   205  		return h.Sum(nil)
   206  	} else if signType == "ACS3-HMAC-SM3" {
   207  		h := sm3.New()
   208  		h.Write(raw)
   209  		return h.Sum(nil)
   210  	}
   211  	return nil
   212  }
   213  
   214  func GetEncodePath(path *string) *string {
   215  	uri := tea.StringValue(path)
   216  	strs := strings.Split(uri, "/")
   217  	for i, v := range strs {
   218  		strs[i] = url.QueryEscape(v)
   219  	}
   220  	uri = strings.Join(strs, "/")
   221  	uri = strings.Replace(uri, "+", "%20", -1)
   222  	uri = strings.Replace(uri, "*", "%2A", -1)
   223  	uri = strings.Replace(uri, "%7E", "~", -1)
   224  	return tea.String(uri)
   225  }
   226  
   227  func GetEncodeParam(param *string) *string {
   228  	uri := tea.StringValue(param)
   229  	uri = url.QueryEscape(uri)
   230  	uri = strings.Replace(uri, "+", "%20", -1)
   231  	uri = strings.Replace(uri, "*", "%2A", -1)
   232  	uri = strings.Replace(uri, "%7E", "~", -1)
   233  	return tea.String(uri)
   234  }
   235  
   236  func GetAuthorization(request *tea.Request, signatureAlgorithm, payload, acesskey, secret *string) *string {
   237  	canonicalURI := tea.StringValue(request.Pathname)
   238  	if canonicalURI == "" {
   239  		canonicalURI = "/"
   240  	}
   241  
   242  	canonicalURI = strings.Replace(canonicalURI, "+", "%20", -1)
   243  	canonicalURI = strings.Replace(canonicalURI, "*", "%2A", -1)
   244  	canonicalURI = strings.Replace(canonicalURI, "%7E", "~", -1)
   245  
   246  	method := tea.StringValue(request.Method)
   247  	canonicalQueryString := getCanonicalQueryString(request.Query)
   248  	canonicalheaders, signedHeaders := getCanonicalHeaders(request.Headers)
   249  
   250  	canonicalRequest := method + "\n" + canonicalURI + "\n" + canonicalQueryString + "\n" + canonicalheaders + "\n" +
   251  		strings.Join(signedHeaders, ";") + "\n" + tea.StringValue(payload)
   252  	signType := tea.StringValue(signatureAlgorithm)
   253  	StringToSign := signType + "\n" + tea.StringValue(HexEncode(Hash([]byte(canonicalRequest), signatureAlgorithm)))
   254  	signature := tea.StringValue(HexEncode(SignatureMethod(tea.StringValue(secret), StringToSign, signType)))
   255  	auth := signType + " Credential=" + tea.StringValue(acesskey) + ",SignedHeaders=" +
   256  		strings.Join(signedHeaders, ";") + ",Signature=" + signature
   257  	return tea.String(auth)
   258  }
   259  
   260  func SignatureMethod(secret, source, signatureAlgorithm string) []byte {
   261  	if signatureAlgorithm == "ACS3-HMAC-SHA256" {
   262  		h := hmac.New(sha256.New, []byte(secret))
   263  		h.Write([]byte(source))
   264  		return h.Sum(nil)
   265  	} else if signatureAlgorithm == "ACS3-HMAC-SM3" {
   266  		h := hmac.New(sm3.New, []byte(secret))
   267  		h.Write([]byte(source))
   268  		return h.Sum(nil)
   269  	} else if signatureAlgorithm == "ACS3-RSA-SHA256" {
   270  		return rsaSign(source, secret)
   271  	}
   272  	return nil
   273  }
   274  
   275  func rsaSign(content, secret string) []byte {
   276  	h := crypto.SHA256.New()
   277  	h.Write([]byte(content))
   278  	hashed := h.Sum(nil)
   279  	priv, err := parsePrivateKey(secret)
   280  	if err != nil {
   281  		return nil
   282  	}
   283  	sign, err := rsa.SignPKCS1v15(rand.Reader, priv, crypto.SHA256, hashed)
   284  	if err != nil {
   285  		return nil
   286  	}
   287  	return sign
   288  }
   289  
   290  func parsePrivateKey(privateKey string) (*rsa.PrivateKey, error) {
   291  	privateKey = formatPrivateKey(privateKey)
   292  	block, _ := pem.Decode([]byte(privateKey))
   293  	if block == nil {
   294  		return nil, errors.New("PrivateKey is invalid")
   295  	}
   296  	priKey, err := x509.ParsePKCS8PrivateKey(block.Bytes)
   297  	if err != nil {
   298  		return nil, err
   299  	}
   300  	switch priKey.(type) {
   301  	case *rsa.PrivateKey:
   302  		return priKey.(*rsa.PrivateKey), nil
   303  	default:
   304  		return nil, nil
   305  	}
   306  }
   307  
   308  func formatPrivateKey(privateKey string) string {
   309  	if !strings.HasPrefix(privateKey, PEM_BEGIN) {
   310  		privateKey = PEM_BEGIN + privateKey
   311  	}
   312  
   313  	if !strings.HasSuffix(privateKey, PEM_END) {
   314  		privateKey += PEM_END
   315  	}
   316  	return privateKey
   317  }
   318  
   319  func getCanonicalHeaders(headers map[string]*string) (string, []string) {
   320  	tmp := make(map[string]string)
   321  	tmpHeader := http.Header{}
   322  	for k, v := range headers {
   323  		if strings.HasPrefix(strings.ToLower(k), "x-acs-") || strings.ToLower(k) == "host" ||
   324  			strings.ToLower(k) == "content-type" {
   325  			tmp[strings.ToLower(k)] = strings.TrimSpace(tea.StringValue(v))
   326  			tmpHeader.Add(strings.ToLower(k), strings.TrimSpace(tea.StringValue(v)))
   327  		}
   328  	}
   329  	hs := newSorter(tmp)
   330  
   331  	// Sort the temp by the ascending order
   332  	hs.Sort()
   333  	canonicalheaders := ""
   334  	for _, key := range hs.Keys {
   335  		vals := tmpHeader[textproto.CanonicalMIMEHeaderKey(key)]
   336  		sort.Strings(vals)
   337  		canonicalheaders += key + ":" + strings.Join(vals, ",") + "\n"
   338  	}
   339  
   340  	return canonicalheaders, hs.Keys
   341  }
   342  
   343  func getCanonicalQueryString(query map[string]*string) string {
   344  	canonicalQueryString := ""
   345  	if tea.BoolValue(util.IsUnset(query)) {
   346  		return canonicalQueryString
   347  	}
   348  	tmp := make(map[string]string)
   349  	for k, v := range query {
   350  		tmp[k] = tea.StringValue(v)
   351  	}
   352  
   353  	hs := newSorter(tmp)
   354  
   355  	// Sort the temp by the ascending order
   356  	hs.Sort()
   357  	for i := range hs.Keys {
   358  		if hs.Vals[i] != "" {
   359  			canonicalQueryString += "&" + hs.Keys[i] + "=" + url.QueryEscape(hs.Vals[i])
   360  		} else {
   361  			canonicalQueryString += "&" + hs.Keys[i] + "="
   362  		}
   363  	}
   364  	canonicalQueryString = strings.Replace(canonicalQueryString, "+", "%20", -1)
   365  	canonicalQueryString = strings.Replace(canonicalQueryString, "*", "%2A", -1)
   366  	canonicalQueryString = strings.Replace(canonicalQueryString, "%7E", "~", -1)
   367  
   368  	if canonicalQueryString != "" {
   369  		canonicalQueryString = strings.TrimLeft(canonicalQueryString, "&")
   370  	}
   371  	return canonicalQueryString
   372  }
   373  
   374  /**
   375   * Parse filter into a form string
   376   * @param filter object
   377   * @return the string
   378   */
   379  func ToForm(filter map[string]interface{}) (_result *string) {
   380  	tmp := make(map[string]interface{})
   381  	byt, _ := json.Marshal(filter)
   382  	d := json.NewDecoder(bytes.NewReader(byt))
   383  	d.UseNumber()
   384  	_ = d.Decode(&tmp)
   385  
   386  	result := make(map[string]*string)
   387  	for key, value := range tmp {
   388  		filterValue := reflect.ValueOf(value)
   389  		flatRepeatedList(filterValue, result, key)
   390  	}
   391  
   392  	m := util.AnyifyMapValue(result)
   393  	return util.ToFormString(m)
   394  }
   395  
   396  func flatRepeatedList(dataValue reflect.Value, result map[string]*string, prefix string) {
   397  	if !dataValue.IsValid() {
   398  		return
   399  	}
   400  
   401  	dataType := dataValue.Type()
   402  	if dataType.Kind().String() == "slice" {
   403  		handleRepeatedParams(dataValue, result, prefix)
   404  	} else if dataType.Kind().String() == "map" {
   405  		handleMap(dataValue, result, prefix)
   406  	} else {
   407  		result[prefix] = tea.String(fmt.Sprintf("%v", dataValue.Interface()))
   408  	}
   409  }
   410  
   411  func handleRepeatedParams(repeatedFieldValue reflect.Value, result map[string]*string, prefix string) {
   412  	if repeatedFieldValue.IsValid() && !repeatedFieldValue.IsNil() {
   413  		for m := 0; m < repeatedFieldValue.Len(); m++ {
   414  			elementValue := repeatedFieldValue.Index(m)
   415  			key := prefix + "." + strconv.Itoa(m+1)
   416  			fieldValue := reflect.ValueOf(elementValue.Interface())
   417  			if fieldValue.Kind().String() == "map" {
   418  				handleMap(fieldValue, result, key)
   419  			} else {
   420  				result[key] = tea.String(fmt.Sprintf("%v", fieldValue.Interface()))
   421  			}
   422  		}
   423  	}
   424  }
   425  
   426  func handleMap(valueField reflect.Value, result map[string]*string, prefix string) {
   427  	if valueField.IsValid() && valueField.String() != "" {
   428  		valueFieldType := valueField.Type()
   429  		if valueFieldType.Kind().String() == "map" {
   430  			var byt []byte
   431  			byt, _ = json.Marshal(valueField.Interface())
   432  			cache := make(map[string]interface{})
   433  			d := json.NewDecoder(bytes.NewReader(byt))
   434  			d.UseNumber()
   435  			_ = d.Decode(&cache)
   436  			for key, value := range cache {
   437  				pre := ""
   438  				if prefix != "" {
   439  					pre = prefix + "." + key
   440  				} else {
   441  					pre = key
   442  				}
   443  				fieldValue := reflect.ValueOf(value)
   444  				flatRepeatedList(fieldValue, result, pre)
   445  			}
   446  		}
   447  	}
   448  }
   449  
   450  /**
   451   * Get timestamp
   452   * @return the timestamp string
   453   */
   454  func GetTimestamp() (_result *string) {
   455  	gmt := time.FixedZone("GMT", 0)
   456  	return tea.String(time.Now().In(gmt).Format("2006-01-02T15:04:05Z"))
   457  }
   458  
   459  /**
   460   * Parse filter into a object which's type is map[string]string
   461   * @param filter query param
   462   * @return the object
   463   */
   464  func Query(filter interface{}) (_result map[string]*string) {
   465  	tmp := make(map[string]interface{})
   466  	byt, _ := json.Marshal(filter)
   467  	d := json.NewDecoder(bytes.NewReader(byt))
   468  	d.UseNumber()
   469  	_ = d.Decode(&tmp)
   470  
   471  	result := make(map[string]*string)
   472  	for key, value := range tmp {
   473  		filterValue := reflect.ValueOf(value)
   474  		flatRepeatedList(filterValue, result, key)
   475  	}
   476  
   477  	return result
   478  }
   479  
   480  /**
   481   * Get signature according to signedParams, method and secret
   482   * @param signedParams params which need to be signed
   483   * @param method http method e.g. GET
   484   * @param secret AccessKeySecret
   485   * @return the signature
   486   */
   487  func GetRPCSignature(signedParams map[string]*string, method *string, secret *string) (_result *string) {
   488  	stringToSign := buildRpcStringToSign(signedParams, tea.StringValue(method))
   489  	signature := sign(stringToSign, tea.StringValue(secret), "&")
   490  	return tea.String(signature)
   491  }
   492  
   493  /**
   494   * Parse array into a string with specified style
   495   * @param array the array
   496   * @param prefix the prefix string
   497   * @style specified style e.g. repeatList
   498   * @return the string
   499   */
   500  func ArrayToStringWithSpecifiedStyle(array interface{}, prefix *string, style *string) (_result *string) {
   501  	if tea.BoolValue(util.IsUnset(array)) {
   502  		return tea.String("")
   503  	}
   504  
   505  	sty := tea.StringValue(style)
   506  	if sty == "repeatList" {
   507  		tmp := map[string]interface{}{
   508  			tea.StringValue(prefix): array,
   509  		}
   510  		return flatRepeatList(tmp)
   511  	} else if sty == "simple" || sty == "spaceDelimited" || sty == "pipeDelimited" {
   512  		return flatArray(array, sty)
   513  	} else if sty == "json" {
   514  		return util.ToJSONString(array)
   515  	}
   516  	return tea.String("")
   517  }
   518  
   519  func ParseToMap(in interface{}) map[string]interface{} {
   520  	if tea.BoolValue(util.IsUnset(in)) {
   521  		return nil
   522  	}
   523  
   524  	tmp := make(map[string]interface{})
   525  	byt, _ := json.Marshal(in)
   526  	d := json.NewDecoder(bytes.NewReader(byt))
   527  	d.UseNumber()
   528  	err := d.Decode(&tmp)
   529  	if err != nil {
   530  		return nil
   531  	}
   532  	return tmp
   533  }
   534  
   535  func flatRepeatList(filter map[string]interface{}) (_result *string) {
   536  	tmp := make(map[string]interface{})
   537  	byt, _ := json.Marshal(filter)
   538  	d := json.NewDecoder(bytes.NewReader(byt))
   539  	d.UseNumber()
   540  	_ = d.Decode(&tmp)
   541  
   542  	result := make(map[string]*string)
   543  	for key, value := range tmp {
   544  		filterValue := reflect.ValueOf(value)
   545  		flatRepeatedList(filterValue, result, key)
   546  	}
   547  
   548  	res := make(map[string]string)
   549  	for k, v := range result {
   550  		res[k] = tea.StringValue(v)
   551  	}
   552  	hs := newSorter(res)
   553  
   554  	hs.Sort()
   555  
   556  	// Get the canonicalizedOSSHeaders
   557  	t := ""
   558  	for i := range hs.Keys {
   559  		if i == len(hs.Keys)-1 {
   560  			t += hs.Keys[i] + "=" + hs.Vals[i]
   561  		} else {
   562  			t += hs.Keys[i] + "=" + hs.Vals[i] + "&&"
   563  		}
   564  	}
   565  	return tea.String(t)
   566  }
   567  
   568  func flatArray(array interface{}, sty string) *string {
   569  	t := reflect.ValueOf(array)
   570  	strs := make([]string, 0)
   571  	for i := 0; i < t.Len(); i++ {
   572  		tmp := t.Index(i)
   573  		if tmp.Kind() == reflect.Ptr || tmp.Kind() == reflect.Interface {
   574  			tmp = tmp.Elem()
   575  		}
   576  
   577  		if tmp.Kind() == reflect.Ptr {
   578  			tmp = tmp.Elem()
   579  		}
   580  		if tmp.Kind() == reflect.String {
   581  			strs = append(strs, tmp.String())
   582  		} else {
   583  			inter := tmp.Interface()
   584  			byt, _ := json.Marshal(inter)
   585  			strs = append(strs, string(byt))
   586  		}
   587  	}
   588  	str := ""
   589  	if sty == "simple" {
   590  		str = strings.Join(strs, ",")
   591  	} else if sty == "spaceDelimited" {
   592  		str = strings.Join(strs, " ")
   593  	} else if sty == "pipeDelimited" {
   594  		str = strings.Join(strs, "|")
   595  	}
   596  	return tea.String(str)
   597  }
   598  
   599  func buildRpcStringToSign(signedParam map[string]*string, method string) (stringToSign string) {
   600  	signParams := make(map[string]string)
   601  	for key, value := range signedParam {
   602  		signParams[key] = tea.StringValue(value)
   603  	}
   604  
   605  	stringToSign = getUrlFormedMap(signParams)
   606  	stringToSign = strings.Replace(stringToSign, "+", "%20", -1)
   607  	stringToSign = strings.Replace(stringToSign, "*", "%2A", -1)
   608  	stringToSign = strings.Replace(stringToSign, "%7E", "~", -1)
   609  	stringToSign = url.QueryEscape(stringToSign)
   610  	stringToSign = method + "&%2F&" + stringToSign
   611  	return
   612  }
   613  
   614  func getUrlFormedMap(source map[string]string) (urlEncoded string) {
   615  	urlEncoder := url.Values{}
   616  	for key, value := range source {
   617  		urlEncoder.Add(key, value)
   618  	}
   619  	urlEncoded = urlEncoder.Encode()
   620  	return
   621  }
   622  
   623  func sign(stringToSign, accessKeySecret, secretSuffix string) string {
   624  	secret := accessKeySecret + secretSuffix
   625  	signedBytes := shaHmac1(stringToSign, secret)
   626  	signedString := base64.StdEncoding.EncodeToString(signedBytes)
   627  	return signedString
   628  }
   629  
   630  func shaHmac1(source, secret string) []byte {
   631  	key := []byte(secret)
   632  	hmac := hmac.New(sha1.New, key)
   633  	hmac.Write([]byte(source))
   634  	return hmac.Sum(nil)
   635  }
   636  

View as plain text