package auth import ( "errors" "net/http" "strings" "hfb_sys/backend/pkg/response" "github.com/gin-gonic/gin" ) type Handler struct { service *Service } type SendSMSRequest struct { Phone string `json:"phone" binding:"required"` } type LoginRequest struct { Phone string `json:"phone" binding:"required"` Code string `json:"code" binding:"required,len=6"` } type RefreshRequest struct { RefreshToken string `json:"refresh_token" binding:"required"` } func NewHandler(service *Service) *Handler { return &Handler{service: service} } func (h *Handler) SendSMS(c *gin.Context) { var req SendSMSRequest if err := c.ShouldBindJSON(&req); err != nil { response.BadRequest(c, "手机号不能为空") return } if err := h.service.SendSMSCode(c.Request.Context(), strings.TrimSpace(req.Phone)); err != nil { writeAuthError(c, err) return } response.OK(c, gin.H{"phone": PublicPhone(req.Phone), "expires_in": 300}) } func (h *Handler) Login(c *gin.Context) { var req LoginRequest if err := c.ShouldBindJSON(&req); err != nil { response.BadRequest(c, "手机号和验证码不能为空") return } result, err := h.service.LoginWithSMS(c.Request.Context(), strings.TrimSpace(req.Phone), strings.TrimSpace(req.Code)) if err != nil { writeAuthError(c, err) return } response.OK(c, result) } func (h *Handler) Refresh(c *gin.Context) { var req RefreshRequest if err := c.ShouldBindJSON(&req); err != nil { response.BadRequest(c, "refresh_token 不能为空") return } tokens, err := h.service.RefreshToken(req.RefreshToken) if err != nil { response.Unauthorized(c, "刷新令牌无效或已过期") return } response.OK(c, tokens) } func (h *Handler) Logout(c *gin.Context) { response.OK(c, gin.H{"logged_out": true}) } func writeAuthError(c *gin.Context, err error) { switch { case errors.Is(err, ErrDependencyUnavailable): response.ServiceUnavailable(c, "数据库或 Redis 未连接") case errors.Is(err, ErrInvalidPhone): response.BadRequest(c, "手机号格式不正确") case errors.Is(err, ErrCodeRateLimited): response.Error(c, http.StatusTooManyRequests, "rate_limited", "验证码发送过于频繁") case errors.Is(err, ErrSMSSendFailed): response.Error(c, http.StatusBadGateway, "sms_send_failed", "验证码发送失败,请稍后重试") case errors.Is(err, ErrCodeInvalid): response.BadRequest(c, "验证码错误或已过期") case errors.Is(err, ErrUserDisabled): response.Error(c, http.StatusForbidden, "user_disabled", "用户已被冻结") default: response.Error(c, http.StatusInternalServerError, "internal_error", "服务暂时不可用") } }