93 lines
3.1 KiB
Go
93 lines
3.1 KiB
Go
package handlers
|
||
|
||
import (
|
||
"github.com/gin-gonic/gin"
|
||
"go.uber.org/zap"
|
||
|
||
"tyapi-server/internal/config"
|
||
"tyapi-server/internal/infrastructure/external/captcha"
|
||
"tyapi-server/internal/shared/interfaces"
|
||
)
|
||
|
||
// CaptchaHandler 验证码(滑块)HTTP 处理器
|
||
type CaptchaHandler struct {
|
||
captchaService *captcha.CaptchaService
|
||
response interfaces.ResponseBuilder
|
||
config *config.Config
|
||
logger *zap.Logger
|
||
}
|
||
|
||
// NewCaptchaHandler 创建验证码处理器
|
||
func NewCaptchaHandler(
|
||
captchaService *captcha.CaptchaService,
|
||
response interfaces.ResponseBuilder,
|
||
cfg *config.Config,
|
||
logger *zap.Logger,
|
||
) *CaptchaHandler {
|
||
return &CaptchaHandler{
|
||
captchaService: captchaService,
|
||
response: response,
|
||
config: cfg,
|
||
logger: logger,
|
||
}
|
||
}
|
||
|
||
// EncryptedSceneIdReq 获取加密场景 ID 的请求(可选参数)
|
||
type EncryptedSceneIdReq struct {
|
||
ExpireSeconds *int `form:"expire_seconds" json:"expire_seconds"` // 有效期秒数,1~86400,默认 3600
|
||
}
|
||
|
||
// GetEncryptedSceneId 获取加密场景 ID,供前端加密模式初始化阿里云验证码
|
||
// @Summary 获取验证码加密场景ID
|
||
// @Description 用于加密模式下发 EncryptedSceneId,前端用此初始化滑块验证码
|
||
// @Tags 验证码
|
||
// @Accept json
|
||
// @Produce json
|
||
// @Param body body EncryptedSceneIdReq false "可选:expire_seconds 有效期(1-86400),默认3600"
|
||
// @Success 200 {object} map[string]interface{} "encryptedSceneId"
|
||
// @Failure 400 {object} map[string]interface{} "配置未启用或参数错误"
|
||
// @Failure 500 {object} map[string]interface{} "服务器内部错误"
|
||
// @Router /api/v1/captcha/encryptedSceneId [post]
|
||
func (h *CaptchaHandler) GetEncryptedSceneId(c *gin.Context) {
|
||
expireSec := 3600
|
||
if c.Request.ContentLength > 0 {
|
||
var req EncryptedSceneIdReq
|
||
if err := c.ShouldBindJSON(&req); err == nil && req.ExpireSeconds != nil {
|
||
expireSec = *req.ExpireSeconds
|
||
}
|
||
}
|
||
if expireSec <= 0 || expireSec > 86400 {
|
||
h.response.BadRequest(c, "expire_seconds 必须在 1~86400 之间")
|
||
return
|
||
}
|
||
|
||
encrypted, err := h.captchaService.GetEncryptedSceneId(expireSec)
|
||
if err != nil {
|
||
if err == captcha.ErrCaptchaEncryptMissing || err == captcha.ErrCaptchaConfig {
|
||
h.logger.Warn("验证码加密场景ID生成失败", zap.Error(err))
|
||
h.response.BadRequest(c, "验证码加密模式未配置或配置错误")
|
||
return
|
||
}
|
||
h.logger.Error("验证码加密场景ID生成失败", zap.Error(err))
|
||
h.response.InternalError(c, "生成失败,请稍后重试")
|
||
return
|
||
}
|
||
|
||
h.response.Success(c, map[string]string{"encryptedSceneId": encrypted}, "ok")
|
||
}
|
||
|
||
// GetConfig 获取验证码前端配置(是否启用、场景ID等),便于前端决定是否展示滑块
|
||
// @Summary 获取验证码配置
|
||
// @Description 返回是否启用滑块、场景ID(非加密模式用)
|
||
// @Tags 验证码
|
||
// @Produce json
|
||
// @Success 200 {object} map[string]interface{} "captchaEnabled, sceneId"
|
||
// @Router /api/v1/captcha/config [get]
|
||
func (h *CaptchaHandler) GetConfig(c *gin.Context) {
|
||
data := map[string]interface{}{
|
||
"captchaEnabled": h.config.SMS.CaptchaEnabled,
|
||
"sceneId": h.config.SMS.SceneID,
|
||
}
|
||
h.response.Success(c, data, "ok")
|
||
}
|