108 lines
3.1 KiB
Go
108 lines
3.1 KiB
Go
|
package wechat
|
|||
|
|
|||
|
import (
|
|||
|
"crypto/sha1"
|
|||
|
"encoding/hex"
|
|||
|
"encoding/json"
|
|||
|
"errors"
|
|||
|
"fmt"
|
|||
|
"github.com/silenceper/wechat/v2"
|
|||
|
"github.com/silenceper/wechat/v2/cache"
|
|||
|
offConfig "github.com/silenceper/wechat/v2/officialaccount/config"
|
|||
|
"github.com/silenceper/wechat/v2/officialaccount/oauth"
|
|||
|
"kefu/tools"
|
|||
|
"log"
|
|||
|
"net/url"
|
|||
|
"sort"
|
|||
|
)
|
|||
|
|
|||
|
type AccessToken struct {
|
|||
|
AccessToken string `json:"access_token"`
|
|||
|
ExpiresIn uint `json:"expires_in"`
|
|||
|
}
|
|||
|
type Ticket struct {
|
|||
|
Ticket string `json:"ticket"`
|
|||
|
ExpireSeconds uint `json:"expire_seconds"`
|
|||
|
Url string `json:"url"`
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
获取access_token
|
|||
|
*/
|
|||
|
func GetAccessToken(appId, appSecret string) *AccessToken {
|
|||
|
url := fmt.Sprintf(
|
|||
|
"https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=%s&secret=%s",
|
|||
|
appId,
|
|||
|
appSecret)
|
|||
|
accessToken := tools.Get(url)
|
|||
|
token := &AccessToken{}
|
|||
|
json.Unmarshal([]byte(accessToken), token)
|
|||
|
return token
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
获取临时二维码ticket
|
|||
|
*/
|
|||
|
func CreateQrImgUrl(accessToken, accountInfo string) {
|
|||
|
api := "https://api.weixin.qq.com/cgi-bin/qrcode/create?access_token=" + accessToken
|
|||
|
data := fmt.Sprintf(
|
|||
|
"{\"expire_seconds\": 604800, \"action_name\": \"QR_STR_SCENE\", \"action_info\": {\"scene\": {\"scene_str\": \"%s\"}}}",
|
|||
|
accountInfo)
|
|||
|
result, _ := tools.Post(api, "application/json;charset=utf-8", []byte(data))
|
|||
|
ticket := &Ticket{}
|
|||
|
json.Unmarshal([]byte(result), ticket)
|
|||
|
imgUrl := "https://mp.weixin.qq.com/cgi-bin/showqrcode?ticket=" + url.QueryEscape(ticket.Ticket)
|
|||
|
log.Println(ticket.Ticket, imgUrl)
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
验证签名
|
|||
|
*/
|
|||
|
func CheckWechatSign(token, signature, timestamp, nonce, echostr string) (string, error) {
|
|||
|
//将token、timestamp、nonce三个参数进行字典序排序
|
|||
|
var tempArray = []string{token, timestamp, nonce}
|
|||
|
sort.Strings(tempArray)
|
|||
|
//将三个参数字符串拼接成一个字符串进行sha1加密
|
|||
|
var sha1String string = ""
|
|||
|
for _, v := range tempArray {
|
|||
|
sha1String += v
|
|||
|
}
|
|||
|
h := sha1.New()
|
|||
|
h.Write([]byte(sha1String))
|
|||
|
sha1String = hex.EncodeToString(h.Sum([]byte("")))
|
|||
|
//获得加密后的字符串可与signature对比
|
|||
|
if sha1String == signature {
|
|||
|
return echostr, nil
|
|||
|
}
|
|||
|
return "", errors.New("微信API验证失败")
|
|||
|
}
|
|||
|
|
|||
|
/**
|
|||
|
公众号网页授权封装函数
|
|||
|
所需参数解释:
|
|||
|
appid,appsecret,token这三个是公众号后台设置的
|
|||
|
code是网页授权回跳链接带回来的,code作为换取access_token的票据,每次用户授权带上的 code 将不一样,code只能使用一次,5分钟未被使用自动过期。
|
|||
|
cache是内存形式存储access_token cache := cache2.NewMemory()
|
|||
|
*/
|
|||
|
func GetWechatOfficialNickname(appId, appSecret, token, code string, cache cache.Cache) (userinfo oauth.UserInfo, err error) {
|
|||
|
cfg := &offConfig.Config{
|
|||
|
AppID: appId,
|
|||
|
AppSecret: appSecret,
|
|||
|
Token: token,
|
|||
|
//EncodingAESKey: "xxxx",
|
|||
|
Cache: cache,
|
|||
|
}
|
|||
|
wc := wechat.NewWechat()
|
|||
|
officialAccount := wc.GetOfficialAccount(cfg)
|
|||
|
oauth := officialAccount.GetOauth()
|
|||
|
accessToken, err := oauth.GetUserAccessToken(code)
|
|||
|
if err != nil {
|
|||
|
return
|
|||
|
}
|
|||
|
userinfo, err = oauth.GetUserInfo(accessToken.AccessToken, accessToken.OpenID, "")
|
|||
|
if err != nil {
|
|||
|
return
|
|||
|
}
|
|||
|
return
|
|||
|
}
|