170 lines
3.2 KiB
Go
170 lines
3.2 KiB
Go
package weixin
|
|
|
|
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)
|
|
}
|