package auth import ( "context" "crypto/md5" "encoding/hex" "fmt" "time" "lone-services/pkg/redis" "lone-services/pkg/utils" jsoniter "github.com/json-iterator/go" ) const accessTokenURL = "https://api.weixin.qq.com/cgi-bin/token" type AccessTokenResult struct { AccessToken string `json:"access_token"` ExpiresIn int `json:"expires_in"` ErrCode int `json:"errcode"` ErrMsg string `json:"errmsg"` } func (c *Client) AccessToken(ctx context.Context) (*AccessTokenResult, error) { if c == nil || c.AppID == utils.StringEmpty || c.Secret == utils.StringEmpty { return nil, fmt.Errorf("wechat app config missing") } if ctx == nil { ctx = context.Background() } secretMd5 := md5.Sum([]byte(c.Secret)) key := fmt.Sprintf("wechat:access_token:%s:%s", c.AppID, hex.EncodeToString(secretMd5[:])[:8]) token, err := redis.Client.Get(ctx, key).Result() if err == nil && token != utils.StringEmpty { return &AccessTokenResult{AccessToken: token}, nil } body, err := utils.Curl(accessTokenURL).SetData(map[string]string{ "grant_type": "client_credential", "appid": c.AppID, "secret": c.Secret, }).Get("") if err != nil { return nil, err } var result AccessTokenResult if err := jsoniter.UnmarshalFromString(body, &result); err != nil { return nil, err } if result.ErrCode != utils.NumberZero { return nil, fmt.Errorf("wechat access_token: %d %s", result.ErrCode, result.ErrMsg) } if result.AccessToken == utils.StringEmpty { return nil, fmt.Errorf("wechat access_token empty") } expire := time.Duration(result.ExpiresIn-300) * time.Second if expire > 0 { _ = redis.Client.Set(ctx, key, result.AccessToken, expire).Err() } return &result, nil }