236 lines
7.0 KiB
Go
236 lines
7.0 KiB
Go
package weixinapi
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/json"
|
|
"errors"
|
|
"git.rosy.net.cn/baseapi/utils"
|
|
"git.rosy.net.cn/jx-callback/globals"
|
|
)
|
|
|
|
type SNSTokenInfo struct {
|
|
AccessToken string `json:"access_token"`
|
|
ExpiresIn int `json:"expires_in"`
|
|
RefreshToken string `json:"refresh_token"`
|
|
OpenID string `json:"openid"`
|
|
Scope string `json:"scope"`
|
|
}
|
|
|
|
type SNSUserInfo struct {
|
|
OpenID string `json:"openid"`
|
|
NickName string `json:"nickname"`
|
|
Sex int `json:"sex"`
|
|
Province string `json:"province"`
|
|
City string `json:"city"`
|
|
Country string `json:"country"`
|
|
HeadImgURL string `json:"headimgurl"`
|
|
Privilege interface{} `json:"privilege"`
|
|
UnionID string `json:"unionid"`
|
|
}
|
|
|
|
type SessionInfo struct {
|
|
OpenID string `json:"openid"`
|
|
SessionKey string `json:"session_key"`
|
|
UnionID string `json:"unionid"`
|
|
}
|
|
|
|
type MiniUserInfo struct {
|
|
OpenID string `json:"openId"`
|
|
NickName string `json:"nickName"`
|
|
Gender int `json:"gender"`
|
|
Language string `json:"language"`
|
|
City string `json:"city"`
|
|
PhoneNumber string `json:"phoneNumber"`
|
|
PurePhoneNumber string `json:"purePhoneNumber"`
|
|
Province string `json:"province"`
|
|
Country string `json:"country"`
|
|
CountryCode string `json:"countryCode"`
|
|
AvatarURL string `json:"avatarUrl"`
|
|
UnionID string `json:"unionId"`
|
|
Watermark struct {
|
|
Timestamp int `json:"timestamp"`
|
|
Appid string `json:"appid"`
|
|
} `json:"watermark"`
|
|
}
|
|
|
|
type GetUserPhone struct {
|
|
ErrCode int64 `json:"errcode"`
|
|
ErrMsg string `json:"errmsg"`
|
|
PhoneInfo *UserPhone `json:"phone_info"`
|
|
}
|
|
|
|
// UserPhone 微信小程序解密后 用户手机号结构体
|
|
type UserPhone struct {
|
|
PhoneNumber string `json:"phoneNumber,omitempty"`
|
|
PurePhoneNumber string `json:"purePhoneNumber,omitempty"`
|
|
CountryCode string `json:"countryCode,omitempty"`
|
|
Watermark *watermarkInfo `json:"watermark,omitempty"`
|
|
}
|
|
|
|
type watermarkInfo struct {
|
|
Appid string `json:"appid,omitempty"`
|
|
Timestamp int `json:"timestamp,omitempty"`
|
|
}
|
|
|
|
func mapData2SNSToken(result map[string]interface{}) *SNSTokenInfo {
|
|
return &SNSTokenInfo{
|
|
AccessToken: utils.Interface2String(result["access_token"]),
|
|
ExpiresIn: int(utils.MustInterface2Int64(result["expires_in"])),
|
|
RefreshToken: utils.Interface2String(result["refresh_token"]),
|
|
OpenID: utils.Interface2String(result["openid"]),
|
|
Scope: utils.Interface2String(result["scope"]),
|
|
}
|
|
}
|
|
|
|
func (a *API) SNSRetrieveToken(code string) (tokenInfo *SNSTokenInfo, err error) {
|
|
result, err := a.AccessAPI("sns/oauth2/access_token", utils.Params2Map("grant_type", "authorization_code", "code", code), "")
|
|
if err != nil {
|
|
globals.SugarLogger.Debugf("SNSRetrieveToken err=%v", err)
|
|
return nil, err
|
|
}
|
|
globals.SugarLogger.Debugf("SNSRetrieveToken result=%s", mapData2SNSToken(result))
|
|
return mapData2SNSToken(result), nil
|
|
}
|
|
|
|
func (a *API) SNSRefreshToken(refreshToken string) (tokenInfo *SNSTokenInfo, err error) {
|
|
result, err := a.AccessAPI("sns/oauth2/refresh_token", utils.Params2Map("grant_type", "refresh_token", "refresh_token", refreshToken), "")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return mapData2SNSToken(result), nil
|
|
}
|
|
|
|
func (a *API) SNSGetUserInfo(accessToken, openid string) (*SNSUserInfo, error) {
|
|
result, err := a.AccessAPI("sns/userinfo", map[string]interface{}{
|
|
"access_token": accessToken,
|
|
"openid": openid,
|
|
}, "")
|
|
if err == nil {
|
|
retVal := &SNSUserInfo{
|
|
OpenID: utils.Interface2String(result["openid"]),
|
|
NickName: utils.Interface2String(result["nickname"]),
|
|
Sex: int(utils.MustInterface2Int64(result["sex"])),
|
|
Province: utils.Interface2String(result["province"]),
|
|
City: utils.Interface2String(result["city"]),
|
|
Country: utils.Interface2String(result["country"]),
|
|
HeadImgURL: utils.Interface2String(result["headimgurl"]),
|
|
Privilege: result["privilege"],
|
|
UnionID: utils.Interface2String(result["unionid"]),
|
|
}
|
|
return retVal, nil
|
|
}
|
|
return nil, err
|
|
}
|
|
|
|
func (a *API) SNSIsOpenIDValid(accessToken, openid string) (bool, error) {
|
|
_, err := a.AccessAPI("sns/auth", map[string]interface{}{
|
|
"access_token": accessToken,
|
|
"openid": openid,
|
|
}, "")
|
|
if err == nil {
|
|
return true, nil
|
|
}
|
|
return false, err
|
|
}
|
|
|
|
func (a *API) SNSCode2Session(jsCode string) (sessionInfo *SessionInfo, err error) {
|
|
result, err := a.AccessAPI("sns/jscode2session", map[string]interface{}{
|
|
"js_code": jsCode,
|
|
"grant_type": "authorization_code",
|
|
}, "")
|
|
if err == nil {
|
|
return &SessionInfo{
|
|
OpenID: utils.Interface2String(result["openid"]),
|
|
SessionKey: utils.Interface2String(result["session_key"]),
|
|
UnionID: utils.Interface2String(result["unionid"]),
|
|
}, nil
|
|
}
|
|
return nil, err
|
|
}
|
|
|
|
func (a *API) SNSGetUserPhone(jsCode string) (string, error) {
|
|
url := "wxa/business/getuserphonenumber"
|
|
if a.token == "" {
|
|
a.CBRetrieveToken()
|
|
}
|
|
bodyJson := map[string]interface{}{
|
|
"code": jsCode,
|
|
}
|
|
|
|
result, err := a.AccessAPI(url, nil, string(utils.MustMarshal(bodyJson)))
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
var phoneInfo *GetUserPhone
|
|
if err := utils.Map2StructByJson(result, &phoneInfo, false); err != nil {
|
|
return "", err
|
|
}
|
|
|
|
if phoneInfo.ErrCode != 0 {
|
|
return "", errors.New(phoneInfo.ErrMsg)
|
|
}
|
|
return phoneInfo.PhoneInfo.PhoneNumber, nil
|
|
}
|
|
|
|
// 获取小程序短连接CBRetrieveToken
|
|
func (a *API) MiniProgramSortLink() (string, error) {
|
|
weChatToken := ""
|
|
token := a.CBGetToken()
|
|
if token == "" {
|
|
newToken, err := a.CBRetrieveToken()
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
weChatToken = newToken.AccessToken
|
|
} else {
|
|
weChatToken = token
|
|
}
|
|
parmaJson := map[string]interface{}{
|
|
"access_token": weChatToken,
|
|
}
|
|
|
|
bodyJson := map[string]interface{}{
|
|
//"access_token ": weChatToken,
|
|
"expire_type": 1,
|
|
"expire_interval": 1,
|
|
}
|
|
body, _ := json.Marshal(bodyJson)
|
|
result, err := a.AccessAPI("wxa/generate_urllink", parmaJson, string(body))
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
errCode, _ := result["errcode"].(json.Number).Int64()
|
|
if errCode != 0 {
|
|
return "", errors.New(result["errmsg"].(string))
|
|
}
|
|
|
|
return result["url_link"].(string), nil
|
|
}
|
|
|
|
// 待删除
|
|
func (a *API) SNSDecodeMiniProgramData(encryptedData, sessionKey, iv string) (decryptedData []byte, err error) {
|
|
return SNSDecodeMiniProgramData(encryptedData, sessionKey, iv)
|
|
}
|
|
|
|
func SNSDecodeMiniProgramData(encryptedData, sessionKey, iv string) (decryptedData []byte, err error) {
|
|
decodedDataList, err := utils.Base64DecodeMultiString(encryptedData, sessionKey, iv)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
decryptedData, err = utils.AESCBCDecpryt(decodedDataList[0], decodedDataList[1], decodedDataList[2])
|
|
return decryptedData, err
|
|
}
|
|
|
|
func PKCSUnPadding(origData []byte) []byte {
|
|
length := len(origData)
|
|
unpadding := int(origData[length-1])
|
|
return origData[:(length - unpadding)]
|
|
}
|
|
|
|
func PKCSPadding(ciphertext []byte, blockSize int) []byte {
|
|
padding := blockSize - len(ciphertext)%blockSize
|
|
padtext := bytes.Repeat([]byte{byte(padding)}, padding)
|
|
return append(ciphertext, padtext...)
|
|
}
|