package validator import ( "encoding/json" "errors" "fmt" "regexp" "strconv" "strings" "time" "github.com/go-playground/validator/v10" ) var validate *validator.Validate // 初始化自定义校验器 func init() { validate = validator.New() if err := validate.RegisterValidation("validName", validName); err != nil { panic(fmt.Sprintf("注册 validName 验证器时发生错误: %v", err)) } // 注册自定义验证器 validMobileNo if err := validate.RegisterValidation("validMobileNo", validMobileNo); err != nil { panic(fmt.Sprintf("注册 validMobileNo 验证器时发生错误: %v", err)) } // 注册自定义验证器 validDate if err := validate.RegisterValidation("validDate", validDate); err != nil { panic(fmt.Sprintf("注册 validDate 验证器时发生错误: %v", err)) } // 注册自定义验证器 validIDCard if err := validate.RegisterValidation("validIDCard", validIDCard); err != nil { panic(fmt.Sprintf("注册 validIDCard 验证器时发生错误: %v", err)) } // 注册自定义验证器 validTimeRange if err := validate.RegisterValidation("validTimeRange", validTimeRange); err != nil { panic(fmt.Sprintf("注册 validTimeRange 验证器时发生错误: %v", err)) } if err := validate.RegisterValidation("validBankCard", validBankCard); err != nil { panic(fmt.Sprintf("注册 validBankCard 验证器时发生错误: %v", err)) } if err := validate.RegisterValidation("validUSCI", validUSCI); err != nil { panic(fmt.Sprintf("注册 validUSCI 验证器时发生错误: %v", err)) } if err := validate.RegisterValidation("validMobileType", validMobileType); err != nil { panic(fmt.Sprintf("注册 validMobileType 验证器时发生错误: %v", err)) } // 注册自定义验证器 validAuthDate if err := validate.RegisterValidation("validAuthDate", validAuthDate); err != nil { panic(fmt.Sprintf("注册 validAuthDate 验证器时发生错误: %v", err)) } } // ValidateAndParse 封装了解密、解析和校验逻辑 func ValidateAndParse(decryptData []byte, req interface{}) error { // 解析解密后的 JSON 数据 if err := json.Unmarshal(decryptData, req); err != nil { return errors.New("解密后的数据格式不正确") } // 校验 v := GetValidator() if err := v.Struct(req); err != nil { for _, validationErr := range err.(validator.ValidationErrors) { field := validationErr.StructField() tag := validationErr.Tag() return errors.New(GetErrorMessage(field, tag)) } } // 如果没有错误,返回 nil return nil } func ValidateAuthDate(date string) error { // 校验日期格式是否为 yyyyMMdd-yyyyMMdd validDateRangePattern := `^\d{4}(0[1-9]|1[0-2])(0[1-9]|[12][0-9]|3[01])-\d{4}(0[1-9]|1[0-2])(0[1-9]|[12][0-9]|3[01])$` matched, _ := regexp.MatchString(validDateRangePattern, date) if !matched { return errors.New("日期范围格式错误,应为yyyyMMdd-yyyyMMdd") } // 分割开始和结束日期 parts := strings.Split(date, "-") if len(parts) != 2 { return errors.New("日期范围格式错误,应为yyyyMMdd-yyyyMMdd") } startDateStr, endDateStr := parts[0], parts[1] // 解析开始日期 startDate, err := time.Parse("20060102", startDateStr) if err != nil { return errors.New("开始日期格式错误") } // 解析结束日期 endDate, err := time.Parse("20060102", endDateStr) if err != nil { return errors.New("结束日期格式错误") } // 校验开始日期不大于结束日期 if startDate.After(endDate) { return errors.New("开始日期不能大于结束日期") } // 校验时间范围不能超过5年 maxDuration := 5 * 365 * 24 * time.Hour // 5年的近似时间(不考虑闰年) if endDate.Sub(startDate) > maxDuration { return errors.New("时间范围不能超过5年") } // 校验当前时间在范围内 now := time.Now() if now.Before(startDate) || now.After(endDate) { return errors.New("当前时间必须在指定的时间范围内") } return nil } // 获取验证器实例 func GetValidator() *validator.Validate { return validate } // 自定义的名称验证 func validName(fl validator.FieldLevel) bool { name := fl.Field().String() validNamePattern := `^[\p{Han}]+$` matched, _ := regexp.MatchString(validNamePattern, name) return matched } // 自定义的手机号验证 func validMobileNo(fl validator.FieldLevel) bool { phone := fl.Field().String() validMobileNoPattern := `^1[3-9]\d{9}$` matched, _ := regexp.MatchString(validMobileNoPattern, phone) return matched } // 自定义正则表达式校验 yyyyMMdd 格式 func validDate(fl validator.FieldLevel) bool { date := fl.Field().String() validDatePattern := `^\d{4}(0[1-9]|1[0-2])(0[1-9]|[12][0-9]|3[01])$` matched, _ := regexp.MatchString(validDatePattern, date) return matched } // 自定义身份证校验 func validIDCard(fl validator.FieldLevel) bool { id := fl.Field().String() validIDPattern := `^\d{17}(\d|X|x)$` // 匹配18位身份证号码 matched, _ := regexp.MatchString(validIDPattern, id) return matched } // 自定义 time_range 校验 (1-5年) func validTimeRange(fl validator.FieldLevel) bool { timeRange := fl.Field().String() if timeRange == "" { return true // 如果为空,认为是有效的,因为是非必填项 } value, err := strconv.Atoi(timeRange) if err != nil || value < 1 || value > 5 { return false } return true } func validBankCard(fl validator.FieldLevel) bool { bankCard := fl.Field().String() // 银行卡号一般是13到19位的数字 validBankCardPattern := `^\d{13,19}$` matched, _ := regexp.MatchString(validBankCardPattern, bankCard) return matched } func validUSCI(fl validator.FieldLevel) bool { usci := fl.Field().String() // 社会信用代码为18位数字和大写字母的组合,最后一位为校验码 validUSCIPattern := `^[1-9A-Z]{2}[0-9]{6}[0-9A-Z]{9}[0-9A-Z]$` matched, _ := regexp.MatchString(validUSCIPattern, usci) return matched } // 自定义的手机号类型验证(可以为空) func validMobileType(fl validator.FieldLevel) bool { mobileType := fl.Field().String() if mobileType == "" { return true // 如果为空,认为是有效的 } // 校验是否是 CTCC, CMCC, CUCC 之一 validTypes := map[string]bool{ "CTCC": true, // 中国电信 "CMCC": true, // 中国移动 "CUCC": true, // 中国联通 } return validTypes[mobileType] } // 自定义的日期范围验证器(用于结构体字段验证) func validAuthDate(fl validator.FieldLevel) bool { dateRange := fl.Field().String() // 如果是空字符串,认为是有效的(非必填项) if dateRange == "" { return true } err := ValidateAuthDate(dateRange) return err == nil }