/** * 系统工具类 * @author * @since 2021/8/25 * @File : utils */ package utils import ( "crypto/md5" "encoding/hex" "encoding/json" "errors" "fmt" "github.com/gin-contrib/sessions" "github.com/gin-gonic/gin" "github.com/gogf/gf/container/garray" "gitlab.52pay.top/go/easygoadmin/library/cfg" "gitlab.52pay.top/go/easygoadmin/utils/gconv" "gitlab.52pay.top/go/easygoadmin/utils/gmd5" "gitlab.52pay.top/go/easygoadmin/utils/gstr" "log" "os" "regexp" "strconv" "strings" "time" ) // 调试模式 func AppDebug() bool { // 获取配置实例 config := cfg.Instance() return config.EasyGoAdmin.Debug } // 登录用户ID func Uid(ctx *gin.Context) int { // 初始化session对象 session := sessions.Default(ctx) // 获取用户ID userId := gconv.Int(session.Get("userId")) // 返回用户ID return userId } // 判断用户登录状态 func IsLogin(ctx *gin.Context) bool { // 初始化session对象 session := sessions.Default(ctx) // 获取用户ID userId := session.Get("userId") return userId != nil } // 检测用户签名 func CheckSign(ctx *gin.Context) bool { ctx.Request.ParseForm() dataMap := make(map[string]string) sign := "" appId := "" //说明:须post方法,加: 'Content-Type': 'application/x-www-form-urlencoded' for key := range ctx.Request.PostForm { if key == "sign" { sign = ctx.PostForm(key) } if key == "app_id" { appId = ctx.PostForm(key) } dataMap[key] = ctx.PostForm(key) } // for key := range ctx.Request.URL.Query() { if key == "sign" { sign = ctx.Query(key) } if key == "app_id" { appId = ctx.Query(key) } dataMap[key] = ctx.Query(key) } if len(dataMap) < 0 || sign == "" { return false } keyArray := garray.NewStrArray() for key := range dataMap { if key == "sign" { continue } keyArray.Append(key) } secret := GetAppSecret(ctx, appId) if secret == "" { return false } newSign := GetNewSign(dataMap, keyArray, secret) if newSign != sign { return false } return true } // 获取签名 func GetNewSign(dataMap map[string]string, keyArray *garray.StrArray, secret string) string { keyArray.Sort() str := "" keyArray.Iterator(func(k int, v string) bool { val := dataMap[v] tmp := fmt.Sprintf("%s=%s", v, val) if k == 0 { str = tmp } else { str = fmt.Sprintf("%s&%s", str, tmp) } return true }) str = fmt.Sprintf("%s&key=%s", str, secret) d := []byte(str) m := md5.New() m.Write(d) newSign := hex.EncodeToString(m.Sum(nil)) newSign = strings.ToUpper(newSign) return newSign } type PbSettingAppUtils struct { Id int `json:"id" xorm:"not null pk autoincr comment('主键ID') INT(10)"` AppId string `json:"app_id"` AppName string `json:"app_name"` Phone string `json:"phone"` AppKey string `json:"app_key"` Status int64 `json:"status"` CouponSmsContent string `json:"coupon_sms_content"` ServiceAddress string `json:"service_address"` ComName string `json:"com_name"` FilingNo string `json:"filing_no"` } func (r *PbSettingAppUtils) TableName() string { return "pb_setting_app" } // 根据 appid 获取 appSecret func GetAppSecret(ctx *gin.Context, appId string) string { cache := GetRedisHelper() cacheKey := fmt.Sprintf("Utils:GetAppSecretV2:%s", appId) val := cache.Get(ctx, cacheKey).Val() if val != "" { return val } var info PbSettingAppUtils _, err := XormDb.Where("app_id = ?", appId).Get(&info) if err != nil { return "" } cache.Set(ctx, cacheKey, info.AppKey, 3*time.Minute) return info.AppKey } // 根据 appid 获取 appSecret func GetAppInfo(ctx *gin.Context, appId string) PbSettingAppUtils { cache := GetRedisHelper() cacheKey := fmt.Sprintf("Utils:GetAppInfo:V2:%s", appId) val := cache.Get(ctx, cacheKey).Val() var info PbSettingAppUtils if val != "" { json.Unmarshal([]byte(val), &info) return info } _, err := XormDb.Where("app_id = ?", appId).Get(&info) if err != nil { return PbSettingAppUtils{} } jsonStr, _ := json.Marshal(info) cache.Set(ctx, cacheKey, jsonStr, 4*time.Minute) return info } // 获取数据库表 func GetDatabase() (string, error) { config := cfg.Instance() if config == nil { fmt.Printf("参数错误") } // 获取数据库连接 link := config.Database.Master if link == "" { return "", errors.New("数据库配置读取错误") } // 分裂字符串 linkArr := strings.Split(link, "/") return strings.Split(linkArr[1], "?")[0], nil } func Md5(password string) (string, error) { // 第一次MD5加密 password, err := gmd5.Encrypt(password) if err != nil { return "", err } // 第二次MD5加密 password2, err := gmd5.Encrypt(password) if err != nil { return "", err } return password2, nil } // 数组反转 func Reverse(arr *[]string) { length := len(*arr) var temp string for i := 0; i < length/2; i++ { temp = (*arr)[i] (*arr)[i] = (*arr)[length-1-i] (*arr)[length-1-i] = temp } } // 获取客户端IP func GetClientIp(ctx *gin.Context) string { ip := ctx.Request.Header.Get("X-Forwarded-For") if ip == "" { ip = ctx.ClientIP() } return ip } func ImageUrl() string { // 获取配置实例 config := cfg.Instance() return config.EasyGoAdmin.Image } // 获取文件地址 func GetImageUrl(path string) string { parts := strings.Split(path, ",") var urls []string for _, part := range parts { urls = append(urls, ImageUrl()+part) } return strings.Join(urls, ",") } func InStringArray(value string, array []string) bool { for _, v := range array { if v == value { return true } } return false } // 判断元素是否在数组中 func InArray(value string, array []interface{}) bool { for _, v := range array { if gconv.String(v) == value { return true } } return false } // 附件目录 func UploadPath() string { // 获取配置实例 config := cfg.Instance() // 附件存储路径 upload_dir := config.EasyGoAdmin.Uploads if upload_dir != "" { return upload_dir } else { // 获取项目根目录 curDir, _ := os.Getwd() return curDir + "/public/uploads" } } // 临时目录 func TempPath() string { return UploadPath() + "/temp" } // 图片存放目录 func ImagePath() string { return UploadPath() + "/images" } // 文件目录(非图片目录) func FilePath() string { return UploadPath() + "/file" } // 创建文件夹并设置权限 func CreateDir(path string) bool { // 判断文件夹是否存在 if IsExist(path) { return true } // 创建多层级目录 err2 := os.MkdirAll(path, os.ModePerm) if err2 != nil { log.Println(err2) return false } return true } // 判断文件/文件夹是否存在(返回true是存在) func IsExist(path string) bool { // 读取文件信息,判断文件是否存在 _, err := os.Stat(path) if err != nil { log.Println(err) if os.IsExist(err) { // 根据错误类型进行判断 return true } return false } return true } func SaveImage(url string, dirname string) (string, error) { // 判断文件地址是否为空 if gstr.Equal(url, "") { return "", errors.New("文件地址不能为空") } // 判断是否本站图片 if gstr.Contains(url, ImageUrl()) { // 本站图片 // 是否临时图片 if gstr.Contains(url, "temp") { // 临时图片 // 创建目录 dirPath := ImagePath() + "/" + dirname + "/" + time.Now().Format("20060102") if !CreateDir(dirPath) { return "", errors.New("文件目录创建失败") } // 原始图片地址 oldPath := gstr.Replace(url, ImageUrl(), UploadPath()) // 目标目录地址 newPath := ImagePath() + "/" + dirname + gstr.Replace(url, ImageUrl()+"/temp", "") // 移动文件 os.Rename(oldPath, newPath) return gstr.Replace(newPath, UploadPath(), ""), nil } else { // 非临时图片 path := gstr.Replace(url, ImageUrl(), "") return path, nil } } else { // 远程图片 // TODO... } return "", errors.New("保存文件异常") } // 处理富文本 func SaveImageContent(content string, title string, dirname string) string { str := ` total { return } // 到末尾 if length < 0 { length = total } end := start + length if end > total { result = string(s[start:]) } else { result = string(s[start:end]) } return } func FloatToInt(f float64) int { i, _ := strconv.Atoi(fmt.Sprintf("%1.0f", f)) return i }