Sfoglia il codice sorgente

F ix work access token (#810)

* feat: enhance WorkAccessToken to include AgentID for improved token management

- Added AgentID field to WorkAccessToken struct.
- Updated NewWorkAccessToken function to accept AgentID as a parameter.
- Modified access token cache key to incorporate AgentID, ensuring unique cache entries per agent.

This change improves the handling of access tokens in a multi-agent environment.

* refactor: enhance WorkAccessToken to improve cache key handling

- Updated the AgentID field in WorkAccessToken struct to clarify its optional nature for distinguishing applications.
- Modified the access token cache key construction to support both new and legacy formats based on the presence of AgentID.
- Added comments for better understanding of the cache key logic and its compatibility with historical versions.

This change improves the flexibility and clarity of access token management in multi-agent scenarios.

* feat: enhance WorkAccessToken with new constructor for AgentID support

- Introduced NewWorkAccessTokenWithAgentID function to maintain backward compatibility while allowing for AgentID usage.
- Updated NewWorkAccessToken to call the new constructor, ensuring seamless integration.
- Improved error handling in GetAccessTokenContext by checking for cache availability and handling potential errors during cache operations.

This change enhances the flexibility of access token management, particularly in multi-agent scenarios, while ensuring compatibility with existing implementations.
mahongran 1 anno fa
parent
commit
71c8ab58fb
4 ha cambiato i file con 32 aggiunte e 12 eliminazioni
  1. 25 4
      credential/default_access_token.go
  2. 5 6
      work/config/config.go
  3. 1 1
      work/kf/client.go
  4. 1 1
      work/work.go

+ 25 - 4
credential/default_access_token.go

@@ -189,19 +189,27 @@ func (ak *StableAccessToken) GetAccessTokenDirectly(ctx context.Context, forceRe
 type WorkAccessToken struct {
 	CorpID          string
 	CorpSecret      string
+	AgentID         string // 可选,用于区分不同应用
 	cacheKeyPrefix  string
 	cache           cache.Cache
 	accessTokenLock *sync.Mutex
 }
 
-// NewWorkAccessToken new WorkAccessToken
-func NewWorkAccessToken(corpID, corpSecret, cacheKeyPrefix string, cache cache.Cache) AccessTokenContextHandle {
+// NewWorkAccessToken new WorkAccessToken (保持向后兼容)
+func NewWorkAccessToken(corpID, corpSecret, agentID, cacheKeyPrefix string, cache cache.Cache) AccessTokenContextHandle {
+	// 调用新方法,保持兼容性
+	return NewWorkAccessTokenWithAgentID(corpID, corpSecret, agentID, cacheKeyPrefix, cache)
+}
+
+// NewWorkAccessTokenWithAgentID new WorkAccessToken with agentID
+func NewWorkAccessTokenWithAgentID(corpID, corpSecret, agentID, cacheKeyPrefix string, cache cache.Cache) AccessTokenContextHandle {
 	if cache == nil {
-		panic("cache the not exist")
+		panic("cache is needed")
 	}
 	return &WorkAccessToken{
 		CorpID:          corpID,
 		CorpSecret:      corpSecret,
+		AgentID:         agentID,
 		cache:           cache,
 		cacheKeyPrefix:  cacheKeyPrefix,
 		accessTokenLock: new(sync.Mutex),
@@ -218,7 +226,17 @@ func (ak *WorkAccessToken) GetAccessTokenContext(ctx context.Context) (accessTok
 	// 加上lock,是为了防止在并发获取token时,cache刚好失效,导致从微信服务器上获取到不同token
 	ak.accessTokenLock.Lock()
 	defer ak.accessTokenLock.Unlock()
-	accessTokenCacheKey := fmt.Sprintf("%s_access_token_%s", ak.cacheKeyPrefix, ak.CorpID)
+
+	// 构建缓存key
+	var accessTokenCacheKey string
+	if ak.AgentID != "" {
+		// 如果设置了AgentID,使用新的key格式
+		accessTokenCacheKey = fmt.Sprintf("%s_access_token_%s_%s", ak.cacheKeyPrefix, ak.CorpID, ak.AgentID)
+	} else {
+		// 兼容历史版本的key格式
+		accessTokenCacheKey = fmt.Sprintf("%s_access_token_%s", ak.cacheKeyPrefix, ak.CorpID)
+	}
+
 	val := ak.cache.Get(accessTokenCacheKey)
 	if val != nil {
 		accessToken = val.(string)
@@ -234,6 +252,9 @@ func (ak *WorkAccessToken) GetAccessTokenContext(ctx context.Context) (accessTok
 
 	expires := resAccessToken.ExpiresIn - 1500
 	err = ak.cache.Set(accessTokenCacheKey, resAccessToken.AccessToken, time.Duration(expires)*time.Second)
+	if err != nil {
+		return
+	}
 
 	accessToken = resAccessToken.AccessToken
 	return

+ 5 - 6
work/config/config.go

@@ -7,12 +7,11 @@ import (
 
 // Config for 企业微信
 type Config struct {
-	CorpID        string `json:"corp_id"`     // corp_id
-	CorpSecret    string `json:"corp_secret"` // corp_secret,如果需要获取会话存档实例,当前参数请填写聊天内容存档的Secret,可以在企业微信管理端--管理工具--聊天内容存档查看
-	AgentID       string `json:"agent_id"`    // agent_id
-	Cache         cache.Cache
-	RasPrivateKey string // 消息加密私钥,可以在企业微信管理端--管理工具--消息加密公钥查看对用公钥,私钥一般由自己保存
-
+	CorpID         string `json:"corp_id"`     // corp_id
+	CorpSecret     string `json:"corp_secret"` // corp_secret,如果需要获取会话存档实例,当前参数请填写聊天内容存档的Secret,可以在企业微信管理端--管理工具--聊天内容存档查看
+	AgentID        string `json:"agent_id"`    // agent_id
+	Cache          cache.Cache
+	RasPrivateKey  string // 消息加密私钥,可以在企业微信管理端--管理工具--消息加密公钥查看对用公钥,私钥一般由自己保存
 	Token          string `json:"token"`            // 微信客服回调配置,用于生成签名校验回调请求的合法性
 	EncodingAESKey string `json:"encoding_aes_key"` // 微信客服回调p配置,用于解密回调消息内容对应的密文
 }

+ 1 - 1
work/kf/client.go

@@ -24,7 +24,7 @@ func NewClient(cfg *config.Config) (client *Client, err error) {
 	}
 
 	// 初始化 AccessToken Handle
-	defaultAkHandle := credential.NewWorkAccessToken(cfg.CorpID, cfg.CorpSecret, credential.CacheKeyWorkPrefix, cfg.Cache)
+	defaultAkHandle := credential.NewWorkAccessToken(cfg.CorpID, cfg.CorpSecret, cfg.AgentID, credential.CacheKeyWorkPrefix, cfg.Cache)
 	ctx := &context.Context{
 		Config:            cfg,
 		AccessTokenHandle: defaultAkHandle,

+ 1 - 1
work/work.go

@@ -24,7 +24,7 @@ type Work struct {
 
 // NewWork init work
 func NewWork(cfg *config.Config) *Work {
-	defaultAkHandle := credential.NewWorkAccessToken(cfg.CorpID, cfg.CorpSecret, credential.CacheKeyWorkPrefix, cfg.Cache)
+	defaultAkHandle := credential.NewWorkAccessToken(cfg.CorpID, cfg.CorpSecret, cfg.AgentID, credential.CacheKeyWorkPrefix, cfg.Cache)
 	ctx := &context.Context{
 		Config:            cfg,
 		AccessTokenHandle: defaultAkHandle,