You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

459 lines
10 KiB

1 month ago
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
}