This commit is contained in:
2025-07-28 01:46:39 +08:00
parent b03129667a
commit 357639462a
219 changed files with 21634 additions and 8138 deletions

View File

@@ -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
}