This commit is contained in:
jiangyong27 2024-10-21 17:27:46 +08:00
parent acc8f15a06
commit 784b361ec8
4 changed files with 353 additions and 0 deletions

18
weixin/app_sdk.go Normal file
View File

@ -0,0 +1,18 @@
package weixin
type AppSdk struct {
BaseSdk
}
func NewAppSdk(appid, secret string) *AppSdk {
return &AppSdk{
BaseSdk{
appid: appid,
secret: secret,
},
}
}
func (o *AppSdk) GetUserInfoByCode(code string) (*UserInfo, error) {
return o.getUserInfoByCode(code)
}

133
weixin/base.go Normal file
View File

@ -0,0 +1,133 @@
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"
accessToken2UserInfoUrl string = "https://api.weixin.qq.com/sns/userinfo"
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
}

110
weixin/mp_sdk.go Normal file
View File

@ -0,0 +1,110 @@
package weixin
import (
"bytes"
"encoding/json"
"errors"
"fmt"
"github.com/spf13/cast"
"github.com/tidwall/gjson"
"io"
"net/http"
)
type MpSdk struct {
BaseSdk
}
func NewMpSdk(appid, secret string) *MpSdk {
return &MpSdk{
BaseSdk{
appid: appid,
secret: secret,
},
}
}
func (o *MpSdk) GetUserInfoByJsCode(code string) (*UserInfo, error) {
url := fmt.Sprintf("%s?appid=%s&secret=%s&js_code=%s&grant_type=authorization_code",
jscode2SessionUrl, 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
}
userInfo := new(UserInfo)
g := gjson.ParseBytes(body)
userInfo.Openid = g.Get("openid").String()
userInfo.Unionid = g.Get("unionid").String()
return userInfo, nil
}
func (o *MpSdk) GetPhone(code string) (string, error) {
accessToken, err := o.getAccessToken()
if err != nil {
return "", err
}
reqUrl := fmt.Sprintf("%s?access_token=%s", userPhoneNumberUrl, accessToken)
res, err := http.Post(reqUrl, "application/json", bytes.NewBuffer([]byte(fmt.Sprintf(`{"code":"%s"}`, code))))
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"))
}
return g.Get("phone_info.phoneNumber").String(), nil
}
func (o *MpSdk) GetUnlimitedQRCode(params map[string]interface{}) ([]byte, error) {
if _, ok := params["scene"]; !ok {
return nil, errors.New("scene参数缺失")
}
if _, ok := params["width"]; !ok {
params["width"] = 280
}
if _, ok := params["env_version"]; !ok {
params["env_version"] = "release"
}
if _, ok := params["check_path"]; !ok {
params["check_path"] = false
}
if _, ok := params["page"]; !ok {
params["page"] = "pages/index/index"
}
marshal, _ := json.Marshal(params)
accessToken, err := o.getAccessToken()
if err != nil {
return nil, err
}
url := fmt.Sprintf("%s?access_token=%s", getWxACodeUnLimitUrl, accessToken)
res, _ := http.Post(url, "application/json", bytes.NewBuffer(marshal))
body, err := io.ReadAll(res.Body)
defer res.Body.Close()
if err != nil {
return nil, err
}
mp := make(map[string]interface{})
err = json.Unmarshal(body, &mp)
if err == nil {
return nil, fmt.Errorf("%d:%s", cast.ToInt64(mp["errcode"]), cast.ToString(mp["errmsg"]))
}
return body, nil
}

92
weixin/oa_sdk.go Normal file
View File

@ -0,0 +1,92 @@
package weixin
import (
"bytes"
"encoding/json"
"fmt"
"github.com/tidwall/gjson"
"io"
"net/http"
)
type OaSdk struct {
BaseSdk
}
func NewOaSdk(appid, secret string) *OaSdk {
return &OaSdk{
BaseSdk{
appid: appid,
secret: secret,
},
}
}
func (o *OaSdk) GetQrCode(sceneStr string) (string, error) {
params := make(map[string]interface{})
params["expire_seconds"] = 1728000 //20天
params["action_name"] = "QR_STR_SCENE"
params["action_info"] = map[string]interface{}{
"scene": map[string]interface{}{
"scene_str": sceneStr, // sceneStr不超过64个字符
},
}
marshal, _ := json.Marshal(params)
accessToken, err := o.getAccessToken()
if err != nil {
return "", err
}
url := fmt.Sprintf("?access_token=%s", oaQrCodeCreateUrl, accessToken)
res, _ := http.Post(url, "application/json", bytes.NewBuffer(marshal))
defer res.Body.Close()
body, err := io.ReadAll(res.Body)
if err != nil {
return "", err
}
g := gjson.ParseBytes(body)
qrcodeUrl := g.Get("url").String()
if qrcodeUrl == "" {
return "", fmt.Errorf("%d:%s", g.Get("errcode").Int(), g.Get("errmsg").String())
}
return qrcodeUrl, nil
}
func (o *BaseSdk) GetUserInfoByCode(code string) (*UserInfo, error) {
return o.getUserInfoByCode(code)
}
func (o *OaSdk) GetUserInfoByOpenid(openid string) (*UserInfo, error) {
accessToken, err := o.getAccessToken()
if err != nil {
return nil, err
}
url := fmt.Sprintf("%s?access_token=%s&openid=%s&lang=zh_CN",
userInfoByOpenid, accessToken, openid)
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())
}
user := new(UserInfo)
user.Unionid = g.Get("unionid").String()
user.Nickname = g.Get("nickname").String()
user.Province = g.Get("province").String()
user.City = g.Get("city").String()
user.Country = g.Get("country").String()
user.HeadUrl = g.Get("headimgurl").String()
user.Sex = int(g.Get("sex").Int())
user.Openid = openid
return user, nil
}