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

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

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
}