package dapi import ( "encoding/json" "epur-pay/cache" "epur-pay/model" "epur-pay/pkg/config" "epur-pay/pkg/logger" "epur-pay/pkg/rds" "epur-pay/pkg/utils" "fmt" "github.com/deatil/go-cryptobin/cryptobin/crypto" "net/url" "reflect" "runtime" "strconv" "strings" "sync" "time" ) var LockPool sync.Map func (a *ApiBase) apiHandler() error { if a.paramNum == 1 { a.funcValue.Call(valOf(a)) } else { if err := a.getBody(); err != nil { return err } a.funcValue.Call(valOf(a, a.body)) } return nil } func (a *ApiBase) limitRouterRuleHandler() error { if cache.Global.LimitRouter.Api != nil { key := cache.Global.LimitRouter.Api.Key(a.C) if bucket, ok := cache.Global.LimitRouter.Api.GetBucket(key); ok { count := bucket.TakeAvailable(1) if count == 0 { return a.ReturnPublicErrorResponse(a.Translate("rateLimit")) } } } return nil } func (a *ApiBase) headerHandler() error { //站点处理 a.siteHandler() //币种处理 a.currencyHander() //时区处理 a.localHandler() //分页参数处理 a.pageHandler() //语言处理 a.getLangByAppRequest() //版本管理 if err := a.versionHander(); err != nil { return err } return nil } func (a *ApiBase) siteHandler() { a.Site = a.C.GetHeader("site") } func (a *ApiBase) currencyHander() { a.Currency = a.C.GetHeader("currency") if len(a.Currency) <= 0 { a.Currency = "USD" } } func (a *ApiBase) GetPage() int { page1, _ := a.C.GetQuery("page") page, _ := strconv.Atoi(page1) if page <= 0 { page = 1 } return page } func (a *ApiBase) pageHandler() { page1, _ := a.C.GetQuery("page") size1, _ := a.C.GetQuery("size") page, _ := strconv.Atoi(page1) limit, _ := strconv.Atoi(size1) if page <= 0 { page = 1 } if limit >= 100 { limit = 100 } else if limit <= 0 { limit = 20 } a.Limit = limit a.Offset = (page - 1) * limit } func (a *ApiBase) localHandler() { var err error a.Local, err = time.LoadLocation(a.C.GetHeader("Timezone")) //等同于"UTC" if err != nil { a.Local = nil } if len(a.C.GetHeader("Timezone")) == 0 { a.Local = nil } } func (a *ApiBase) getBody() error { if a.C.Request.Method == "POST" || a.C.Request.Method == "PUT" || a.C.Request.Method == "PATCH" { row, err := a.C.GetRawData() if err != nil { logger.ErrorLogger.Errorln(err.Error()) return err } var data string data = string(row) if config.Cf.Common.RunMode == "debug" { logger.AccessLogger.Infof("%s 请求数据 -> %s", a.C.FullPath(), data) } if a.Log != nil && a.Log.Event != "登陆" { a.Log.Data = data } err = json.Unmarshal([]byte(data), &a.body) if err != nil { logger.AccessLogger.Errorf("===> BindJSON: %s", a.Translate("param_fail")) return a.ReturnErrorResponse(InvalidParams, a.Translate("param_fail")) } if a.InParams.IsErrors { var errMsg []string ValidateField(a.body, func(typeOfCat reflect.Type, fieldName string) { field, ok := typeOfCat.FieldByName(fieldName) //通过反射获取filed if ok { errMsg = append(errMsg, a.Translate(field.Tag.Get("label"))) } }) if len(errMsg) > 0 { return a.ReturnErrorResponse(InvalidParams, strings.Join(errMsg, ",")) } } else { var errMsg string ValidateField(a.body, func(typeOfCat reflect.Type, fieldName string) { field, ok := typeOfCat.FieldByName(fieldName) //通过反射获取filed if ok { errMsg = field.Tag.Get("label") return } }) if len(errMsg) > 0 { return a.ReturnErrorResponse(InvalidParams, a.Translate(errMsg)) } } } return nil } func valOf(i ...interface{}) []reflect.Value { var rt []reflect.Value for _, i2 := range i { rt = append(rt, reflect.ValueOf(i2)) } return rt } func (a *ApiBase) ClientIp() string { ip := a.C.Request.Header.Get("Cf-Connecting-Ip") if len(ip) <= 0 { ip = a.C.Request.Header.Get("X-Real-Ip") } if len(ip) <= 0 { ip = a.C.ClientIP() } return ip } func (a *ApiBase) Translate(key string) string { return cache.Global.Caches.Language.GetLang(a.Lang, key) } func (a *ApiBase) RefreshCache(key string) error { return Cf.ApiRefreshCache(key) } func (a *ApiBase) authHandler() error { if a.InParams.IsTicket || a.InParams.IsTicketSkip { if err := a.getUser(a.C.Request.Header.Get("Token")); err != nil { return err } } return nil } func (a *ApiBase) getUser(token string) error { var uid int64 a.Token = token if a.InParams.IsTicket && len(a.Token) <= 0 { return a.ReturnErrorResponse(600, a.Translate("reset_login")) } else if len(a.Token) > 0 { //logger.AccessLogger.Infoln("---> getUser DecryptToken ", a.Token) t, e := DecryptToken(a.Token) if !e { if a.InParams.IsTicket { return a.ReturnErrorResponse(600, a.Translate("not_found")) } } else { uid, _ = strconv.ParseInt(strings.Split(t, ",")[0], 10, 64) } } if uid > 0 { a.User = cache.Global.Caches.User.Get(uid) if a.User == nil { //解决用户被删除后token无效的问题 if a.InParams.IsTicket { return a.ReturnErrorResponse(600, a.Translate("reset_login")) } else { return nil } } if a.User.Detail.Token != a.Token { if a.InParams.IsTicket { return a.ReturnErrorResponse(600, a.Translate("reset_login")) } else { a.User = nil return nil } } if a.User.Uid <= 0 { if a.InParams.IsTicket { return a.ReturnErrorResponse(600, a.Translate("not_found")) } else { a.User = nil return nil } } // 如果必须是超级权限操作,需要判断是否存在权限ID=1的数据 //!a.User.RoleIds.Of(1) if a.InParams.IsSuperOnly && a.User.Uid != 1 { logger.AccessLogger.Errorf("---> Uid: [%d] Super权限错误 %s", a.User.Uid, a.InParams.Permission) return a.ReturnErrorResponse(602, a.Translate("AT004")) } // 这里验证用户是否拥有接口操作权限 if len(a.InParams.Permission) > 0 { if !cache.Global.Caches.RolePermission.Check(a.User.RoleIds, a.InParams.Permission) { logger.AccessLogger.Errorf("---> Uid: [%d] 尚无权限: [%s] %v", a.User.Uid, a.InParams.Permission, a.User.RoleIds) return a.ReturnPublicErrorResponse(a.Translate("AT058")) } } if a.User.Status != "0" { if a.InParams.IsTicket || (a.InParams.IsTicketSkip && a.User != nil) { if !a.InParams.IsNoCheckBlackList { return a.ReturnErrorResponse(602, a.Translate("black_list")) } } else { a.User = nil return nil } } } return nil } func (a *ApiBase) lockTrade() error { //logger.AccessLogger.Infof("params:%+v user:%+v", a.InParams.IsLockTradeForMerchant, a.User) if a.InParams.IsForUpdate && a.User != nil { if _, ok := LockPool.Load(fmt.Sprintf("%s%d", a.C.FullPath(), a.User.Uid)); ok { return a.ReturnPublicErrorResponse(a.Translate("LLLP")) } else { LockPool.Store(fmt.Sprintf("%s%d", a.C.FullPath(), a.User.Uid), true) } } return nil } func (a *ApiBase) freeTrade() { if a.InParams.IsForUpdate && a.User != nil { LockPool.Delete(fmt.Sprintf("%s%d", a.C.FullPath(), a.User.Uid)) } } func (a *ApiBase) saveLog() { defer func() { err := recover() if err != nil { buf := make([]byte, 1<<16) runtime.Stack(buf, true) e := reflect.ValueOf(err) logger.ErrorLogger.Errorln(e.String()) } }() //logger.AccessLogger.Warnln(a.Error, a.InParams.IsSkipErrorSaveLog) if a.Log != nil && a.Log.Uid > 0 && (a.Error == nil || a.InParams.IsSkipErrorSaveLog) { // 如果是super操作也记录 if a.Log.Name == "super" && a.Log.UserType == "1" { a.Log.IsSuper = "1" a.Log.Ip = "" } a.Log.A1 = cache.GetIpAddress(a.Log.Ip) if a.Error != nil { a.Log.Event = fmt.Sprintf("%s(失败)", a.Log.Event) } if err := rds.DB.Create(a.Log).Error; err != nil { logger.ErrorLogger.Errorln(err.Error()) } } } func (a *ApiBase) getLangByAppRequest() { lan := a.C.Request.Header.Get("Language") languageCode := "" countryCode := "" if len(strings.Split(lan, "_")) > 1 { languageCode = strings.Split(lan, "_")[0] countryCode = strings.Split(lan, "_")[1] } row := "" tmpLanguageCodes := make([]model.SysLanguage, 0) for _, v := range cache.Global.Caches.Language.List { if v.LanguageCode == languageCode { tmpLanguageCodes = append(tmpLanguageCodes, v) } } isFind := false for _, v := range tmpLanguageCodes { if v.CountryCode == countryCode { isFind = true row = fmt.Sprintf("%s_%s", v.LanguageCode, v.CountryCode) break } } if !isFind && len(tmpLanguageCodes) > 0 { row = fmt.Sprintf("%s_%s", tmpLanguageCodes[0].LanguageCode, tmpLanguageCodes[0].CountryCode) } if len(row) <= 0 { row = cache.Global.Caches.Language.DefaultLanguage } if len(row) <= 0 { row = "en_US" } a.Lang = row } func (a *ApiBase) versionHander() error { appVersion := a.C.Request.Header.Get("appversion") { var version *model.Version if a.Site == "h5Pc" { version = cache.Global.Caches.Version.Get("2") } else if a.Site == "h5App" { version = cache.Global.Caches.Version.Get("1") } else if a.Site == "h5Admin" { version = cache.Global.Caches.Version.Get("0") } if version != nil && version.Id > 0 { if len(appVersion) > 0 { requestVersion, err := strconv.ParseInt(appVersion, 10, 64) if err != nil { logger.AccessLogger.Errorln("requestVersion version error", appVersion) return nil } currVersion, err := strconv.ParseInt(version.Version, 10, 64) if err != nil { logger.AccessLogger.Errorln("currVersion version error", version.Version) return nil } if currVersion > requestVersion && version.Force == "0" { return a.ReturnErrorResponse(920, a.Translate("versionUpdateing")) } } } } return nil } // 加密 func EncryptToken(uid int64) string { return url.QueryEscape(crypto.FromString(fmt.Sprintf("%d,%d", uid, utils.Time2StampSecond()+24*60*60)). SetKey("dfertf12dfertf12"). SetIv("dfertf12dfertf12"). Aes(). CBC(). PKCS7Padding(). Encrypt(). ToBase64String()) } func DecryptToken(token string) (string, bool) { token, _ = url.QueryUnescape(token) cyptde := crypto. FromBase64String(token). SetKey("dfertf12dfertf12"). SetIv("dfertf12dfertf12"). Aes(). CBC(). PKCS7Padding(). Decrypt(). ToString() if len(cyptde) <= 0 { return "", false } return cyptde, true }