76 lines
1.6 KiB
Go
76 lines
1.6 KiB
Go
package weipinshang_api
|
||
|
||
import (
|
||
"encoding/json"
|
||
"fmt"
|
||
"sort"
|
||
"strconv"
|
||
"strings"
|
||
)
|
||
|
||
func SortedString(data any) string {
|
||
// 1. 序列化成 JSON
|
||
dataBytes, err := json.Marshal(data)
|
||
if err != nil {
|
||
return ""
|
||
}
|
||
|
||
// 2. 反序列化成 map[string]interface{}
|
||
var tmp map[string]interface{}
|
||
if err = json.Unmarshal(dataBytes, &tmp); err != nil {
|
||
return ""
|
||
}
|
||
|
||
// 3. 提取并排序 keys
|
||
keys := make([]string, 0, len(tmp))
|
||
for k := range tmp {
|
||
keys = append(keys, k)
|
||
}
|
||
sort.Strings(keys)
|
||
|
||
// 4. 构建键值对字符串
|
||
var sortedParams []string
|
||
for _, key := range keys {
|
||
if key == "hmac" {
|
||
continue // 跳过 hmac 字段
|
||
}
|
||
|
||
value := tmp[key]
|
||
strValue, err := valueToString(value)
|
||
if err != nil {
|
||
return ""
|
||
}
|
||
sortedParams = append(sortedParams, fmt.Sprintf("%s=%s", key, strValue))
|
||
}
|
||
return strings.Join(sortedParams, "&")
|
||
}
|
||
|
||
// valueToString 将任意 JSON 值转换为字符串
|
||
func valueToString(v interface{}) (string, error) {
|
||
switch i := v.(type) {
|
||
case string:
|
||
return i, nil
|
||
case bool:
|
||
return strconv.FormatBool(i), nil
|
||
case float64:
|
||
// 判断是否是整数(如 2.0 → "2")
|
||
if i == float64(int64(i)) {
|
||
return strconv.FormatInt(int64(i), 10), nil
|
||
}
|
||
return strconv.FormatFloat(i, 'f', -1, 64), nil
|
||
case json.Number:
|
||
return i.String(), nil // 如果使用 json.Number,直接返回其字符串形式
|
||
case nil:
|
||
return "", nil
|
||
case map[string]interface{}, []interface{}:
|
||
// 如果是嵌套结构,重新序列化成 JSON
|
||
bytes, err := json.Marshal(i)
|
||
if err != nil {
|
||
return "", err
|
||
}
|
||
return string(bytes), nil
|
||
default:
|
||
return "", fmt.Errorf("unsupported type: %T", i)
|
||
}
|
||
}
|