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  }