package service import ( "errors" "licserver/internal/model" "licserver/internal/utils" "strings" "time" "github.com/mojocn/base64Captcha" "gorm.io/gorm" ) type CaptchaService struct { db *gorm.DB emailConfig *utils.EmailConfig store base64Captcha.Store } func NewCaptchaService(db *gorm.DB, emailConfig *utils.EmailConfig) *CaptchaService { return &CaptchaService{ db: db, emailConfig: emailConfig, store: base64Captcha.DefaultMemStore, } } func (s *CaptchaService) SendEmailCaptcha(email, captchaType string) error { // 检查是否存在未过期的验证码 var count int64 s.db.Model(&model.Captcha{}). Where("target = ? AND type = ? AND expires_at > ? AND used = ?", email, captchaType, time.Now(), false). Count(&count) if count > 0 { return errors.New("请勿频繁发送验证码") } // 生成验证码 code, err := utils.GenerateCaptcha() if err != nil { return err } // 保存验证码 captcha := model.Captcha{ Code: code, Type: captchaType, Target: email, ExpiresAt: time.Now().Add(5 * time.Minute), Used: false, } if err := s.db.Create(&captcha).Error; err != nil { return err } // 发送验证码邮件 emailService := utils.NewEmailService(s.emailConfig) content := utils.GenerateEmailCaptchaContent(code, email, captchaType) return emailService.SendEmail(email, "验证码", content) } func (s *CaptchaService) VerifyCaptcha(target, captchaType, code string) error { var captcha model.Captcha err := s.db.Where("target = ? AND type = ? AND code = ? AND used = ? AND expires_at > ?", target, captchaType, code, false, time.Now()). First(&captcha).Error if err != nil { if errors.Is(err, gorm.ErrRecordNotFound) { return errors.New("验证码无效或已过期") } return err } // 标记验证码为已使用 return s.db.Model(&captcha).Update("used", true).Error } // 生成图片验证码 func (s *CaptchaService) GenerateImageCaptcha() (string, string, error) { driver := base64Captcha.NewDriverDigit(80, 240, 6, 0.7, 80) c := base64Captcha.NewCaptcha(driver, s.store) id, b64s, err := c.Generate() if err != nil { return "", "", err } // 确保返回的base64字符串不包含前缀 b64s = strings.TrimPrefix(b64s, "data:image/png;base64,") return id, b64s, nil } // 验证图片验证码 func (s *CaptchaService) VerifyImageCaptcha(id, code string) bool { return s.store.Verify(id, code, true) }