Files
hyapi-server/internal/shared/fadada/token.go

72 lines
1.7 KiB
Go
Raw Normal View History

2026-07-21 15:53:29 +08:00
package fadada
import (
"fmt"
"strconv"
"sync"
"time"
)
// tokenCache accessToken 内存缓存(官方有效期约 2 小时)
type tokenCache struct {
mu sync.Mutex
token string
expiresAt time.Time
}
func (c *tokenCache) get() (string, bool) {
c.mu.Lock()
defer c.mu.Unlock()
if c.token == "" || time.Now().After(c.expiresAt) {
return "", false
}
return c.token, true
}
func (c *tokenCache) set(token string, ttl time.Duration) {
c.mu.Lock()
defer c.mu.Unlock()
c.token = token
c.expiresAt = time.Now().Add(ttl)
}
// ensureAccessToken 获取可用 accessToken过期前自动刷新
func (c *Client) ensureAccessToken() (string, error) {
if token, ok := c.tokenCache.get(); ok {
return token, nil
}
c.tokenMu.Lock()
defer c.tokenMu.Unlock()
if token, ok := c.tokenCache.get(); ok {
return token, nil
}
res, err := c.http.PostToken(pathGetAccessToken)
if err != nil {
return "", err
}
if res.Code != "" && res.Code != successCode {
return "", fmt.Errorf("获取法大大 accessToken 失败: code=%s msg=%s requestId=%s", res.Code, res.Msg, res.RequestID)
}
var data accessTokenData
if err := decodeData(res.Data, &data); err != nil {
return "", fmt.Errorf("解析 accessToken 失败: %w", err)
}
if data.AccessToken == "" {
return "", fmt.Errorf("获取法大大 accessToken 失败: 响应为空 code=%s msg=%s", res.Code, res.Msg)
}
ttl := 2*time.Hour - 5*time.Minute
if expiresIn, err := strconv.Atoi(data.ExpiresIn); err == nil && expiresIn > 0 {
ttl = time.Duration(expiresIn)*time.Second - 5*time.Minute
if ttl < time.Minute {
ttl = time.Minute
}
}
c.tokenCache.set(data.AccessToken, ttl)
return data.AccessToken, nil
}