github.com/infraboard/keyauth@v0.8.1/apps/verifycode/verifycode_ext.go (about) 1 package verifycode 2 3 import ( 4 "fmt" 5 "hash/fnv" 6 "math/rand" 7 "strconv" 8 "strings" 9 "time" 10 11 "github.com/go-playground/validator/v10" 12 "github.com/infraboard/mcube/exception" 13 "github.com/infraboard/mcube/types/ftime" 14 ) 15 16 // use a single instance of Validate, it caches struct info 17 var ( 18 validate = validator.New() 19 ) 20 21 // NewCode todo 22 func NewCode(req *IssueCodeRequest) (*Code, error) { 23 if err := req.Validate(); err != nil { 24 return nil, exception.NewBadRequest("validate issue code request error, %s", err) 25 } 26 27 c := &Code{ 28 Number: GenRandomCode(6), 29 Username: req.Account(), 30 IssueAt: ftime.Now().Timestamp(), 31 ExpiredMinite: 10, 32 } 33 34 c.Id = HashID(c.Username, c.Number) 35 return c, nil 36 } 37 38 // NewDefaultCode todo 39 func NewDefaultCode() *Code { 40 return &Code{} 41 } 42 43 // IsExpired todo 44 func (c *Code) IsExpired() bool { 45 return time.Now().Sub(time.Unix(c.IssueAt/1000, 0)).Minutes() > float64(c.ExpiredMinite) 46 } 47 48 // ExpiredMiniteString todo 49 func (c *Code) ExpiredMiniteString() string { 50 return fmt.Sprintf("%d", c.ExpiredMinite) 51 } 52 53 // HashID todo 54 func HashID(username, number string) string { 55 hash := fnv.New32a() 56 hash.Write([]byte(username)) 57 hash.Write([]byte(number)) 58 return fmt.Sprintf("%x", hash.Sum32()) 59 } 60 61 // NewDefaultConfig todo 62 func NewDefaultConfig() *Config { 63 return &Config{ 64 NotifyType: NotifyType_MAIL, 65 ExpireMinutes: 10, 66 MailTemplate: "您的动态验证码为:{1},{2}分钟内有效!,如非本人操作,请忽略本邮件!", 67 } 68 } 69 70 // Config todo 71 type Config struct { 72 NotifyType NotifyType `bson:"notify_type" json:"notify_type"` 73 ExpireMinutes uint `bson:"expire_minutes" json:"expire_minutes" validate:"required,gte=10,lte=600"` // 验证码默认过期时间 74 MailTemplate string `bson:"mail_template" json:"mail_template"` // 邮件通知时的模板 75 SmsTemplateID string `bson:"sms_template_id" json:"sms_template_id"` // 短信通知时的云商模板ID 76 } 77 78 // RenderMailTemplate todo 79 func (conf *Config) RenderMailTemplate(number, expiiredMinite string) string { 80 t1 := strings.ReplaceAll(conf.MailTemplate, "{1}", number) 81 return strings.ReplaceAll(t1, "{2}", expiiredMinite) 82 } 83 84 // Validate todo 85 func (conf *Config) Validate() error { 86 return validate.Struct(conf) 87 } 88 89 // GenRandomCode todo 90 func GenRandomCode(length uint) string { 91 numbers := []string{} 92 rand.Seed(time.Now().Unix()) 93 for i := 0; i < int(length); i++ { 94 c := rand.Intn(9) 95 // 第一位不能为0 96 if c == 0 { 97 c = 1 98 } 99 100 numbers = append(numbers, strconv.Itoa(c)) 101 } 102 103 return strings.Join(numbers, "") 104 }