From 6ac7e1142f6b8d19df4782760b52de3d8472b1dc Mon Sep 17 00:00:00 2001 From: wenzl Date: Tue, 10 Jul 2018 14:24:38 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E4=BC=81=E4=B8=9A=E5=BE=AE?= =?UTF-8?q?=E4=BF=A1=E7=BD=91=E9=A1=B5=E6=8E=88=E6=9D=83=E6=94=AF=E6=8C=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- context/qy_access_token.go | 76 ++++++++++++++++++++++++++++++ menu/menu.go | 1 - oauth/qy_oauth.go | 95 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 171 insertions(+), 1 deletion(-) create mode 100644 context/qy_access_token.go create mode 100644 oauth/qy_oauth.go diff --git a/context/qy_access_token.go b/context/qy_access_token.go new file mode 100644 index 0000000..c76d35a --- /dev/null +++ b/context/qy_access_token.go @@ -0,0 +1,76 @@ +package context + +import ( + "encoding/json" + "fmt" + "log" + "sync" + "time" + + "github.com/silenceper/wechat/util" +) + +const ( + //qyAccessTokenURL 获取access_token的接口 + qyAccessTokenURL = "https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid=%s&corpsecret=%s" +) + +//ResQyAccessToken struct +type ResQyAccessToken struct { + util.CommonError + + AccessToken string `json:"access_token"` + ExpiresIn int64 `json:"expires_in"` +} + +//SetQyAccessTokenLock 设置读写锁(一个appID一个读写锁) +func (ctx *Context) SetQyAccessTokenLock(l *sync.RWMutex) { + ctx.accessTokenLock = l +} + +//GetQyAccessToken 获取access_token +func (ctx *Context) GetQyAccessToken() (accessToken string, err error) { + ctx.accessTokenLock.Lock() + defer ctx.accessTokenLock.Unlock() + + accessTokenCacheKey := fmt.Sprintf("qy_access_token_%s", ctx.AppID) + val := ctx.Cache.Get(accessTokenCacheKey) + if val != nil { + accessToken = val.(string) + return + } + + //从微信服务器获取 + var resQyAccessToken ResQyAccessToken + resQyAccessToken, err = ctx.GetQyAccessTokenFromServer() + if err != nil { + return + } + + accessToken = resQyAccessToken.AccessToken + return +} + +//GetQyAccessTokenFromServer 强制从微信服务器获取token +func (ctx *Context) GetQyAccessTokenFromServer() (resQyAccessToken ResQyAccessToken, err error) { + log.Printf("GetQyAccessTokenFromServer") + url := fmt.Sprintf(qyAccessTokenURL, ctx.AppID, ctx.AppSecret) + var body []byte + body, err = util.HTTPGet(url) + if err != nil { + return + } + err = json.Unmarshal(body, &resQyAccessToken) + if err != nil { + return + } + if resQyAccessToken.ErrCode != 0 { + err = fmt.Errorf("get qy_access_token error : errcode=%v , errormsg=%v", resQyAccessToken.ErrCode, resQyAccessToken.ErrMsg) + return + } + + qyAccessTokenCacheKey := fmt.Sprintf("qy_access_token_%s", ctx.AppID) + expires := resQyAccessToken.ExpiresIn - 1500 + err = ctx.Cache.Set(qyAccessTokenCacheKey, resQyAccessToken.AccessToken, time.Duration(expires)*time.Second) + return +} diff --git a/menu/menu.go b/menu/menu.go index f4aeb6d..67fe015 100644 --- a/menu/menu.go +++ b/menu/menu.go @@ -286,7 +286,6 @@ func (menu *Menu) GetCurrentSelfMenuInfo() (resSelfMenuInfo ResSelfMenuInfo, err if err != nil { return } - fmt.Println(string(response)) err = json.Unmarshal(response, &resSelfMenuInfo) if err != nil { return diff --git a/oauth/qy_oauth.go b/oauth/qy_oauth.go new file mode 100644 index 0000000..3f6916d --- /dev/null +++ b/oauth/qy_oauth.go @@ -0,0 +1,95 @@ +package oauth + +import ( + "encoding/json" + "fmt" + "net/url" + + "github.com/silenceper/wechat/util" +) + +var ( + qyRedirectOauthURL = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=%s&redirect_uri=%s&response_type=code&scope=%s&agentid=%s&state=%s#wechat_redirect" + qyUserInfoURL = "https://qyapi.weixin.qq.com/cgi-bin/user/getuserinfo?access_token=%s&code=%s" + qyUserDetailURL = "https://qyapi.weixin.qq.com/cgi-bin/user/getuserdetail" +) + +//GetQyRedirectURL 获取企业微信跳转的url地址 +func (oauth *Oauth) GetQyRedirectURL(redirectURI, agentid, scope, state string) (string, error) { + //url encode + urlStr := url.QueryEscape(redirectURI) + return fmt.Sprintf(qyRedirectOauthURL, oauth.AppID, urlStr, scope, agentid, state), nil +} + +//QyUserInfo 用户授权获取到用户信息 +type QyUserInfo struct { + util.CommonError + + UserID string `json:"UserId"` + DeviceID string `json:"DeviceId"` + UserTicket string `json:"user_ticket"` + ExpiresIn int64 `json:"expires_in"` +} + +//GetQyUserInfoByCode 根据code获取企业user_info +func (oauth *Oauth) GetQyUserInfoByCode(code string) (result QyUserInfo, err error) { + qyAccessToken, e := oauth.GetQyAccessToken() + if e != nil { + err = e + return + } + urlStr := fmt.Sprintf(qyUserInfoURL, qyAccessToken, code) + var response []byte + response, err = util.HTTPGet(urlStr) + if err != nil { + return + } + err = json.Unmarshal(response, &result) + if err != nil { + return + } + if result.ErrCode != 0 { + err = fmt.Errorf("GetQyUserInfoByCode error : errcode=%v , errmsg=%v", result.ErrCode, result.ErrMsg) + return + } + return +} + +//QyUserDetail 到用户详情 +type QyUserDetail struct { + util.CommonError + + UserID string `json:"UserId"` + Name string `json:"name"` + Mobile string `json:"mobile"` + Gender string `json:"gender"` + Email string `json:"email"` + Avatar string `json:"avatar"` + QrCode string `json:"qr_code"` +} + +//GetQyUserDetailUserTicket 根据user_ticket获取到用户详情 +func (oauth *Oauth) GetQyUserDetailUserTicket(userTicket string) (result QyUserDetail, err error) { + var qyAccessToken string + qyAccessToken, err = oauth.GetQyAccessToken() + if err != nil { + return + } + uri := fmt.Sprintf("%s?access_token=%s", qyUserDetailURL, qyAccessToken) + var response []byte + response, err = util.PostJSON(uri, map[string]string{ + "user_ticket": userTicket, + }) + if err != nil { + return + } + err = json.Unmarshal(response, &result) + if err != nil { + return + } + if result.ErrCode != 0 { + err = fmt.Errorf("GetQyUserDetailUserTicket Error , errcode=%d , errmsg=%s", result.ErrCode, result.ErrMsg) + return + } + return +}