package itao import ( "context" "crypto/hmac" "crypto/sha1" "encoding/hex" "github.com/gogf/gf/encoding/gjson" "github.com/gogf/gf/errors/gerror" "github.com/gogf/gf/frame/g" "github.com/gogf/gf/os/gtime" "github.com/gogf/gf/util/gconv" "net/url" "sort" "strings" "time" ) type Config struct { ApiUrl string AppKey string AppSecret string DB int } var server *Config const PkgName = "itao" const CacheKey = "itao:token" const Host = "https://open.huoju6.com/openapi/param2/1/com.huoju6.open/" func New(req *Config) { server = req if server.DB == 0 { server.DB = 10 } return } type CommonRes struct { Success bool `json:"success"` ErrCode string `json:"errCode"` ErrMsg string `json:"errMsg"` } func generate(req string) (res string) { //拼接参数 mac := hmac.New(sha1.New, []byte(server.AppSecret)) mac.Write([]byte(req)) mdStr := hex.EncodeToString(mac.Sum(nil)) res = strings.ToUpper(mdStr) return } func sign(method string, req g.Map) (err error) { var keys []string req["_aop_timestamp"] = gtime.Now().TimestampMilliStr() for k := range req { keys = append(keys, k) } sort.Strings(keys) var signStr string for _, v := range keys { if v != "_aop_signature" { signStr += v signStr += gconv.String(req[v]) } } //拼接参数 signStr = "param2/1/com.huoju6.open/" + method + "/" + server.AppKey + signStr req["_aop_signature"] = generate(signStr) return } func (s *Config) Post(ctx context.Context, method string, params g.Map) (str string, err error) { params["access_token"], err = AccessToken(ctx) if err != nil { return } str, err = Post(ctx, method, params) return } func Post(ctx context.Context, method string, params g.Map) (str string, err error) { Start := gtime.TimestampMilli() err = sign(method, params) if err != nil { return } Url := Host + method + "/" + server.AppKey Request := g.Client() Request.SetHeader("Content-Type", "application/x-www-form-urlencoded") resp, err := Request.Timeout(time.Second*5).Get(Url, params) defer func() { _ = resp.Close() paramStr := gjson.New(params).MustToJsonString() ctx = context.WithValue(ctx, "Method", "POST") ctx = context.WithValue(ctx, "URI", Url) if err != nil { g.Log().Cat(PkgName).Ctx(ctx).Infof("参数【%v】错误【%v】响应时间【%vms】", paramStr, err.Error(), gtime.TimestampMilli()-Start) } else { g.Log().Cat(PkgName).Ctx(ctx).Infof("参数【%v】响应【%v】响应时间【%vms】", paramStr, str, gtime.TimestampMilli()-Start) } }() str = resp.ReadAllString() return } func (s *Config) Get(ctx context.Context, method string, params g.Map) (str string, err error) { params["access_token"], err = AccessToken(ctx) if err != nil { return } str, err = Get(ctx, method, params) return } func Get(ctx context.Context, method string, params g.Map) (str string, err error) { Start := gtime.TimestampMilli() err = sign(method, params) if err != nil { return } Url := Host + method + "/" + server.AppKey Request := g.Client() Values := url.Values{} for k, v := range params { Values.Add(k, gconv.String(v)) } Request.SetHeader("Content-Type", "application/x-www-form-urlencoded") resp, err := Request.Timeout(time.Second * 5).Get(Url + "?" + Values.Encode()) defer func() { _ = resp.Close() paramStr := gjson.New(params).MustToJsonString() ctx = context.WithValue(ctx, "Method", "GET") ctx = context.WithValue(ctx, "URI", Url) if err != nil { g.Log().Cat(PkgName).Ctx(ctx).Infof("参数【%v】错误【%v】响应时间【%vms】", paramStr, err.Error(), gtime.TimestampMilli()-Start) } else { g.Log().Cat(PkgName).Ctx(ctx).Infof("参数【%v】响应【%v】响应时间【%vms】", paramStr, str, gtime.TimestampMilli()-Start) } }() str = resp.ReadAllString() return } func AccessToken(ctx context.Context) (res string, err error) { var conn = g.Redis().Conn() defer func() { _ = conn.Close() }() _, _ = conn.DoVar("SELECT", server.DB) cache, _ := conn.DoVar("HGETALL", CacheKey) if cache.IsEmpty() { g.Log().Ctx(ctx).Cat(PkgName).Line(true).Info("获取token失败") err = gerror.New("获取token失败") return } var result *AuthTokenRes _ = gjson.New(cache).Scan(&result) if result == nil { g.Log().Ctx(ctx).Cat(PkgName).Line(true).Info("获取token失败") err = gerror.New("获取token失败") return } if result.AccessToken == "" || result.AccessTokenExpireTime < gtime.TimestampMilli() { result, err = RefreshToken(ctx) } res = result.AccessToken return } //RefreshToken 刷新 func RefreshToken(ctx context.Context) (res *AuthTokenRes, err error) { var conn = g.Redis().Conn() defer func() { _ = conn.Close() }() _, _ = conn.DoVar("SELECT", server.DB) cache, _ := conn.DoVar("HGETALL", CacheKey) if cache.IsEmpty() { g.Log().Ctx(ctx).Cat(PkgName).Line(true).Info("获取token失败") err = gerror.New("获取token失败") return } _ = gjson.New(cache).Scan(&res) if res.AccessTokenExpireTime > gtime.Now().Add(time.Hour).TimestampMilli() { return } res, err = Auth.Token(ctx, res.RefreshToken, 2) if err != nil { return } if res.Code != "success" { g.Log().Ctx(ctx).Cat(PkgName).Line(true).Info("获取token失败") err = gerror.New("获取token失败") return } _, _ = conn.Do("HMSET", CacheKey, "accessToken", res.AccessToken, "accessTokenExpireTime", res.AccessTokenExpireTime) return }