123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130 |
- package wx
- import (
- "bytes"
- "crypto/md5"
- "crypto/sha1"
- "encoding/json"
- "fmt"
- "io/ioutil"
- "math/rand"
- "net/http"
- "net/url"
- "sort"
- "strings"
- "sync"
- "time"
- )
- type TicketResponse struct {
- ErrCode int `json:"errcode"`
- ErrMsg string `json:"errmsg"`
- Ticket string `json:"ticket"`
- ExpiresIn int64 `json:"expires_in"`
- }
- type SignPackage map[string]interface{}
- type JsSdk interface {
- GenerateNoncestr(length int) string
- GetTicket(token string) (*TicketResponse, error)
- ComputeSignature(token, ticket, signUrl string) (SignPackage, error)
- ComputePaySignature(params PkgComponents, apikey string) string
- }
- type JsSdkDefault struct {
- }
- func NewJsSdk() JsSdk {
- return &JsSdkDefault{}
- }
- var chars string = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
- var bufPool = sync.Pool{
- New: func() interface{} {
- return new(bytes.Buffer)
- },
- }
- func (sdk *JsSdkDefault) GenerateNoncestr(length int) string {
- buf := bufPool.Get().(*bytes.Buffer)
- defer func() {
- buf.Reset()
- bufPool.Put(buf)
- }()
- var ridx int
- upBound := len(chars)
- for i := 0; i < length; i++ {
- ridx = rand.Intn(upBound)
- buf.WriteByte(chars[ridx])
- }
- return buf.String()
- }
- func (sdk *JsSdkDefault) GetTicket(accessToken string) (*TicketResponse, error) {
- serviceUrl := "https://api.weixin.qq.com/cgi-bin/ticket/getticket"
- reqParams := url.Values{}
- reqParams.Add("type", "jsapi")
- reqParams.Add("access_token", accessToken)
- serviceUrl += "?" + reqParams.Encode()
- res, err := http.Get(serviceUrl)
- if err != nil {
- return nil, err
- }
- defer res.Body.Close()
- bytesBuf, err := ioutil.ReadAll(res.Body)
- if err != nil {
- return nil, err
- }
- ticketRes := &TicketResponse{}
- err = json.Unmarshal(bytesBuf, ticketRes)
- if err != nil {
- return nil, err
- }
- return ticketRes, nil
- }
- func (sdk *JsSdkDefault) ComputeSignature(accessToken, ticket, signUrl string) (SignPackage, error) {
- timestamp := time.Now().Unix()
- noncestr := sdk.GenerateNoncestr(16)
- params := PkgComponents{
- "jsapi_ticket": ticket,
- "noncestr": noncestr,
- "timestamp": fmt.Sprintf("%d", timestamp),
- "url": signUrl,
- }
- rawStr := params.buildRawQueryString()
- signature := sha1.Sum([]byte(rawStr))
- return SignPackage{
- "access_token": accessToken,
- "ticket": ticket,
- "noncestr": noncestr,
- "timestamp": timestamp,
- "signature": fmt.Sprintf("%x", signature),
- }, nil
- }
- func (sdk *JsSdkDefault) ComputePaySignature(components PkgComponents, apikey string) string {
- rawStr := components.buildRawQueryString() + "&key=" + apikey
- signature := md5.Sum([]byte(rawStr))
- return strings.ToUpper(fmt.Sprintf("%x", signature))
- }
- type PkgComponents map[string]string
- func (pc PkgComponents) buildRawQueryString() string {
- qstr := ""
- keys := []string{}
- for key := range pc {
- keys = append(keys, key)
- }
- sort.Strings(keys)
- for _, key := range keys {
- if pc[key] == "" {
- continue
- }
- qstr += key + "=" + pc[key] + "&"
- }
- return qstr[0 : len(qstr)-1]
- }
|