You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
111 lines
2.6 KiB
Go
111 lines
2.6 KiB
Go
![]()
1 week ago
|
package wechat
|
||
|
|
||
|
import (
|
||
|
"crypto/sha1"
|
||
|
"encoding/hex"
|
||
|
"encoding/json"
|
||
|
"fmt"
|
||
|
"github.com/pkg/errors"
|
||
|
"io"
|
||
|
"net/http"
|
||
|
)
|
||
|
|
||
|
type WechatService struct {
|
||
|
AppId string
|
||
|
AppSecret string
|
||
|
client *http.Client
|
||
|
}
|
||
|
|
||
|
func NewWechatService(appId, appSecret string) *WechatService {
|
||
|
return &WechatService{appId, appSecret, nil}
|
||
|
}
|
||
|
|
||
|
func (ws *WechatService) GetOpenID(code string) (string, error) {
|
||
|
url := fmt.Sprintf(
|
||
|
"https://api.weixin.qq.com/sns/oauth2/access_token?appid=%s&secret=%s&code=%s&grant_type=authorization_code",
|
||
|
ws.AppId,
|
||
|
ws.AppSecret,
|
||
|
code,
|
||
|
)
|
||
|
resp, err := http.Get(url)
|
||
|
if err != nil {
|
||
|
return "", err
|
||
|
}
|
||
|
defer resp.Body.Close()
|
||
|
var res struct {
|
||
|
AccessToken string `json:"access_token"`
|
||
|
ExpiresIn int `json:"expires_in"`
|
||
|
RefreshToken string `json:"refresh_token"`
|
||
|
OpenID string `json:"openid"`
|
||
|
Scope string `json:"scope"`
|
||
|
ErrCode int `json:"errcode"`
|
||
|
ErrMsg string `json:"errmsg"`
|
||
|
}
|
||
|
|
||
|
if err := json.NewDecoder(resp.Body).Decode(&res); err != nil {
|
||
|
return "", errors.New("Failed to decode response")
|
||
|
}
|
||
|
fmt.Printf("%+v\n", res)
|
||
|
if res.ErrCode != 0 {
|
||
|
return "", errors.New(fmt.Sprintf("WeChat error: %s", res.ErrMsg))
|
||
|
}
|
||
|
|
||
|
// 🎯 获取到 openid
|
||
|
return res.OpenID, nil
|
||
|
}
|
||
|
|
||
|
func (ws *WechatService) GetAccessToken() (string, error) {
|
||
|
url := fmt.Sprintf("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=%s&secret=%s", ws.AppId, ws.AppSecret)
|
||
|
resp, err := http.Get(url)
|
||
|
if err != nil {
|
||
|
return "", err
|
||
|
}
|
||
|
defer resp.Body.Close()
|
||
|
|
||
|
var result map[string]interface{}
|
||
|
if err := json.NewDecoder(resp.Body).Decode(&result); err != nil {
|
||
|
return "", err
|
||
|
}
|
||
|
|
||
|
// 获取 access_token
|
||
|
accessToken, ok := result["access_token"].(string)
|
||
|
if !ok {
|
||
|
return "", errors.New("获取 access_token 失败")
|
||
|
}
|
||
|
|
||
|
return accessToken, nil
|
||
|
}
|
||
|
|
||
|
func (ws *WechatService) GetJsapiTicket(accessToken string) (string, error) {
|
||
|
url := fmt.Sprintf("https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=%s&type=jsapi", accessToken)
|
||
|
|
||
|
resp, err := http.Get(url)
|
||
|
if err != nil {
|
||
|
return "", err
|
||
|
}
|
||
|
defer resp.Body.Close()
|
||
|
|
||
|
var result map[string]interface{}
|
||
|
if err := json.NewDecoder(resp.Body).Decode(&result); err != nil {
|
||
|
return "", err
|
||
|
}
|
||
|
|
||
|
// 获取 jsapi_ticket
|
||
|
jsapiTicket, ok := result["ticket"].(string)
|
||
|
if !ok {
|
||
|
return "", errors.New("获取 jsapi_ticket 失败")
|
||
|
}
|
||
|
|
||
|
return jsapiTicket, nil
|
||
|
}
|
||
|
|
||
|
func (ws *WechatService) SignWxConfig(signStr string) (string, error) {
|
||
|
h := sha1.New()
|
||
|
_, err := io.WriteString(h, signStr)
|
||
|
if err != nil {
|
||
|
return "", err
|
||
|
}
|
||
|
signature := hex.EncodeToString(h.Sum(nil))
|
||
|
return signature, nil
|
||
|
}
|