@@ -1,6 +1,7 @@
package credential
import (
"context"
"encoding/json"
"fmt"
"sync"
@@ -11,19 +12,19 @@ import (
)
const (
//AccessTokenURL 获取access_token的接口
// AccessTokenURL 获取access_token的接口
accessTokenURL = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=%s&secret=%s"
//AccessTokenURL 企业微信获取access_token的接口
// AccessTokenURL 企业微信获取access_token的接口
workAccessTokenURL = "https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid=%s&corpsecret=%s"
//CacheKeyOfficialAccountPrefix 微信公众号cache key前缀
// CacheKeyOfficialAccountPrefix 微信公众号cache key前缀
CacheKeyOfficialAccountPrefix = "gowechat_officialaccount_"
//CacheKeyMiniProgramPrefix 小程序cache key前缀
// CacheKeyMiniProgramPrefix 小程序cache key前缀
CacheKeyMiniProgramPrefix = "gowechat_miniprogram_"
//CacheKeyWorkPrefix 企业微信cache key前缀
// CacheKeyWorkPrefix 企业微信cache key前缀
CacheKeyWorkPrefix = "gowechat_work_"
)
//DefaultAccessToken 默认AccessToken 获取
// DefaultAccessToken 默认AccessToken 获取
type DefaultAccessToken struct {
appID string
appSecret string
@@ -32,8 +33,8 @@ type DefaultAccessToken struct {
accessTokenLock * sync . Mutex
}
//NewDefaultAccessToken new DefaultAccessToken
func NewDefaultAccessToken ( appID , appSecret , cacheKeyPrefix string , cache cache . Cache ) AccessTokenHandle {
// NewDefaultAccessToken new DefaultAccessToken
func NewDefaultAccessToken ( appID , appSecret , cacheKeyPrefix string , cache cache . Cache ) AccessTokenContext Handle {
if cache == nil {
panic ( "cache is ineed" )
}
@@ -46,7 +47,7 @@ func NewDefaultAccessToken(appID, appSecret, cacheKeyPrefix string, cache cache.
}
}
//ResAccessToken struct
// ResAccessToken struct
type ResAccessToken struct {
util . CommonError
@@ -54,15 +55,20 @@ type ResAccessToken struct {
ExpiresIn int64 ` json:"expires_in" `
}
//GetAccessToken 获取access_token,先从cache中获取, 没有则从服务端获取
// GetAccessToken 获取access_token,先从cache中获取, 没有则从服务端获取
func ( ak * DefaultAccessToken ) GetAccessToken ( ) ( accessToken string , err error ) {
return ak . GetAccessTokenContext ( context . Background ( ) )
}
// GetAccessTokenContext 获取access_token,先从cache中获取, 没有则从服务端获取
func ( ak * DefaultAccessToken ) GetAccessTokenContext ( ctx context . Context ) ( accessToken string , err error ) {
// 先从cache中取
accessTokenCacheKey := fmt . Sprintf ( "%s_access_token_%s" , ak . cacheKeyPrefix , ak . appID )
if val := ak . cache . Get ( accessTokenCacheKey ) ; val != nil {
return val . ( string ) , nil
}
//加上lock, 是为了防止在并发获取token时, cache刚好失效, 导致从微信服务器上获取到不同token
// 加上lock, 是为了防止在并发获取token时, cache刚好失效, 导致从微信服务器上获取到不同token
ak . accessTokenLock . Lock ( )
defer ak . accessTokenLock . Unlock ( )
@@ -71,9 +77,9 @@ func (ak *DefaultAccessToken) GetAccessToken() (accessToken string, err error) {
return val . ( string ) , nil
}
//cache失效, 从微信服务器获取
// cache失效, 从微信服务器获取
var resAccessToken ResAccessToken
resAccessToken , err = GetTokenFromServer( fmt . Sprintf ( accessTokenURL , ak . appID , ak . appSecret ) )
resAccessToken , err = GetTokenFromServerContext ( ctx , fmt . Sprintf ( accessTokenURL , ak . appID , ak . appSecret ) )
if err != nil {
return
}
@@ -87,7 +93,7 @@ func (ak *DefaultAccessToken) GetAccessToken() (accessToken string, err error) {
return
}
//WorkAccessToken 企业微信AccessToken 获取
// WorkAccessToken 企业微信AccessToken 获取
type WorkAccessToken struct {
CorpID string
CorpSecret string
@@ -96,8 +102,8 @@ type WorkAccessToken struct {
accessTokenLock * sync . Mutex
}
//NewWorkAccessToken new WorkAccessToken
func NewWorkAccessToken ( corpID , corpSecret , cacheKeyPrefix string , cache cache . Cache ) AccessTokenHandle {
// NewWorkAccessToken new WorkAccessToken
func NewWorkAccessToken ( corpID , corpSecret , cacheKeyPrefix string , cache cache . Cache ) AccessTokenContext Handle {
if cache == nil {
panic ( "cache the not exist" )
}
@@ -110,9 +116,14 @@ func NewWorkAccessToken(corpID, corpSecret, cacheKeyPrefix string, cache cache.C
}
}
//GetAccessToken 企业微信获取access_token,先从cache中获取, 没有则从服务端获取
// GetAccessToken 企业微信获取access_token,先从cache中获取, 没有则从服务端获取
func ( ak * WorkAccessToken ) GetAccessToken ( ) ( accessToken string , err error ) {
//加上lock, 是为了防止在并发获取token时, cache刚好失效, 导致从微信服务器上获取到不同token
return ak . GetAccessTokenContext ( context . Background ( ) )
}
// GetAccessTokenContext 企业微信获取access_token,先从cache中获取, 没有则从服务端获取
func ( ak * WorkAccessToken ) GetAccessTokenContext ( ctx context . Context ) ( accessToken string , err error ) {
// 加上lock, 是为了防止在并发获取token时, cache刚好失效, 导致从微信服务器上获取到不同token
ak . accessTokenLock . Lock ( )
defer ak . accessTokenLock . Unlock ( )
accessTokenCacheKey := fmt . Sprintf ( "%s_access_token_%s" , ak . cacheKeyPrefix , ak . CorpID )
@@ -122,9 +133,9 @@ func (ak *WorkAccessToken) GetAccessToken() (accessToken string, err error) {
return
}
//cache失效, 从微信服务器获取
// cache失效, 从微信服务器获取
var resAccessToken ResAccessToken
resAccessToken , err = GetTokenFromServer( fmt . Sprintf ( workAccessTokenURL , ak . CorpID , ak . CorpSecret ) )
resAccessToken , err = GetTokenFromServerContext ( ctx , fmt . Sprintf ( workAccessTokenURL , ak . CorpID , ak . CorpSecret ) )
if err != nil {
return
}
@@ -138,10 +149,15 @@ func (ak *WorkAccessToken) GetAccessToken() (accessToken string, err error) {
return
}
//GetTokenFromServer 强制从微信服务器获取token
// GetTokenFromServer 强制从微信服务器获取token
func GetTokenFromServer ( url string ) ( resAccessToken ResAccessToken , err error ) {
return GetTokenFromServerContext ( context . Background ( ) , url )
}
// GetTokenFromServerContext 强制从微信服务器获取token
func GetTokenFromServerContext ( ctx context . Context , url string ) ( resAccessToken ResAccessToken , err error ) {
var body [ ] byte
body , err = util . HTTPGet( url )
body , err = util . HTTPGetContext ( ctx , url )
if err != nil {
return
}