v0.1
This commit is contained in:
@@ -5,10 +5,40 @@ import (
|
||||
"crypto/md5"
|
||||
"crypto/sha256"
|
||||
"encoding/base64"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
// appendSignDataString 拼接待签名字符串
|
||||
func appendSignDataString(httpMethod, accept, contentMD5, contentType, date, headers, pathAndParameters string) string {
|
||||
if accept == "" {
|
||||
accept = "*/*"
|
||||
}
|
||||
if contentType == "" {
|
||||
contentType = "application/json; charset=UTF-8"
|
||||
}
|
||||
// 前四项
|
||||
signStr := httpMethod + "\n" + accept + "\n" + contentMD5 + "\n" + contentType + "\n"
|
||||
// 处理 date
|
||||
if date == "" {
|
||||
signStr += "\n"
|
||||
} else {
|
||||
signStr += date + "\n"
|
||||
}
|
||||
// 处理 headers
|
||||
if headers == "" {
|
||||
signStr += pathAndParameters
|
||||
} else {
|
||||
signStr += headers + "\n" + pathAndParameters
|
||||
}
|
||||
return signStr
|
||||
}
|
||||
|
||||
// generateSignature 生成e签宝API请求签名
|
||||
// 使用HMAC-SHA256算法对请求参数进行签名
|
||||
//
|
||||
@@ -24,8 +54,8 @@ import (
|
||||
//
|
||||
// 返回: Base64编码的签名字符串
|
||||
func generateSignature(appSecret, httpMethod, accept, contentMD5, contentType, date, headers, pathAndParameters string) string {
|
||||
// 构建待签名字符串,按照e签宝API规范拼接
|
||||
signStr := httpMethod + "\n" + accept + "\n" + contentMD5 + "\n" + contentType + "\n" + date + "\n" + headers + pathAndParameters
|
||||
// 构建待签名字符串,按照e签宝API规范拼接(兼容Python实现细节)
|
||||
signStr := appendSignDataString(httpMethod, accept, contentMD5, contentType, date, headers, pathAndParameters)
|
||||
|
||||
// 使用HMAC-SHA256计算签名
|
||||
h := hmac.New(sha256.New, []byte(appSecret))
|
||||
@@ -102,3 +132,66 @@ func generateFileName(baseName, extension string) string {
|
||||
func calculateExpireTime(days int) int64 {
|
||||
return time.Now().AddDate(0, 0, days).UnixMilli()
|
||||
}
|
||||
|
||||
// verifySignature 验证e签宝回调签名
|
||||
func VerifySignature(callbackData interface{}, headers map[string]string, queryParams map[string]string, appSecret string) error {
|
||||
// 1. 获取签名相关参数
|
||||
signature, ok := headers["X-Tsign-Open-Signature"]
|
||||
if !ok {
|
||||
return fmt.Errorf("缺少签名头: X-Tsign-Open-Signature")
|
||||
}
|
||||
|
||||
timestamp, ok := headers["X-Tsign-Open-Timestamp"]
|
||||
if !ok {
|
||||
return fmt.Errorf("缺少时间戳头: X-Tsign-Open-Timestamp")
|
||||
}
|
||||
|
||||
// 2. 构建查询参数字符串
|
||||
var queryKeys []string
|
||||
for key := range queryParams {
|
||||
queryKeys = append(queryKeys, key)
|
||||
}
|
||||
sort.Strings(queryKeys) // 按ASCII码升序排序
|
||||
|
||||
var queryValues []string
|
||||
for _, key := range queryKeys {
|
||||
queryValues = append(queryValues, queryParams[key])
|
||||
}
|
||||
queryString := strings.Join(queryValues, "")
|
||||
|
||||
// 3. 获取请求体数据
|
||||
bodyData, err := getRequestBodyString(callbackData)
|
||||
if err != nil {
|
||||
return fmt.Errorf("获取请求体数据失败: %w", err)
|
||||
}
|
||||
|
||||
// 4. 构建验签数据
|
||||
data := timestamp + queryString + bodyData
|
||||
|
||||
// 5. 计算签名
|
||||
expectedSignature := calculateSignature(data, appSecret)
|
||||
|
||||
// 6. 比较签名
|
||||
if strings.ToLower(expectedSignature) != strings.ToLower(signature) {
|
||||
return fmt.Errorf("签名验证失败")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// calculateSignature 计算HMAC-SHA256签名
|
||||
func calculateSignature(data, secret string) string {
|
||||
h := hmac.New(sha256.New, []byte(secret))
|
||||
h.Write([]byte(data))
|
||||
return strings.ToUpper(hex.EncodeToString(h.Sum(nil)))
|
||||
}
|
||||
|
||||
// getRequestBodyString 获取请求体字符串
|
||||
func getRequestBodyString(callbackData interface{}) (string, error) {
|
||||
// 将map转换为JSON字符串
|
||||
jsonBytes, err := json.Marshal(callbackData)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("JSON序列化失败: %w", err)
|
||||
}
|
||||
return string(jsonBytes), nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user