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") }