gosdk/util/params.go

170 lines
3.2 KiB
Go

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(`<xml>`)
for k, v := range p {
buf.WriteString(`<`)
buf.WriteString(k)
buf.WriteString(`><![CDATA[`)
buf.WriteString(v)
buf.WriteString(`]]></`)
buf.WriteString(k)
buf.WriteString(`>`)
}
buf.WriteString(`</xml>`)
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)
}