2024-10-02 00:57:17 +08:00
|
|
|
|
package validator
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"encoding/json"
|
|
|
|
|
"errors"
|
|
|
|
|
"fmt"
|
|
|
|
|
"regexp"
|
|
|
|
|
"strconv"
|
2025-03-18 22:07:42 +08:00
|
|
|
|
"strings"
|
|
|
|
|
"time"
|
|
|
|
|
|
|
|
|
|
"github.com/go-playground/validator/v10"
|
2024-10-02 00:57:17 +08:00
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
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))
|
|
|
|
|
}
|
2024-10-13 20:52:47 +08:00
|
|
|
|
|
|
|
|
|
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))
|
|
|
|
|
}
|
2025-03-18 22:07:42 +08:00
|
|
|
|
|
|
|
|
|
// 注册自定义验证器 validAuthDate
|
|
|
|
|
if err := validate.RegisterValidation("validAuthDate", validAuthDate); err != nil {
|
|
|
|
|
panic(fmt.Sprintf("注册 validAuthDate 验证器时发生错误: %v", err))
|
|
|
|
|
}
|
2024-10-02 00:57:17 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 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
|
|
|
|
|
}
|
|
|
|
|
|
2025-03-18 22:07:42 +08:00
|
|
|
|
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
|
|
|
|
|
}
|
|
|
|
|
|
2024-10-02 00:57:17 +08:00
|
|
|
|
// 获取验证器实例
|
|
|
|
|
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()
|
2024-10-15 17:19:23 +08:00
|
|
|
|
validIDPattern := `^\d{17}(\d|X|x)$` // 匹配18位身份证号码
|
2024-10-02 00:57:17 +08:00
|
|
|
|
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
|
|
|
|
|
}
|
2024-10-13 20:52:47 +08:00
|
|
|
|
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]
|
|
|
|
|
}
|
2025-03-18 22:07:42 +08:00
|
|
|
|
|
|
|
|
|
// 自定义的日期范围验证器(用于结构体字段验证)
|
|
|
|
|
func validAuthDate(fl validator.FieldLevel) bool {
|
|
|
|
|
dateRange := fl.Field().String()
|
|
|
|
|
// 如果是空字符串,认为是有效的(非必填项)
|
|
|
|
|
if dateRange == "" {
|
|
|
|
|
return true
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
err := ValidateAuthDate(dateRange)
|
|
|
|
|
return err == nil
|
|
|
|
|
}
|