package tasks import ( "fmt" "time" "git.rosy.net.cn/jx-callback/business/legacymodel" "git.rosy.net.cn/jx-callback/globals/api" "git.rosy.net.cn/baseapi/utils" "git.rosy.net.cn/jx-callback/globals" "git.rosy.net.cn/jx-callback/legacy/freshfood" "github.com/astaxie/beego/orm" ) const ( weixinTokenExpires = 7200 * time.Second elmTokenExpires = 20 * 24 * 3600 * time.Second maxRefreshGap = 5 * 60 * time.Second ) type ElmTokenForCompatible struct { Error string `json:"error"` ErrorDescription string `json:"error_description"` AccessToken string `json:"accessToken"` TokenType string `json:"tokenType"` Expires int `json:"expires"` RefreshToken string `json:"refreshToken"` Success bool `json:"success"` } func RefreshConfig(configKey string, expiresTime time.Duration, configGetter func() string, configSetter func(value string)) error { sleepGap := expiresTime / 10 needRefreshGap := expiresTime * 8 / 10 if sleepGap > maxRefreshGap { sleepGap = maxRefreshGap } refreshFunc := func() (string, error) { curConfig := &legacymodel.Config{ Thirdparty: configKey, } db := orm.NewOrm() // 0: don't refresh, 1 update, 2 insert handleType := 0 if err := db.Read(curConfig, "Thirdparty"); err != nil { if err != orm.ErrNoRows { globals.SugarLogger.Errorf("db error:%v, curConfig:%v", err, curConfig) return "", err } handleType = 2 } else if curConfig.Date <= utils.Time2Str(time.Now().Add(-needRefreshGap)) { handleType = 1 } if handleType != 0 { if curConfig.Token = configGetter(); curConfig.Token == "" { return "", fmt.Errorf("can not get token for %s", configKey) } globals.SugarLogger.Debugf("refresh %s, value:%s", configKey, curConfig.Token) curConfig.Date = utils.GetCurTimeStr() var num int64 var err error if handleType == 1 { num, err = db.Update(curConfig, "Token", "Date") } else { num, err = db.Insert(curConfig) } if err != nil || num == 0 { globals.SugarLogger.Errorf("db error:%v, num:%d, curConfig:%v", err, num, curConfig) return "", err } else { configSetter(curConfig.Token) } } return curConfig.Token, nil } token, err := refreshFunc() // 这样写的目的是强制第一次调用时要刷新一次 if err == nil { configSetter(token) go func() { for { time.Sleep(sleepGap) refreshFunc() } }() } return err } func RefreshWeixinToken() error { return RefreshConfig("wechat", weixinTokenExpires, func() string { if tokenInfo, err := api.WeixinAPI.RefreshToken(); err == nil { return tokenInfo.AccessToken } return "" }, func(value string) { api.WeixinAPI.SetToken(value) freshfood.FreshFoodAPI.RefreshWeixinToken() }) } func RefreshElmToken() error { return RefreshConfig("eleme", elmTokenExpires, func() string { if tokenInfo, err := api.ElmAPI.RefreshTokenIndividual(); err == nil { tokenInfo2 := &ElmTokenForCompatible{ Error: "", ErrorDescription: "", AccessToken: tokenInfo.AccessToken, TokenType: tokenInfo.TokenType, Expires: tokenInfo.ExpiresIn, RefreshToken: "", Success: true, } return string(utils.MustMarshal(tokenInfo2)) } return "" }, func(value string) { var tokenInfo ElmTokenForCompatible err := utils.UnmarshalUseNumber([]byte(value), &tokenInfo) if err == nil { api.ElmAPI.SetToken(tokenInfo.AccessToken) freshfood.FreshFoodAPI.RefreshElmToken() } }) }