| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899 |
- package credential
- import (
- "encoding/json"
- "fmt"
- "sync"
- "time"
- "github.com/silenceper/wechat/v2/cache"
- "github.com/silenceper/wechat/v2/util"
- )
- const (
- //AccessTokenURL 获取access_token的接口
- accessTokenURL = "https://api.weixin.qq.com/cgi-bin/token"
- //CacheKeyOfficialAccountPrefix 微信公众号cache key前缀
- CacheKeyOfficialAccountPrefix = "gowechat_officialaccount_"
- //CacheKeyMiniProgramPrefix 小程序cache key前缀
- CacheKeyMiniProgramPrefix = "gowechat_miniprogram_"
- )
- //DefaultAccessToken 默认AccessToken 获取
- type DefaultAccessToken struct {
- appID string
- appSecret string
- cacheKeyPrefix string
- cache cache.Cache
- accessTokenLock *sync.Mutex
- }
- //NewDefaultAccessToken new DefaultAccessToken
- func NewDefaultAccessToken(appID, appSecret, cacheKeyPrefix string, cache cache.Cache) AccessTokenHandle {
- if cache == nil {
- panic("cache is ineed")
- }
- return &DefaultAccessToken{
- appID: appID,
- appSecret: appSecret,
- cache: cache,
- cacheKeyPrefix: cacheKeyPrefix,
- accessTokenLock: new(sync.Mutex),
- }
- }
- //ResAccessToken struct
- type ResAccessToken struct {
- util.CommonError
- AccessToken string `json:"access_token"`
- ExpiresIn int64 `json:"expires_in"`
- }
- //GetAccessToken 获取access_token,先从cache中获取,没有则从服务端获取
- func (ak *DefaultAccessToken) GetAccessToken() (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.appID)
- val := ak.cache.Get(accessTokenCacheKey)
- if val != nil {
- accessToken = val.(string)
- return
- }
- //cache失效,从微信服务器获取
- var resAccessToken ResAccessToken
- resAccessToken, err = GetTokenFromServer(ak.appID, ak.appSecret)
- if err != nil {
- return
- }
- expires := resAccessToken.ExpiresIn - 1500
- err = ak.cache.Set(accessTokenCacheKey, resAccessToken.AccessToken, time.Duration(expires)*time.Second)
- if err != nil {
- return
- }
- accessToken = resAccessToken.AccessToken
- return
- }
- //GetTokenFromServer 强制从微信服务器获取token
- func GetTokenFromServer(appID, appSecret string) (resAccessToken ResAccessToken, err error) {
- url := fmt.Sprintf("%s?grant_type=client_credential&appid=%s&secret=%s", accessTokenURL, appID, appSecret)
- var body []byte
- body, err = util.HTTPGet(url)
- if err != nil {
- return
- }
- err = json.Unmarshal(body, &resAccessToken)
- if err != nil {
- return
- }
- if resAccessToken.ErrMsg != "" {
- err = fmt.Errorf("get access_token error : errcode=%v , errormsg=%v", resAccessToken.ErrCode, resAccessToken.ErrMsg)
- return
- }
- return
- }
|