🐛 fix bug
This commit is contained in:
190
utils/wx_msg.go
Normal file
190
utils/wx_msg.go
Normal file
@@ -0,0 +1,190 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"crypto/sha1"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"github.com/pkg/errors"
|
||||
"miniapp/global"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"sort"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
//type wxMsg struct{}
|
||||
//
|
||||
//func WxMsgUtils() *wxMsg {
|
||||
// return &wxMsg{}
|
||||
//}
|
||||
|
||||
type Wechat struct {
|
||||
appID string
|
||||
secret string
|
||||
templateID string
|
||||
accessToken *AccessToken
|
||||
sync.Mutex
|
||||
}
|
||||
|
||||
type OpenIDResponse struct {
|
||||
Openid string `json:"openid"`
|
||||
SessionKey string `json:"session_key"`
|
||||
Unionid string `json:"unionid"`
|
||||
WxErr
|
||||
}
|
||||
|
||||
type CheckTokenRequest struct {
|
||||
Signature string `json:"signature"`
|
||||
Timestamp string `json:"timestamp"`
|
||||
Nonce string `json:"nonce"`
|
||||
Echostr string `json:"echostr"`
|
||||
}
|
||||
|
||||
type WxErr struct {
|
||||
Errcode int `json:"errcode"`
|
||||
Errmsg string `json:"errmsg"`
|
||||
}
|
||||
|
||||
type AccessToken struct {
|
||||
AccessToken string `json:"access_token"`
|
||||
ExpiresIn int64 `json:"expires_in"`
|
||||
WxErr
|
||||
}
|
||||
|
||||
type SendRequest struct {
|
||||
Touser string `json:"touser"`
|
||||
Page string `json:"page"`
|
||||
Data Message `json:"data"`
|
||||
EmphasisKeyword string `json:"emphasis_keyword"`
|
||||
}
|
||||
|
||||
type Message map[string]interface{}
|
||||
|
||||
func (w *Wechat) SendMsg(req SendRequest) (err error) {
|
||||
token, err := w.GetAccessToken()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
api, err := TokenAPI("https://api.weixin.qq.com/cgi-bin/message/wxopen/template/send", token)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
for key := range req.Data {
|
||||
req.Data[key] = Message{"value": req.Data[key]}
|
||||
}
|
||||
body := map[string]interface{}{
|
||||
"touser": "o9Fq_6_cYKvOWnyUM3McC11hWsTI",
|
||||
"template_id": global.GVA_CONFIG.MiniApp.TemplateID,
|
||||
"page": "/pages/index/todo",
|
||||
"data": req.Data,
|
||||
"emphasis_keyword": req.EmphasisKeyword,
|
||||
}
|
||||
|
||||
b, err := json.Marshal(body)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
res, err := http.Post(api, "application/json", strings.NewReader(string(b)))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer res.Body.Close()
|
||||
|
||||
if res.StatusCode != 200 {
|
||||
err = errors.New("WECHAT_SERVER_ERROR")
|
||||
return err
|
||||
}
|
||||
|
||||
var resp WxErr
|
||||
if err = json.NewDecoder(res.Body).Decode(&resp); err != nil {
|
||||
return err
|
||||
}
|
||||
if resp.Errcode != 0 {
|
||||
return errors.New(resp.Errmsg)
|
||||
}
|
||||
return nil
|
||||
|
||||
}
|
||||
|
||||
func (w *Wechat) GetAccessToken() (token string, err error) {
|
||||
w.Lock()
|
||||
defer w.Unlock()
|
||||
if w.accessToken == nil || w.accessToken.ExpiresIn < time.Now().Unix() {
|
||||
for i := 0; i < 3; i++ {
|
||||
err = w.getAccessToken()
|
||||
if err == nil {
|
||||
break
|
||||
}
|
||||
time.Sleep(time.Second)
|
||||
}
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
token = w.accessToken.AccessToken
|
||||
return
|
||||
}
|
||||
|
||||
func (w *Wechat) CheckSignature(req CheckTokenRequest) (err error) {
|
||||
if sig := w.sortSha1(req.Timestamp, req.Nonce, req.Echostr); sig != req.Signature {
|
||||
err = errors.New("check signature failed.")
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func TokenAPI(api, token string) (string, error) {
|
||||
u, err := url.Parse(api)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
query := u.Query()
|
||||
query.Set("access_token", token)
|
||||
u.RawQuery = query.Encode()
|
||||
|
||||
return u.String(), nil
|
||||
}
|
||||
|
||||
func (w *Wechat) getAccessToken() (err error) {
|
||||
urls, err := url.Parse("https://api.weixin.qq.com/cgi-bin/token")
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
query := urls.Query()
|
||||
query.Set("appid", w.appID)
|
||||
query.Set("secret", w.secret)
|
||||
query.Set("grant_type", "client_credential")
|
||||
|
||||
urls.RawQuery = query.Encode()
|
||||
|
||||
res, err := http.Get(urls.String())
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
defer res.Body.Close()
|
||||
|
||||
if res.StatusCode != 200 {
|
||||
return errors.New("wechat internal server error.")
|
||||
}
|
||||
|
||||
var token AccessToken
|
||||
if err = json.NewDecoder(res.Body).Decode(&token); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if token.Errcode != 0 {
|
||||
return errors.New(token.Errmsg)
|
||||
}
|
||||
w.accessToken.AccessToken = token.AccessToken
|
||||
w.accessToken.ExpiresIn = token.ExpiresIn
|
||||
return
|
||||
}
|
||||
|
||||
func (w *Wechat) sortSha1(s ...string) string {
|
||||
sort.Strings(s)
|
||||
h := sha1.New()
|
||||
h.Write([]byte(strings.Join(s, "")))
|
||||
return fmt.Sprintf("%x", h.Sum(nil))
|
||||
}
|
Reference in New Issue
Block a user