gosdk/weixin/base.go

133 lines
3.3 KiB
Go

package weixin
import (
"fmt"
"github.com/tidwall/gjson"
"io"
"net/http"
"sync"
"time"
)
const (
code2AccessTokenUrl string = "https://api.weixin.qq.com/sns/oauth2/access_token"
jscode2SessionUrl string = "https://api.weixin.qq.com/sns/jscode2session"
accessTokenUrl string = "https://api.weixin.qq.com/cgi-bin/token"
userPhoneNumberUrl string = "https://api.weixin.qq.com/wxa/business/getuserphonenumber"
getWxACodeUnLimitUrl string = "https://api.weixin.qq.com/wxa/getwxacodeunlimit"
code2UserinfoUrl string = "https://api.weixin.qq.com/sns/userinfo"
oaQrCodeCreateUrl string = "https://api.weixin.qq.com/cgi-bin/qrcode/create"
userInfoByOpenid string = "https://api.weixin.qq.com/cgi-bin/user/info"
)
type UserInfo struct {
Openid string
Unionid string
AccessToken string
Nickname string
HeadUrl string
Sex int //1:为男性 2位女性
Country string
City string
Province string
}
type BaseSdk struct {
appid string
secret string
accessToken string
expireIn int64
lock sync.Mutex
}
func (o *BaseSdk) getAccessToken() (string, error) {
o.lock.Lock()
defer o.lock.Unlock()
if time.Now().Unix() < o.expireIn {
return o.accessToken, nil
}
// 获取一个新token
url := fmt.Sprintf("%s?grant_type=client_credential&appid=%s&secret=%s", accessTokenUrl, o.appid, o.secret)
res, err := http.Get(url)
if err != nil {
return "", err
}
defer res.Body.Close()
body, err := io.ReadAll(res.Body)
if err != nil {
return "", err
}
g := gjson.ParseBytes(body)
accessToken := g.Get("access_token").String()
if accessToken == "" {
return "", fmt.Errorf("%d:%s", g.Get("errcode").Int(), g.Get("errmsg").String())
}
o.accessToken = accessToken
o.expireIn = time.Now().Unix() + g.Get("expires_in").Int() - 10
return o.accessToken, nil
}
func (o *BaseSdk) getUserInfoByCode(code string) (*UserInfo, error) {
url := fmt.Sprintf("%s?appid=%s&secret=%s&code=%s&grant_type=authorization_code",
code2AccessTokenUrl, o.appid, o.secret, code)
res, err := http.Get(url)
if err != nil {
return nil, err
}
defer res.Body.Close()
body, err := io.ReadAll(res.Body)
if err != nil {
return nil, err
}
g := gjson.ParseBytes(body)
errcode := g.Get("errcode").Int()
if errcode != 0 {
return nil, fmt.Errorf("%d:%s", errcode, g.Get("errmsg").String())
}
var user UserInfo
user.Unionid = g.Get("unionid").String()
user.AccessToken = g.Get("access_token").String()
user.Openid = g.Get("openid").String()
err = o.getUserInfo(&user)
if err != nil {
return nil, err
}
return &user, nil
}
func (o *BaseSdk) getUserInfo(user *UserInfo) error {
url := fmt.Sprintf("%s?access_token=%s&openid=%s&lang=zh_CN",
code2UserinfoUrl, user.AccessToken, user.Openid)
res, err := http.Get(url)
if err != nil {
return err
}
defer res.Body.Close()
body, err := io.ReadAll(res.Body)
if err != nil {
return err
}
g := gjson.ParseBytes(body)
errcode := g.Get("errcode").Int()
if errcode != 0 {
return fmt.Errorf("%d:%s", errcode, g.Get("errmsg").String())
}
user.Unionid = g.Get("unionid").String()
user.Nickname = g.Get("nickname").String()
user.HeadUrl = g.Get("headimgurl").String()
user.Province = g.Get("province").String()
user.City = g.Get("city").String()
user.Country = g.Get("country").String()
user.Sex = int(g.Get("sex").Int())
return nil
}