package util import ( "bytes" "crypto/hmac" "crypto/md5" "crypto/sha256" "encoding/hex" "encoding/xml" "fmt" "io" "sort" "strconv" "strings" ) type Params map[string]string func NewParams() Params { return make(Params) } func (p Params) Set(k string, v interface{}) { p[k] = fmt.Sprintf("%v", v) } func (p Params) GetString(k string) string { s, _ := p[k] return s } func (p Params) GetUint64(k string) uint64 { s, _ := strconv.ParseUint(p[k], 10, 64) return s } func (p Params) GetInt64(k string) int64 { i, _ := strconv.ParseInt(p.GetString(k), 10, 64) return i } func (p Params) GetInt(k string) int64 { i, _ := strconv.ParseInt(p.GetString(k), 10, 64) return i } func (p Params) GetFloat64(k string) float64 { f, _ := strconv.ParseFloat(p.GetString(k), 64) return f } func (p Params) GetBool(k string) bool { b, _ := strconv.ParseBool(p.GetString(k)) return b } // XML解码 func (p Params) Decode(body []byte) (err error) { defer func() { if e := recover(); e != nil { err = fmt.Errorf("%v", e) } }() var ( d *xml.Decoder start *xml.StartElement ) buf := bytes.NewBuffer(body) d = xml.NewDecoder(buf) for { tok, err := d.Token() if err != nil { break } switch t := tok.(type) { case xml.StartElement: start = &t case xml.CharData: if t = bytes.TrimSpace(t); len(t) > 0 { p.Set(start.Name.Local, string(t)) } } } return nil } // XML编码 func (p Params) Encode() []byte { var buf bytes.Buffer buf.WriteString(``) for k, v := range p { buf.WriteString(`<`) buf.WriteString(k) buf.WriteString(`>`) } buf.WriteString(``) return buf.Bytes() } // 验证签名 func (p Params) CheckSign(key string) bool { return p.GetString("sign") == p.SignMd5(key) } // 生成签名 func (p Params) getSignStr(key string) string { var keys = make([]string, 0, len(p)) for k, _ := range p { if k != "sign" { keys = append(keys, k) } } sort.Strings(keys) var buf bytes.Buffer for _, k := range keys { if len(p.GetString(k)) > 0 { buf.WriteString(k) buf.WriteString(`=`) buf.WriteString(p.GetString(k)) buf.WriteString(`&`) } } buf.WriteString(`key=`) buf.WriteString(key) return buf.String() } func (p Params) getQySignStr(secret string) string { keys := []string{"act_name", "mch_billno", "mch_id", "nonce_str", "re_openid", "total_amount", "wxappid"} sort.Strings(keys) var buf bytes.Buffer for _, k := range keys { buf.WriteString(k) buf.WriteString(`=`) buf.WriteString(p.GetString(k)) buf.WriteString(`&`) } buf.WriteString(`secret=`) buf.WriteString(secret) return buf.String() } // 生成签名 func (p Params) QySignMd5(secret string) string { sum := md5.Sum([]byte(p.getQySignStr(secret))) str := hex.EncodeToString(sum[:]) return strings.ToUpper(str) } // 生成签名 func (p Params) SignMd5(key string) string { sum := md5.Sum([]byte(p.getSignStr(key))) str := hex.EncodeToString(sum[:]) return strings.ToUpper(str) } // 生成签名 func (p Params) SignHmacSha256(key string) string { h := hmac.New(sha256.New, []byte(key)) io.WriteString(h, p.getSignStr(key)) str := hex.EncodeToString(h.Sum(nil)) return strings.ToUpper(str) }