101 lines
2.4 KiB
Go
101 lines
2.4 KiB
Go
|
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)
|
||
|
}
|