weixin
This commit is contained in:
parent
acc8f15a06
commit
784b361ec8
|
@ -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)
|
||||
}
|
|
@ -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
|
||||
}
|
|
@ -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
|
||||
}
|
|
@ -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
|
||||
}
|
Loading…
Reference in New Issue