first commit
This commit is contained in:
105
pkg/lzkit/crypto/crypto.go
Normal file
105
pkg/lzkit/crypto/crypto.go
Normal file
@@ -0,0 +1,105 @@
|
||||
package crypto
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/aes"
|
||||
"crypto/cipher"
|
||||
"crypto/md5"
|
||||
"crypto/rand"
|
||||
"encoding/base64"
|
||||
"encoding/hex"
|
||||
"errors"
|
||||
"io"
|
||||
)
|
||||
|
||||
// PKCS7填充
|
||||
func PKCS7Padding(ciphertext []byte, blockSize int) []byte {
|
||||
padding := blockSize - len(ciphertext)%blockSize
|
||||
padtext := bytes.Repeat([]byte{byte(padding)}, padding)
|
||||
return append(ciphertext, padtext...)
|
||||
}
|
||||
|
||||
// 去除PKCS7填充
|
||||
func PKCS7UnPadding(origData []byte) ([]byte, error) {
|
||||
length := len(origData)
|
||||
if length == 0 {
|
||||
return nil, errors.New("input data error")
|
||||
}
|
||||
unpadding := int(origData[length-1])
|
||||
if unpadding > length {
|
||||
return nil, errors.New("unpadding size is invalid")
|
||||
}
|
||||
|
||||
// 检查填充字节是否一致
|
||||
for i := 0; i < unpadding; i++ {
|
||||
if origData[length-1-i] != byte(unpadding) {
|
||||
return nil, errors.New("invalid padding")
|
||||
}
|
||||
}
|
||||
|
||||
return origData[:(length - unpadding)], nil
|
||||
}
|
||||
|
||||
// AES CBC模式加密,Base64传入传出
|
||||
func AesEncrypt(plainText, key []byte) (string, error) {
|
||||
block, err := aes.NewCipher(key)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
blockSize := block.BlockSize()
|
||||
plainText = PKCS7Padding(plainText, blockSize)
|
||||
|
||||
cipherText := make([]byte, blockSize+len(plainText))
|
||||
iv := cipherText[:blockSize] // 使用前blockSize字节作为IV
|
||||
_, err = io.ReadFull(rand.Reader, iv)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
mode := cipher.NewCBCEncrypter(block, iv)
|
||||
mode.CryptBlocks(cipherText[blockSize:], plainText)
|
||||
|
||||
return base64.StdEncoding.EncodeToString(cipherText), nil
|
||||
}
|
||||
|
||||
// AES CBC模式解密,Base64传入传出
|
||||
func AesDecrypt(cipherTextBase64 string, key []byte) ([]byte, error) {
|
||||
cipherText, err := base64.StdEncoding.DecodeString(cipherTextBase64)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
block, err := aes.NewCipher(key)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
blockSize := block.BlockSize()
|
||||
if len(cipherText) < blockSize {
|
||||
return nil, errors.New("ciphertext too short")
|
||||
}
|
||||
|
||||
iv := cipherText[:blockSize]
|
||||
cipherText = cipherText[blockSize:]
|
||||
|
||||
if len(cipherText)%blockSize != 0 {
|
||||
return nil, errors.New("ciphertext is not a multiple of the block size")
|
||||
}
|
||||
|
||||
mode := cipher.NewCBCDecrypter(block, iv)
|
||||
mode.CryptBlocks(cipherText, cipherText)
|
||||
|
||||
plainText, err := PKCS7UnPadding(cipherText)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return plainText, nil
|
||||
}
|
||||
|
||||
// Md5Encrypt 用于对传入的message进行MD5加密
|
||||
func Md5Encrypt(message string) string {
|
||||
hash := md5.New()
|
||||
hash.Write([]byte(message)) // 将字符串转换为字节切片并写入
|
||||
return hex.EncodeToString(hash.Sum(nil)) // 将哈希值转换为16进制字符串并返回
|
||||
}
|
||||
63
pkg/lzkit/crypto/generate.go
Normal file
63
pkg/lzkit/crypto/generate.go
Normal file
@@ -0,0 +1,63 @@
|
||||
package crypto
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"encoding/hex"
|
||||
"io"
|
||||
mathrand "math/rand"
|
||||
"strconv"
|
||||
"time"
|
||||
)
|
||||
|
||||
// 生成AES-128密钥的函数,符合市面规范
|
||||
func GenerateSecretKey() (string, error) {
|
||||
key := make([]byte, 16) // 16字节密钥
|
||||
_, err := io.ReadFull(rand.Reader, key)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return hex.EncodeToString(key), nil
|
||||
}
|
||||
|
||||
func GenerateSecretId() (string, error) {
|
||||
// 创建一个字节数组,用于存储随机数据
|
||||
bytes := make([]byte, 8) // 因为每个字节表示两个16进制字符
|
||||
|
||||
// 读取随机字节到数组中
|
||||
_, err := rand.Read(bytes)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
// 将字节数组转换为16进制字符串
|
||||
return hex.EncodeToString(bytes), nil
|
||||
}
|
||||
|
||||
// GenerateTransactionID 生成16位数的交易单号
|
||||
func GenerateTransactionID() string {
|
||||
length := 16
|
||||
// 获取当前时间戳
|
||||
timestamp := time.Now().UnixNano()
|
||||
|
||||
// 转换为字符串
|
||||
timeStr := strconv.FormatInt(timestamp, 10)
|
||||
|
||||
// 生成随机数
|
||||
mathrand.Seed(time.Now().UnixNano())
|
||||
randomPart := strconv.Itoa(mathrand.Intn(1000000))
|
||||
|
||||
// 组合时间戳和随机数
|
||||
combined := timeStr + randomPart
|
||||
|
||||
// 如果长度超出指定值,则截断;如果不够,则填充随机字符
|
||||
if len(combined) >= length {
|
||||
return combined[:length]
|
||||
}
|
||||
|
||||
// 如果长度不够,填充0
|
||||
for len(combined) < length {
|
||||
combined += strconv.Itoa(mathrand.Intn(10)) // 填充随机数
|
||||
}
|
||||
|
||||
return combined
|
||||
}
|
||||
150
pkg/lzkit/crypto/west_crypto.go
Normal file
150
pkg/lzkit/crypto/west_crypto.go
Normal file
@@ -0,0 +1,150 @@
|
||||
package crypto
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/aes"
|
||||
"crypto/cipher"
|
||||
"crypto/sha1"
|
||||
"encoding/base64"
|
||||
)
|
||||
|
||||
const (
|
||||
KEY_SIZE = 16 // AES-128, 16 bytes
|
||||
)
|
||||
|
||||
// Encrypt encrypts the given data using AES encryption in ECB mode with PKCS5 padding
|
||||
func WestDexEncrypt(data, secretKey string) (string, error) {
|
||||
key := generateAESKey(KEY_SIZE*8, []byte(secretKey))
|
||||
ciphertext, err := aesEncrypt([]byte(data), key)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return base64.StdEncoding.EncodeToString(ciphertext), nil
|
||||
}
|
||||
|
||||
// Decrypt decrypts the given base64-encoded string using AES encryption in ECB mode with PKCS5 padding
|
||||
func WestDexDecrypt(encodedData, secretKey string) ([]byte, error) {
|
||||
ciphertext, err := base64.StdEncoding.DecodeString(encodedData)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
key := generateAESKey(KEY_SIZE*8, []byte(secretKey))
|
||||
plaintext, err := aesDecrypt(ciphertext, key)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return plaintext, nil
|
||||
}
|
||||
|
||||
// generateAESKey generates a key for AES encryption using a SHA-1 based PRNG
|
||||
func generateAESKey(length int, password []byte) []byte {
|
||||
h := sha1.New()
|
||||
h.Write(password)
|
||||
state := h.Sum(nil)
|
||||
|
||||
keyBytes := make([]byte, 0, length/8)
|
||||
for len(keyBytes) < length/8 {
|
||||
h := sha1.New()
|
||||
h.Write(state)
|
||||
state = h.Sum(nil)
|
||||
keyBytes = append(keyBytes, state...)
|
||||
}
|
||||
|
||||
return keyBytes[:length/8]
|
||||
}
|
||||
|
||||
// aesEncrypt encrypts plaintext using AES in ECB mode with PKCS5 padding
|
||||
func aesEncrypt(plaintext, key []byte) ([]byte, error) {
|
||||
block, err := aes.NewCipher(key)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
paddedPlaintext := pkcs5Padding(plaintext, block.BlockSize())
|
||||
ciphertext := make([]byte, len(paddedPlaintext))
|
||||
mode := newECBEncrypter(block)
|
||||
mode.CryptBlocks(ciphertext, paddedPlaintext)
|
||||
return ciphertext, nil
|
||||
}
|
||||
|
||||
// aesDecrypt decrypts ciphertext using AES in ECB mode with PKCS5 padding
|
||||
func aesDecrypt(ciphertext, key []byte) ([]byte, error) {
|
||||
block, err := aes.NewCipher(key)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
plaintext := make([]byte, len(ciphertext))
|
||||
mode := newECBDecrypter(block)
|
||||
mode.CryptBlocks(plaintext, ciphertext)
|
||||
return pkcs5Unpadding(plaintext), nil
|
||||
}
|
||||
|
||||
// pkcs5Padding pads the input to a multiple of the block size using PKCS5 padding
|
||||
func pkcs5Padding(src []byte, blockSize int) []byte {
|
||||
padding := blockSize - len(src)%blockSize
|
||||
padtext := bytes.Repeat([]byte{byte(padding)}, padding)
|
||||
return append(src, padtext...)
|
||||
}
|
||||
|
||||
// pkcs5Unpadding removes PKCS5 padding from the input
|
||||
func pkcs5Unpadding(src []byte) []byte {
|
||||
length := len(src)
|
||||
unpadding := int(src[length-1])
|
||||
return src[:(length - unpadding)]
|
||||
}
|
||||
|
||||
// ECB mode encryption/decryption
|
||||
type ecb struct {
|
||||
b cipher.Block
|
||||
blockSize int
|
||||
}
|
||||
|
||||
func newECB(b cipher.Block) *ecb {
|
||||
return &ecb{
|
||||
b: b,
|
||||
blockSize: b.BlockSize(),
|
||||
}
|
||||
}
|
||||
|
||||
type ecbEncrypter ecb
|
||||
|
||||
func newECBEncrypter(b cipher.Block) cipher.BlockMode {
|
||||
return (*ecbEncrypter)(newECB(b))
|
||||
}
|
||||
|
||||
func (x *ecbEncrypter) BlockSize() int { return x.blockSize }
|
||||
|
||||
func (x *ecbEncrypter) CryptBlocks(dst, src []byte) {
|
||||
if len(src)%x.blockSize != 0 {
|
||||
panic("crypto/cipher: input not full blocks")
|
||||
}
|
||||
if len(dst) < len(src) {
|
||||
panic("crypto/cipher: output smaller than input")
|
||||
}
|
||||
for len(src) > 0 {
|
||||
x.b.Encrypt(dst, src[:x.blockSize])
|
||||
src = src[x.blockSize:]
|
||||
dst = dst[x.blockSize:]
|
||||
}
|
||||
}
|
||||
|
||||
type ecbDecrypter ecb
|
||||
|
||||
func newECBDecrypter(b cipher.Block) cipher.BlockMode {
|
||||
return (*ecbDecrypter)(newECB(b))
|
||||
}
|
||||
|
||||
func (x *ecbDecrypter) BlockSize() int { return x.blockSize }
|
||||
|
||||
func (x *ecbDecrypter) CryptBlocks(dst, src []byte) {
|
||||
if len(src)%x.blockSize != 0 {
|
||||
panic("crypto/cipher: input not full blocks")
|
||||
}
|
||||
if len(dst) < len(src) {
|
||||
panic("crypto/cipher: output smaller than input")
|
||||
}
|
||||
for len(src) > 0 {
|
||||
x.b.Decrypt(dst, src[:x.blockSize])
|
||||
src = src[x.blockSize:]
|
||||
dst = dst[x.blockSize:]
|
||||
}
|
||||
}
|
||||
65
pkg/lzkit/delay/ProgressiveDelay.go
Normal file
65
pkg/lzkit/delay/ProgressiveDelay.go
Normal file
@@ -0,0 +1,65 @@
|
||||
package delay
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"time"
|
||||
)
|
||||
|
||||
// ProgressiveDelay 用于管理渐进式延迟策略
|
||||
type ProgressiveDelay struct {
|
||||
initialDelay time.Duration // 初始延迟时间
|
||||
growthFactor float64 // 延迟增长因子 (例如 1.5)
|
||||
maxDelay time.Duration // 最大延迟时间
|
||||
maxRetryDuration time.Duration // 最大重试时间
|
||||
currentDelay time.Duration // 当前延迟时间
|
||||
startTime time.Time // 重试开始时间
|
||||
}
|
||||
|
||||
// New 创建一个新的渐进式延迟对象
|
||||
func New(initialDelay, maxDelay, maxRetryDuration time.Duration, growthFactor float64) (*ProgressiveDelay, error) {
|
||||
// 参数校验
|
||||
if initialDelay <= 0 {
|
||||
return nil, errors.New("initialDelay must be greater than zero")
|
||||
}
|
||||
if maxDelay <= 0 {
|
||||
return nil, errors.New("maxDelay must be greater than zero")
|
||||
}
|
||||
if maxRetryDuration <= 0 {
|
||||
return nil, errors.New("maxRetryDuration must be greater than zero")
|
||||
}
|
||||
if growthFactor <= 1.0 {
|
||||
return nil, errors.New("growthFactor must be greater than 1")
|
||||
}
|
||||
|
||||
// 初始化并返回
|
||||
return &ProgressiveDelay{
|
||||
initialDelay: initialDelay,
|
||||
maxDelay: maxDelay,
|
||||
maxRetryDuration: maxRetryDuration,
|
||||
growthFactor: growthFactor,
|
||||
currentDelay: initialDelay,
|
||||
startTime: time.Now(),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// NextDelay 计算并返回下次的延迟时间
|
||||
func (pd *ProgressiveDelay) NextDelay() (time.Duration, error) {
|
||||
// 检查最大重试时间是否已过
|
||||
if time.Since(pd.startTime) > pd.maxRetryDuration {
|
||||
return 0, fmt.Errorf("最大重试时间超过限制: %v", pd.maxRetryDuration)
|
||||
}
|
||||
|
||||
// 返回当前延迟时间
|
||||
delay := pd.currentDelay
|
||||
|
||||
// 计算下一个延迟时间并更新 currentDelay
|
||||
pd.currentDelay = time.Duration(float64(pd.currentDelay) * pd.growthFactor)
|
||||
|
||||
// 如果下次延迟超过最大延迟时间,限制在最大值
|
||||
if pd.currentDelay > pd.maxDelay {
|
||||
pd.currentDelay = pd.maxDelay
|
||||
}
|
||||
|
||||
return delay, nil
|
||||
}
|
||||
38
pkg/lzkit/lzUtils/sqlutls.go
Normal file
38
pkg/lzkit/lzUtils/sqlutls.go
Normal file
@@ -0,0 +1,38 @@
|
||||
package lzUtils
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"time"
|
||||
)
|
||||
|
||||
// StringToNullString 将 string 转换为 sql.NullString
|
||||
func StringToNullString(s string) sql.NullString {
|
||||
return sql.NullString{
|
||||
String: s,
|
||||
Valid: s != "",
|
||||
}
|
||||
}
|
||||
|
||||
// NullStringToString 将 sql.NullString 转换为 string
|
||||
func NullStringToString(ns sql.NullString) string {
|
||||
if ns.Valid {
|
||||
return ns.String
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// TimeToNullTime 将 time.Time 转换为 sql.NullTime
|
||||
func TimeToNullTime(t time.Time) sql.NullTime {
|
||||
return sql.NullTime{
|
||||
Time: t,
|
||||
Valid: !t.IsZero(), // 仅当 t 不是零值时才设置为有效
|
||||
}
|
||||
}
|
||||
|
||||
// NullTimeToTime 将 sql.NullTime 转换为 time.Time
|
||||
func NullTimeToTime(nt sql.NullTime) time.Time {
|
||||
if nt.Valid {
|
||||
return nt.Time
|
||||
}
|
||||
return time.Time{} // 返回零值时间
|
||||
}
|
||||
15
pkg/lzkit/lzUtils/utils.go
Normal file
15
pkg/lzkit/lzUtils/utils.go
Normal file
@@ -0,0 +1,15 @@
|
||||
package lzUtils
|
||||
|
||||
import "fmt"
|
||||
|
||||
// ToWechatAmount 将金额从元转换为微信支付 SDK 需要的分(int64 类型)
|
||||
func ToWechatAmount(amount float64) int64 {
|
||||
// 将金额从元转换为分,并四舍五入
|
||||
return int64(amount*100 + 0.5)
|
||||
}
|
||||
|
||||
// ToAlipayAmount 将金额从元转换为支付宝支付 SDK 需要的字符串格式,保留两位小数
|
||||
func ToAlipayAmount(amount float64) string {
|
||||
// 格式化为字符串,保留两位小数
|
||||
return fmt.Sprintf("%.2f", amount)
|
||||
}
|
||||
38
pkg/lzkit/validator/error_messages.go
Normal file
38
pkg/lzkit/validator/error_messages.go
Normal file
@@ -0,0 +1,38 @@
|
||||
package validator
|
||||
|
||||
// 定义自定义错误消息
|
||||
var customMessages = map[string]string{
|
||||
"Name.min": "姓名不能少于1个字",
|
||||
"Name.required": "姓名是必填项",
|
||||
"Name.name": "姓名只能包含中文",
|
||||
"NameMan.min": "男方姓名不能少于1个字",
|
||||
"NameMan.required": "男方姓名是必填项",
|
||||
"NameMan.name": "男方姓名只能包含中文",
|
||||
"NameWoman.min": "女方姓名不能少于1个字",
|
||||
"NameWoman.required": "女方姓名是必填项",
|
||||
"NameWoman.name": "女方姓名只能包含中文",
|
||||
"Mobile.required": "手机号是必填项",
|
||||
"Mobile.min": "电话号码必须为有效的中国电话号码",
|
||||
"Mobile.max": "电话号码必须为有效的中国电话号码",
|
||||
"Mobile.mobile": "电话号码必须为有效的中国电话号码",
|
||||
"IDCard.required": "身份证号是必填项",
|
||||
"IDCard.idCard": "无效的身份证号码",
|
||||
"IDCardMan.required": "男方身份证号是必填项",
|
||||
"IDCardMan.idCard": "无效的男方身份证号码",
|
||||
"IDCardWoman.required": "女方身份证号是必填项",
|
||||
"IDCardWoman.idCard": "无效的女方身份证号码",
|
||||
"Password.min": "密码不能少于8位数",
|
||||
"Password.max": "密码不能超过32位数",
|
||||
"Password.password": "密码强度太弱",
|
||||
//"EntCode.required":"请输入统一社会信用代码",
|
||||
//"EntCode.USCI": "请输入正确的统一社会信用代码",
|
||||
}
|
||||
|
||||
// 获取自定义错误消息
|
||||
func GetErrorMessage(field, tag string) string {
|
||||
key := field + "." + tag
|
||||
if msg, exists := customMessages[key]; exists {
|
||||
return msg
|
||||
}
|
||||
return "请输入正确格式的参数"
|
||||
}
|
||||
174
pkg/lzkit/validator/validator.go
Normal file
174
pkg/lzkit/validator/validator.go
Normal file
@@ -0,0 +1,174 @@
|
||||
package validator
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/go-playground/validator/v10"
|
||||
"regexp"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var validate *validator.Validate
|
||||
|
||||
// 初始化自定义校验器
|
||||
func init() {
|
||||
validate = validator.New()
|
||||
|
||||
if err := validate.RegisterValidation("name", validName); err != nil {
|
||||
panic(fmt.Sprintf("注册 name 验证器时发生错误: %v", err))
|
||||
}
|
||||
|
||||
// 注册自定义验证器 validmobile
|
||||
if err := validate.RegisterValidation("mobile", validmobile); err != nil {
|
||||
panic(fmt.Sprintf("注册 mobile 验证器时发生错误: %v", err))
|
||||
}
|
||||
|
||||
// 注册自定义验证器 validDate
|
||||
if err := validate.RegisterValidation("date", validDate); err != nil {
|
||||
panic(fmt.Sprintf("注册 date 验证器时发生错误: %v", err))
|
||||
}
|
||||
|
||||
// 注册自定义验证器 validIDCard
|
||||
if err := validate.RegisterValidation("idCard", validIDCard); err != nil {
|
||||
panic(fmt.Sprintf("注册 idCard 验证器时发生错误: %v", err))
|
||||
}
|
||||
|
||||
if err := validate.RegisterValidation("bankCard", validBankCard); err != nil {
|
||||
panic(fmt.Sprintf("注册 bankCard 验证器时发生错误: %v", err))
|
||||
}
|
||||
|
||||
if err := validate.RegisterValidation("USCI", validUSCI); err != nil {
|
||||
panic(fmt.Sprintf("注册 USCI 社会统一信用代码 验证器时发生错误: %v", err))
|
||||
}
|
||||
|
||||
if err := validate.RegisterValidation("mobileType", validMobileType); err != nil {
|
||||
panic(fmt.Sprintf("注册 mobileType 验证器时发生错误: %v", err))
|
||||
}
|
||||
if err := validate.RegisterValidation("password", validatePassword); err != nil {
|
||||
panic(fmt.Sprintf("注册 password 验证器时发生错误: %v", err))
|
||||
}
|
||||
if err := validate.RegisterValidation("payMethod", validatePayMethod); err != nil {
|
||||
panic(fmt.Sprintf("注册 payMethod 验证器时发生错误: %v", err))
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// 弱口令列表
|
||||
var weakPasswords = []string{
|
||||
"12345678", "password", "123456789", "qwerty", "123456", "letmein",
|
||||
"1234567", "welcome", "abc123", "password1", "1234", "111111", "admin",
|
||||
}
|
||||
|
||||
// Validate 校验参数逻辑
|
||||
func Validate(req interface{}) error {
|
||||
if err := validate.Struct(req); err != nil {
|
||||
// 检查 err 是否是 ValidationErrors 类型
|
||||
if validationErrors, ok := err.(validator.ValidationErrors); ok {
|
||||
for _, validationErr := range validationErrors {
|
||||
field := validationErr.StructField()
|
||||
tag := validationErr.Tag()
|
||||
return errors.New(GetErrorMessage(field, tag))
|
||||
}
|
||||
} else {
|
||||
// 其他错误处理
|
||||
return fmt.Errorf("验证时出现未知错误: %v", err)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// 自定义的名称验证
|
||||
func validName(fl validator.FieldLevel) bool {
|
||||
name := fl.Field().String()
|
||||
validNamePattern := `^[\p{Han}]+$`
|
||||
matched, _ := regexp.MatchString(validNamePattern, name)
|
||||
return matched
|
||||
}
|
||||
|
||||
// 自定义的手机号验证
|
||||
func validmobile(fl validator.FieldLevel) bool {
|
||||
phone := fl.Field().String()
|
||||
validmobilePattern := `^1[3-9]\d{9}$`
|
||||
matched, _ := regexp.MatchString(validmobilePattern, 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
|
||||
}
|
||||
|
||||
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 validatePassword(fl validator.FieldLevel) bool {
|
||||
password := fl.Field().String()
|
||||
|
||||
// 检查密码是否在弱口令列表中
|
||||
for _, weakPwd := range weakPasswords {
|
||||
if strings.ToLower(password) == weakPwd {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
// 支付方式
|
||||
func validatePayMethod(fl validator.FieldLevel) bool {
|
||||
payMethod := fl.Field().String()
|
||||
|
||||
if payMethod == "" {
|
||||
return true // 如果为空,认为是有效的
|
||||
}
|
||||
|
||||
validTypes := map[string]bool{
|
||||
"alipay": true, // 中国电信
|
||||
"wechatpay": true, // 中国移动
|
||||
}
|
||||
|
||||
return validTypes[payMethod]
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user