最近对接了多个第三方平台,但是都没有提供go的sdk,所以把签名流程做了个整理,以便将来复用。
 

一、常用签名流程

1、先将需要参与签名的键值对,根据键名称 ASCII 码排序
2、获取 value 值,拼接成一行
3、使用密钥,用 HmacSHA256 对拼接的字符串进行加密
4、加密后 的密文进行 base64 编码,生成加密的字符串

package main

import (
	"crypto/hmac"
	"crypto/sha256"
	"encoding/base64"
	"fmt"
	"reflect"
	"sort"
)

type SignTool struct {
	SecretKey string
}

func NewSignTool(secret string) *SignTool {
	return &SignTool{
		SecretKey: secret,
	}
}

func (s *SignTool) Sign(obj interface{}) string {
	signmap := map[string]interface{}{}
	valueOfObj := reflect.ValueOf(obj)
	for i := 0; i < valueOfObj.NumField(); i++ {
		signmap[valueOfObj.Type().Field(i).Name] = valueOfObj.Field(i)
	}

	//进行键排序
	keys := make([]string, len(signmap))
	j := 0
	for k := range signmap {
		keys[j] = k
		j++
	}

	sort.Strings(keys)
	//获取 value 值,拼接成一行
	valueStr := ""
	for _, k := range keys {
		if v, ok := signmap[k]; ok {
			valueStr = fmt.Sprintf("%s%v", valueStr, v)
		}
	}
	//把 secretAccessKey 做为 key,用 HmacSHA256 对拼接的字符串
	//加密后 的密文进行 base64 编码,生成加密的字符串
	return hmacSha256(valueStr, s.SecretKey)
}

func hmacSha256(msg, pwd string) string {
	h := hmac.New(sha256.New, []byte(pwd))
	h.Write([]byte(msg))
	return base64.StdEncoding.EncodeToString(h.Sum(nil))
}

// 测试签名的结构体
type Book struct {
	Name   string  `json:"name"`
	Price  float32 `json:"price"`
	Number int     `json:"number"`
}

// 测试签名
func main() {
	signTool := NewSignTool("abc")
	book := Book{
		Name:   "我和我的祖国",
		Price:  100.00,
		Number: 20,
	}
	sign := signTool.Sign(book)
	fmt.Println("签名结果: ", sign)
}