package context import ( "dashoo.cn/opms_libary/plugin/dingtalk/message" "encoding/json" "fmt" "github.com/gogf/gf/frame/g" "sync" "time" ) const ( //AccessTokenURL 获取access_token的接口 AccessTokenURL = "https://oapi.dingtalk.com/gettoken" ) //ResAccessToken 结构体 type ResAccessToken struct { AccessToken string `json:"access_token"` ExpiresIn int64 `json:"expires_in"` Code int64 `json:"errcode"` Msg string `json:"errmsg"` } type Context struct { *Config //accessTokenLock 读写锁 同一个AppKey一个 accessTokenLock *sync.RWMutex SubsMessage *message.SubsMessage } //SetAccessTokenLock 设置读写锁(一个appID一个读写锁) func (ctx *Context) SetAccessTokenLock(l *sync.RWMutex) { ctx.accessTokenLock = l } //GetAccessToken 获取access_token func (ctx *Context) GetAccessToken() (accessToken string, err error) { ctx.accessTokenLock.Lock() defer ctx.accessTokenLock.Unlock() accessTokenCacheKey := fmt.Sprintf("access_token_%s", ctx.AppKey) val, _ := ctx.Cache.Get(accessTokenCacheKey) if val != nil { accessToken = val.(string) return } //从钉钉服务器获取 var resAccessToken ResAccessToken resAccessToken, err = ctx.GetAccessTokenFromServer() if err != nil { return } accessToken = resAccessToken.AccessToken return } //CleanAccessTokenCache clean cache func (ctx *Context) CleanAccessTokenCache() { accessTokenCacheKey := fmt.Sprintf("access_token_%s", ctx.AppKey) ctx.Cache.Remove(accessTokenCacheKey) } //GetAccessTokenFromServer 强制从服务器获取token func (ctx *Context) GetAccessTokenFromServer() (token ResAccessToken, err error) { url := fmt.Sprintf("%s?appkey=%s&appsecret=%s", AccessTokenURL, ctx.AppKey, ctx.AppSecret) body := g.Client().GetBytes(url) err = json.Unmarshal(body, &token) if err != nil { return } if token.Code != 0 { err = fmt.Errorf("get access_token error : errcode=%v , errormsg=%v", token.Code, token.Msg) return } accessTokenCacheKey := fmt.Sprintf("access_token_%s", ctx.AppKey) expires := token.ExpiresIn - 1500 err = ctx.Cache.Set(accessTokenCacheKey, token.AccessToken, time.Duration(expires)*time.Second) return }