| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596 |
- package services
- import (
- "context"
- "encoding/json"
- "fmt"
- "go-policy-service/models"
- "go-policy-service/structs"
- "go-policy-service/utils"
- "log"
- "time"
- "github.com/go-redis/redis/v8"
- )
- type TokenManager struct {
- rdb *redis.Client
- hgConfig *models.HgConfig
- httpClient utils.HTTPClient // 自己请求 token
- apiUrl string // 自己请求 token 的接口
- }
- // 修复构造函数参数声明
- func NewTokenManager(
- rdb *redis.Client,
- hgConfig *models.HgConfig,
- httpClient utils.HTTPClient, // 明确参数类型
- apiUrl string, // 添加类型声明
- ) *TokenManager {
- return &TokenManager{
- rdb: rdb,
- hgConfig: hgConfig,
- httpClient: httpClient,
- apiUrl: apiUrl,
- }
- }
- func (t *TokenManager) GetAccessToken() (string, error) {
- tokenKey := fmt.Sprintf("60s-hgapi-%s", t.hgConfig.Account)
- ctx := context.Background()
- // 尝试从 Redis 获取现有 token
- token, err := t.rdb.Get(ctx, tokenKey).Result()
- if err == nil {
- return token, nil
- }
- // 重试机制
- const maxRetries = 3
- for i := 0; i < maxRetries; i++ {
- tokenData, err := t.requestToken()
- if err == nil {
- expireTimestamp := utils.StringToTimestamp(tokenData.ExpireTime, "2006-01-02 15:04:05")
- // 提前半小时失效
- durationSeconds := expireTimestamp - time.Now().Unix()
- // 确保最小有效期为0秒
- if durationSeconds < 0 {
- durationSeconds = 0
- }
- // 成功获取 token 后存入 Redis
- if setErr := t.rdb.SetEX(ctx, tokenKey, tokenData.AccessToken, time.Duration(durationSeconds)*time.Second).Err(); setErr != nil {
- log.Printf("Failed to set token in Redis: %v", setErr)
- }
- return tokenData.AccessToken, nil
- }
- log.Printf("获取hgApi token失败,剩余重试次数: %d, 错误: %v", maxRetries-i-1, err)
- if i < maxRetries-1 {
- time.Sleep(1 * time.Second)
- }
- }
- log.Println("hgApi token获取彻底失败,请检查接口状态")
- return "", fmt.Errorf("failed to get token after %d attempts", maxRetries)
- }
- func (t *TokenManager) requestToken() (structs.TokenData, error) {
- url := fmt.Sprintf("%s/gateway/oauth/token?grant_type=client_credentials&client_id=%s&client_secret=%s",
- t.apiUrl, t.hgConfig.Account, t.hgConfig.Password)
- respBytes, err := t.httpClient.RequestJSON(context.Background(), "GET", url, nil)
- if err != nil {
- return structs.TokenData{}, fmt.Errorf("HTTP请求失败: %w", err)
- }
- var tokenResp structs.TokenResponse
- if err := json.Unmarshal(respBytes, &tokenResp); err != nil {
- return structs.TokenData{}, fmt.Errorf("JSON解析失败: %w", err)
- }
- if !tokenResp.Success || tokenResp.Data.AccessToken == "" {
- return structs.TokenData{}, fmt.Errorf("接口返回无效响应")
- }
- return tokenResp.Data, nil
- }
|