package gome import ( "context" "errors" "github.com/gogf/gf/crypto/gmd5" "github.com/gogf/gf/encoding/gjson" "github.com/gogf/gf/frame/g" "github.com/gogf/gf/os/gtime" "github.com/gogf/gf/text/gstr" "github.com/gogf/gf/util/gconv" "github.com/gogf/gf/util/gutil" "gitlab.jxhh.com/stbz/library.git/logs" "time" ) type Config struct { ApiUrl string AppKey string AppSecret string Version string } type Client struct { *Config AccessToken string RefreshToken string } type CommonReq struct { AppKey string `json:"app_key"` Version string `json:"version"` Method string `json:"method"` AccessToken string `json:"access_token"` Timestamp string `json:"timestamp"` Param interface{} `json:"param"` Sign string `json:"sign,omitempty"` } type CommonPageReq struct { PageNo int `json:"pageNo"` PageSize int `json:"pageSize"` } type CommonPageRes struct { PageSize int `json:"pageSize"` PageNo int `json:"pageNo"` TotalPage int `json:"totalPage"` TotalCount int `json:"totalCount"` } type CommonRes struct { Code string `json:"code"` Message string `json:"message"` SubCode string `json:"sub_code"` SubMsg string `json:"sub_msg"` } var server *Client const pkgName = "gome" const CacheKey = "gome:token" func New(config *Config) { _ = gconv.Struct(config, &server) return } func (s *Client) sign(req g.Map) string { data := gjson.New(req) _ = data.Remove("sign") return gstr.ToUpper(gmd5.MustEncryptString(server.AppSecret + data.MustToJsonString() + server.AppSecret)) } func (s *Client) post(ctx context.Context, method string, req interface{}) (str string, err error) { Start := gtime.TimestampMilli() allparams := &CommonReq{ AppKey: server.AppKey, Version: server.Version, Method: method, AccessToken: server.AccessToken, Timestamp: gtime.Now().String(), Param: req, } allparams.Sign = s.sign(gconv.Map(allparams)) Request := g.Client() Request.SetHeader("Content-Type", "application/json") resp, err := Request.Timeout(time.Second*5).Post(server.ApiUrl, allparams) defer func() { paramStr := gjson.New(req).MustToJsonString() ctx = context.WithValue(ctx, "Method", "POST") ctx = context.WithValue(ctx, "URI", method) if err != nil { logs.Errorf(ctx, pkgName, logs.FormatErr, paramStr, err.Error(), gtime.TimestampMilli()-Start) } else { logs.Infof(ctx, pkgName, logs.FormatSuc, paramStr, str, gtime.TimestampMilli()-Start) } }() str = resp.ReadAllString() return } func (s *Client) requestApi(ctx context.Context, method string, req interface{}) (str string, err error) { err = s.getAccessToken(ctx) if err != nil { return } str, err = s.post(ctx, method, req) return } type accessToken struct { AppKey string `json:"appKey"` AccessToken string `json:"access_token"` RefreshToken string `json:"refresh_token"` ExpiresInSeconds int64 `json:"expiresInSeconds"` CreateTime string `json:"createTime"` } //getAccessToken 获取token func (s *Client) getAccessToken(ctx context.Context) (err error) { var token *accessToken cache, _ := g.Redis().DoVar("HGETALL", CacheKey) if !cache.IsEmpty() { _ = cache.Scan(&token) if gtime.NewFromStr(token.CreateTime).Timestamp()+token.ExpiresInSeconds > gtime.Timestamp()-3600 { s.AccessToken = token.AccessToken return } return s.refreshToken(ctx, token) } res, err := Token.Get(ctx) if err != nil { return } if res.Code != "4000" { err = errors.New(res.Message) return } _, _ = g.Redis().Do("HMSET", append(g.Slice{CacheKey}, gutil.MapToSlice(gconv.Map(res.Data))...)...) s.AccessToken = res.Data.AccessToken return } //refreshToken 刷新token func (s *Client) refreshToken(ctx context.Context, req *accessToken) (err error) { if gtime.NewFromStr(req.CreateTime).Timestamp()+req.ExpiresInSeconds < gtime.Timestamp() { _, err = g.Redis().DoVar("DEL", CacheKey) return s.getAccessToken(ctx) } res, err := Token.Refresh(ctx, req.RefreshToken) if err != nil { return } if res.Code != "4000" { err = errors.New(res.Message) return } _, _ = g.Redis().Do("HMSET", append(g.Slice{CacheKey}, gutil.MapToSlice(gconv.Map(res.Data))...)...) s.AccessToken = res.Data.AccessToken return }