package common import ( "crypto/hmac" "crypto/md5" "crypto/sha256" "designs/config" "designs/global" "encoding/hex" "encoding/json" "errors" "fmt" "math/rand" "net/http" "net/url" "sort" "strconv" "strings" "time" "github.com/gin-gonic/gin" "github.com/golang-jwt/jwt/v5" ) // 打印 func Print(i interface{}) { fmt.Println("---") fmt.Println(i) fmt.Println("---") } // 返回JSON func RetJson(code int, msg string, data interface{}, c *gin.Context) { c.JSON(http.StatusOK, gin.H{ "code": code, "msg": msg, "data": data, "timestamp": GetTimeUnix(), }) c.Abort() } // 获取当前时间戳 func GetTimeUnix() int64 { return time.Now().Unix() } // MD5 方法 func MD5(str string) string { s := md5.New() s.Write([]byte(str)) return hex.EncodeToString(s.Sum(nil)) } // 生成签名 func CreateSign(params url.Values) string { var key []string var str = "" for k := range params { if k != "sn" { key = append(key, k) } } sort.Strings(key) for i := 0; i < len(key); i++ { if i == 0 { str = fmt.Sprintf("%v=%v", key[i], params.Get(key[i])) } else { str = str + fmt.Sprintf("&%v=%v", key[i], params.Get(key[i])) } } // 自定义签名算法 sign := MD5(MD5(str) + MD5(config.Get("app_name")+config.Get("app_secret"))) return sign } // 验证签名 func VerifySign(c *gin.Context) { var method = c.Request.Method var ts int64 var sn string var req url.Values if method == "GET" { req = c.Request.URL.Query() sn = c.Query("sn") ts, _ = strconv.ParseInt(c.Query("ts"), 10, 64) } else if method == "POST" { c.Request.ParseForm() req = c.Request.PostForm sn = c.PostForm("sn") ts, _ = strconv.ParseInt(c.PostForm("ts"), 10, 64) } else { RetJson(500, "Illegal requests", "", c) return } exp, _ := strconv.ParseInt(config.Get("api_expire"), 10, 64) // 验证过期时间 if ts > GetTimeUnix() || GetTimeUnix()-ts >= exp { RetJson(500, "Ts Error", "", c) return } // 验证签名 if sn == "" || sn != CreateSign(req) { RetJson(500, "Sn Error", "", c) return } } func StructToArr(data interface{}) (string, error) { res, err := json.Marshal(data) if err != nil { return "", err } //将json解析为map var mapdata map[string]interface{} err1 := json.Unmarshal([]byte(res), &mapdata) if err1 != nil { return "", err1 } //获取排序map键值 keys := make([]string, 0, len(mapdata)) for key := range mapdata { keys = append(keys, key) } //排序 sort.Strings(keys) fmt.Println("我的数据:", string(res)) //排序后直接构建map sortMap := make(map[string]interface{}, len(mapdata)) for _, key := range keys { sortMap[key] = mapdata[key] } //序列化 sortJosn, err2 := json.Marshal(sortMap) if err2 != nil { return "", err2 } return string(sortJosn), nil } /* 检测数据是否篡改 */ func VerifySignData(data interface{}) bool { var checkSign string var sign string = "test" checkKey := "secret" res, err := json.Marshal(data) if err != nil { return false } //将json解析为map var mapdata map[string]interface{} err1 := json.Unmarshal([]byte(res), &mapdata) if err1 != nil { return false } //fmt.Println("解析后的数据:", mapdata) val, exist := mapdata[checkKey].(string) if exist { checkSign = val } else { return false } fmt.Println("解析后的数据:", mapdata) //获取排序map键值 keys := make([]string, 0, len(mapdata)) for key := range mapdata { if key != checkKey { keys = append(keys, key) } } // fmt.Println("解析后的keys数据:", keys) //排序 sort.Strings(keys) //排序后直接构建map sortMap := make(map[string]interface{}, len(mapdata)) for _, key := range keys { newKey := strings.ToLower(string(key[0])) + key[1:] sortMap[newKey] = mapdata[key] } //序列化数据 sortJosn, err2 := json.Marshal(sortMap) if err2 != nil { return false } // fmt.Println("我的排序数据:", string(sortJosn), sign) // sum := ([]byte("hello world")) // fmt.Printf("加密数据:%x\n", sum) // 密钥 key := []byte(config.Get("app.app_check_secret")) // 数据 // data := []byte(msg) // 创建一个新的HMAC将SHA-256用作哈希函数 h := hmac.New(sha256.New, key) // 写入数据 h.Write(sortJosn) // 得到MAC mac := h.Sum(nil) sign = hex.EncodeToString(mac) // 打印MAC fmt.Println("生成的签名:", sign, checkSign) if sign != checkSign { global.App.Log.Error("mapdata:", mapdata) global.App.Log.Error("sign:", sign) global.App.Log.Error("checkSign:", checkSign) } return sign == checkSign } // 生成token func GetDefineToken(openid string) string { timestamp := time.Now().UnixNano() / int64(time.Millisecond) randNum := 10000 + rand.Intn(10000) token := fmt.Sprintf("%s%d%d", openid, timestamp, randNum) return MD5(token) } // 自定义结构体 type MyCustomClaims struct { OpenId string `json:"openid"` Gid string `json:"gid"` Pf string `json:"pf"` TokenType int `json:"tokenType"` //0 token 登录 1:刷新token jwt.RegisteredClaims } // 生成jwt token func GetJwtToken(openId string, gid string, pf string, tokenType int) (string, error) { mySigningKey := []byte(config.Get("app.JwtSecret")) timeData := time.Second if tokenType == 0 { timeData = time.Duration(config.GetInt("app.api_exp")) * time.Second } else { timeData = 24 * time.Hour } claims := MyCustomClaims{ openId, gid, pf, tokenType, jwt.RegisteredClaims{ // A usual scenario is to set the expiration time relative to the current time ExpiresAt: jwt.NewNumericDate(time.Now().Add(timeData)), IssuedAt: jwt.NewNumericDate(time.Now()), NotBefore: jwt.NewNumericDate(time.Now()), Issuer: "test", Subject: "somebody", ID: "1", Audience: []string{"somebody_else"}, }, } token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims) ss, err := token.SignedString(mySigningKey) return ss, err } /* 解析jwt */ func ParseJwtWithClaims(tokenString string) (string, string, string, int) { token, err := jwt.ParseWithClaims(tokenString, &MyCustomClaims{}, func(token *jwt.Token) (interface{}, error) { return []byte(config.Get("app.JwtSecret")), nil }) if err != nil { // fmt.Println(err) return "", "", "", 0 } else if claims, ok := token.Claims.(*MyCustomClaims); ok { // fmt.Println(claims.OpenId, claims.RegisteredClaims.Issuer) return claims.OpenId, claims.Gid, claims.Pf, claims.TokenType } else { // fmt.Println("unknown claims type, cannot proceed") return "", "", "", 0 } } // 刷新Token func RefreshToken(oldToken string) (string, error) { token, err := jwt.Parse(oldToken, func(*jwt.Token) (interface{}, error) { return config.Get("app.JwtSecret"), nil }) if err != nil { return "", err } if claims, ok := token.Claims.(jwt.MapClaims); ok && token.Valid { claims["exp"] = time.Now().Add(time.Duration(config.GetInt("app.api_exp")) * time.Second).Unix() // 更新过期时间 return jwt.NewWithClaims(jwt.SigningMethodHS256, claims).SignedString(config.Get("app.JwtSecret")) } return "", err } // 返回剩余时间 func GetRemainderTime(timeType int) (time.Duration, error) { var remaining time.Duration err := errors.New("发生错误") //获取当前时间 now := time.Now() switch timeType { case 2: //计算本日剩余时间 endOfDay := time.Date(now.Year(), now.Month(), now.Day(), 23, 59, 59, 0, now.Location()) remaining = endOfDay.Sub(now) case 3: //计算本周剩余时间 daysUntiEndOfWeek := 6 - now.Weekday() endOfWeek := time.Date(now.Year(), now.Month(), now.Day()+int(daysUntiEndOfWeek), 23, 59, 59, 0, now.Location()) remaining = endOfWeek.Sub(now) case 4: //计算本月剩余时间 // endOfMonth := time.Date(now.Year(), now.Month()+1, 1, 0, 0, 0, 0, now.Location()).Add(-time.Second) // remaining = endOfMonth.Sub(now) nextMonth := now.AddDate(0, 1, 0) endOfMonth := time.Date(nextMonth.Year(), nextMonth.Month(), 1, 0, 0, 0, 0, nextMonth.Location()).Add(-time.Second) remaining = endOfMonth.Sub(now) default: return remaining, err } // fmt.Printf("Remaning day data:%v\n", remaining) // fmt.Printf("Remaning week data:%v\n", remaining) // fmt.Printf("Remaning month data:%v\n", remaining) return remaining, nil }