1
0
mirror of https://github.com/silenceper/wechat.git synced 2026-02-04 12:52:27 +08:00

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.
This commit is contained in:
mahongran
2025-01-07 22:19:21 +08:00
committed by GitHub
parent 92bf6c7699
commit 71c8ab58fb
4 changed files with 32 additions and 12 deletions

View File

@@ -189,19 +189,27 @@ func (ak *StableAccessToken) GetAccessTokenDirectly(ctx context.Context, forceRe
type WorkAccessToken struct { type WorkAccessToken struct {
CorpID string CorpID string
CorpSecret string CorpSecret string
AgentID string // 可选,用于区分不同应用
cacheKeyPrefix string cacheKeyPrefix string
cache cache.Cache cache cache.Cache
accessTokenLock *sync.Mutex accessTokenLock *sync.Mutex
} }
// NewWorkAccessToken new WorkAccessToken // NewWorkAccessToken new WorkAccessToken (保持向后兼容)
func NewWorkAccessToken(corpID, corpSecret, cacheKeyPrefix string, cache cache.Cache) AccessTokenContextHandle { 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 { if cache == nil {
panic("cache the not exist") panic("cache is needed")
} }
return &WorkAccessToken{ return &WorkAccessToken{
CorpID: corpID, CorpID: corpID,
CorpSecret: corpSecret, CorpSecret: corpSecret,
AgentID: agentID,
cache: cache, cache: cache,
cacheKeyPrefix: cacheKeyPrefix, cacheKeyPrefix: cacheKeyPrefix,
accessTokenLock: new(sync.Mutex), accessTokenLock: new(sync.Mutex),
@@ -218,7 +226,17 @@ func (ak *WorkAccessToken) GetAccessTokenContext(ctx context.Context) (accessTok
// 加上lock是为了防止在并发获取token时cache刚好失效导致从微信服务器上获取到不同token // 加上lock是为了防止在并发获取token时cache刚好失效导致从微信服务器上获取到不同token
ak.accessTokenLock.Lock() ak.accessTokenLock.Lock()
defer ak.accessTokenLock.Unlock() 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) val := ak.cache.Get(accessTokenCacheKey)
if val != nil { if val != nil {
accessToken = val.(string) accessToken = val.(string)
@@ -234,6 +252,9 @@ func (ak *WorkAccessToken) GetAccessTokenContext(ctx context.Context) (accessTok
expires := resAccessToken.ExpiresIn - 1500 expires := resAccessToken.ExpiresIn - 1500
err = ak.cache.Set(accessTokenCacheKey, resAccessToken.AccessToken, time.Duration(expires)*time.Second) err = ak.cache.Set(accessTokenCacheKey, resAccessToken.AccessToken, time.Duration(expires)*time.Second)
if err != nil {
return
}
accessToken = resAccessToken.AccessToken accessToken = resAccessToken.AccessToken
return return

View File

@@ -12,7 +12,6 @@ type Config struct {
AgentID string `json:"agent_id"` // agent_id AgentID string `json:"agent_id"` // agent_id
Cache cache.Cache Cache cache.Cache
RasPrivateKey string // 消息加密私钥,可以在企业微信管理端--管理工具--消息加密公钥查看对用公钥,私钥一般由自己保存 RasPrivateKey string // 消息加密私钥,可以在企业微信管理端--管理工具--消息加密公钥查看对用公钥,私钥一般由自己保存
Token string `json:"token"` // 微信客服回调配置,用于生成签名校验回调请求的合法性 Token string `json:"token"` // 微信客服回调配置,用于生成签名校验回调请求的合法性
EncodingAESKey string `json:"encoding_aes_key"` // 微信客服回调p配置用于解密回调消息内容对应的密文 EncodingAESKey string `json:"encoding_aes_key"` // 微信客服回调p配置用于解密回调消息内容对应的密文
} }

View File

@@ -24,7 +24,7 @@ func NewClient(cfg *config.Config) (client *Client, err error) {
} }
// 初始化 AccessToken Handle // 初始化 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{ ctx := &context.Context{
Config: cfg, Config: cfg,
AccessTokenHandle: defaultAkHandle, AccessTokenHandle: defaultAkHandle,

View File

@@ -24,7 +24,7 @@ type Work struct {
// NewWork init work // NewWork init work
func NewWork(cfg *config.Config) *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{ ctx := &context.Context{
Config: cfg, Config: cfg,
AccessTokenHandle: defaultAkHandle, AccessTokenHandle: defaultAkHandle,