package paymentutil import ( "crypto/hmac" "crypto/md5" "crypto/sha256" "encoding/hex" "fmt" "net/url" "sort" "strings" ) func WechatV2Sign(values map[string]string, key, signType string) string { keys := make([]string, 0, len(values)) for k, v := range values { if k != "sign" && v != "" { keys = append(keys, k) } } sort.Strings(keys) parts := make([]string, 0, len(keys)) for _, k := range keys { parts = append(parts, k+"="+values[k]) } raw := strings.Join(parts, "&") + "&key=" + key if strings.EqualFold(signType, "HMAC-SHA256") { return HMACSHA256Hex([]byte(raw), key, true) } sum := md5.Sum([]byte(raw)) return strings.ToUpper(hex.EncodeToString(sum[:])) } func MD5Canonical(values map[string]any, secret string) string { keys := make([]string, 0, len(values)) for key, value := range values { if key != "sign" && value != nil && fmt.Sprint(value) != "" { keys = append(keys, key) } } sort.Strings(keys) query := url.Values{} for _, key := range keys { query.Set(key, fmt.Sprint(values[key])) } sum := md5.Sum([]byte(query.Encode() + "&key=" + secret)) return strings.ToUpper(hex.EncodeToString(sum[:])) } func HMACSHA256Hex(raw []byte, secret string, upper bool) string { h := hmac.New(sha256.New, []byte(secret)) _, _ = h.Write(raw) result := hex.EncodeToString(h.Sum(nil)) if upper { return strings.ToUpper(result) } return result }