package handlers import ( "awesomeProject/internal/common" "awesomeProject/internal/models" "awesomeProject/internal/services" jwtutil "awesomeProject/pkg/utils" "crypto/md5" "fmt" "github.com/google/uuid" "net/http" "strings" "github.com/gin-gonic/gin" "gorm.io/gorm" ) // AuthHandler 认证处理器 type AuthHandler struct{} // LoginRequest 登录请求结构 type LoginRequest struct { Phone string `json:"phone" binding:"required"` Password string `json:"password" binding:"required"` } // LoginResponse 登录响应结构 type LoginResponse struct { Token string `json:"token"` User models.User `json:"user"` } type TokenGen struct { UserID uint `json:"user_id"` Phone string `json:"phone"` SystemRole int8 `json:"system_role"` } // Login 用户登录 func (h *AuthHandler) Login(c *gin.Context) { var req LoginRequest if err := c.ShouldBindJSON(&req); err != nil { c.JSON(http.StatusOK, common.Error(400, "参数错误: "+err.Error())) return } // 查询用户 var user models.User err := common.GetDB().Where("phone = ?", req.Phone).First(&user).Error if err != nil { if err == gorm.ErrRecordNotFound { c.JSON(http.StatusOK, common.Error(401, "手机号或密码错误")) } else { c.JSON(http.StatusOK, common.Error(500, "登录失败")) } return } // 验证密码(这里简单使用MD5,实际应该使用bcrypt) hashedPassword := fmt.Sprintf("%x", md5.Sum([]byte(req.Password))) fmt.Println(hashedPassword) if user.Password != hashedPassword { c.JSON(http.StatusOK, common.Error(404, "手机号或密码错误")) return } // 检查用户状态 if user.Status != 1 { c.JSON(http.StatusOK, common.Error(404, "用户已被禁用,请联系管理员")) return } // 生成JWT token claims := TokenGen{ UserID: user.ID, Phone: user.Phone, SystemRole: int8(user.SystemRole), } token, err := jwtutil.GenerateToken(claims) if err != nil { c.JSON(http.StatusOK, common.Error(500, "生成token失败")) return } // 返回登录结果 response := LoginResponse{ Token: token, User: user, } c.JSON(http.StatusOK, common.Success(response)) } // RegisterRequest 注册请求结构体 type RegisterRequest struct { models.User SMSCode string `json:"sms_code"` // 短信验证码 } // Register 用户注册 func (h *AuthHandler) Register(c *gin.Context) { var req RegisterRequest if err := c.ShouldBindJSON(&req); err != nil { c.JSON(http.StatusOK, common.Error(400, "参数错误: "+err.Error())) return } // 验证短信验证码(必填) if req.SMSCode == "" { c.JSON(http.StatusOK, common.Error(400, "请输入短信验证码")) return } // 验证短信验证码 smsService := services.GetSMSService() if !smsService.VerifyCode(req.Phone, req.SMSCode) { c.JSON(http.StatusOK, common.Error(400, "短信验证码错误或已过期")) return } // 检查手机号是否已存在 var existUser models.User if err := common.GetDB().Where("phone = ?", req.Phone).First(&existUser).Error; err == nil { c.JSON(http.StatusOK, common.Error(400, "手机号已被注册")) return } user := req.User // 生成身份码(简单实现,实际应该使用更复杂的算法) user.IdentityCode = fmt.Sprintf("U%v", uuid.New().String()[:8]) // 密码加密(这里简单使用MD5,实际应该使用bcrypt) hashedPassword := fmt.Sprintf("%x", md5.Sum([]byte(user.Password))) user.Password = hashedPassword // 默认为普通用户 if user.SystemRole == 0 { user.SystemRole = 2 } user.Status = 0 // 保存用户 if err := common.GetDB().Create(&user).Error; err != nil { c.JSON(http.StatusOK, common.Error(500, "注册失败")) return } common.GetDB().Model(&user).Update("status", 0) c.JSON(http.StatusOK, common.Success(user)) } // GetCurrentUser 获取当前用户信息 func (h *AuthHandler) GetCurrentUser(c *gin.Context) { // 从token中获取用户信息 tokenMap, exists := c.Get("tokenMap") if !exists { c.JSON(http.StatusOK, common.Error(401, "未授权访问")) return } claims := tokenMap.(map[string]interface{}) userIDFloat, ok := claims["user_id"].(float64) if !ok { c.JSON(http.StatusOK, common.Error(401, "用户信息无效")) return } userID := uint(userIDFloat) // 查询用户信息 var user models.User if err := common.GetDB().First(&user, userID).Error; err != nil { c.JSON(http.StatusOK, common.Error(404, "用户不存在")) return } c.JSON(http.StatusOK, common.Success(user)) } // UpdateProfileRequest 更新个人信息请求结构体 type UpdateProfileRequest struct { CustomerName string `json:"customer_name" binding:"required"` RealName string `json:"real_name" binding:"required"` Avatar string `json:"avatar"` CompanyName string `json:"company_name"` PersonalIntro string `json:"personal_intro"` BusinessLicense string `json:"business_license"` IDCardFront string `json:"id_card_front"` IDCardBack string `json:"id_card_back"` MainPaymentCode string `json:"main_payment_code"` BackupPaymentCode string `json:"backup_payment_code"` Phone string `json:"phone"` } // UpdateProfile 更新个人信息 func (h *AuthHandler) UpdateProfile(c *gin.Context) { // 从token中获取用户信息 tokenMap, exists := c.Get("tokenMap") if !exists { c.JSON(http.StatusOK, common.Error(401, "未授权访问")) return } claims := tokenMap.(map[string]interface{}) userIDFloat, ok := claims["user_id"].(float64) if !ok { c.JSON(http.StatusOK, common.Error(401, "用户信息无效")) return } userID := uint(userIDFloat) var req UpdateProfileRequest if err := c.ShouldBindJSON(&req); err != nil { c.JSON(http.StatusOK, common.Error(400, "参数错误: "+err.Error())) return } // 查询当前用户 var user models.User if err := common.GetDB().First(&user, userID).Error; err != nil { c.JSON(http.StatusOK, common.Error(404, "用户不存在")) return } // 更新用户信息 updateData := models.User{ CustomerName: req.CustomerName, RealName: req.RealName, Avatar: req.Avatar, CompanyName: req.CompanyName, PersonalIntro: req.PersonalIntro, BusinessLicenseImage: req.BusinessLicense, IdCardFrontImage: req.IDCardFront, IdCardBackImage: req.IDCardBack, MainPaymentQrImage: &req.MainPaymentCode, SubPaymentQrImage: &req.BackupPaymentCode, Phone: req.Phone, } updateData.ID = userID if err := common.GetDB().Model(&user).Updates(&updateData).Error; err != nil { c.JSON(http.StatusOK, common.Error(500, "更新个人信息失败")) return } // 返回更新后的用户信息 var updatedUser models.User common.GetDB().First(&updatedUser, userID) c.JSON(http.StatusOK, common.Success(updatedUser)) } // ChangePasswordRequest 修改密码请求结构体 type ChangePasswordRequest struct { CurrentPassword string `json:"current_password" binding:"required"` NewPassword string `json:"new_password" binding:"required"` } // ChangePassword 修改密码 func (h *AuthHandler) ChangePassword(c *gin.Context) { // 从token中获取用户信息 tokenMap, exists := c.Get("tokenMap") if !exists { c.JSON(http.StatusOK, common.Error(401, "未授权访问")) return } claims := tokenMap.(map[string]interface{}) userIDFloat, ok := claims["user_id"].(float64) if !ok { c.JSON(http.StatusOK, common.Error(401, "用户信息无效")) return } userID := uint(userIDFloat) var req ChangePasswordRequest if err := c.ShouldBindJSON(&req); err != nil { c.JSON(http.StatusOK, common.Error(400, "参数错误: "+err.Error())) return } // 查询当前用户 var user models.User if err := common.GetDB().First(&user, userID).Error; err != nil { c.JSON(http.StatusOK, common.Error(404, "用户不存在")) return } // 验证当前密码 hashedCurrentPassword := fmt.Sprintf("%x", md5.Sum([]byte(req.CurrentPassword))) if hashedCurrentPassword != user.Password { c.JSON(http.StatusOK, common.Error(400, "当前密码错误")) return } // 加密新密码 hashedNewPassword := fmt.Sprintf("%x", md5.Sum([]byte(req.NewPassword))) // 更新密码 if err := common.GetDB().Model(&user).Update("password", hashedNewPassword).Error; err != nil { c.JSON(http.StatusOK, common.Error(500, "修改密码失败")) return } c.JSON(http.StatusOK, common.Success(nil)) } // SendSMSRequest 发送短信验证码请求结构体 type SendSMSRequest struct { Phone string `json:"phone" binding:"required"` } // SendSMS 发送短信验证码 func (h *AuthHandler) SendSMS(c *gin.Context) { var req SendSMSRequest if err := c.ShouldBindJSON(&req); err != nil { c.JSON(http.StatusOK, common.Error(400, "参数错误: "+err.Error())) return } // 获取客户端IP地址 clientIP := getClientIP(c) // 调用短信服务发送验证码 smsService := services.GetSMSService() code, err := smsService.SendSMS(req.Phone, clientIP) if err != nil { c.JSON(http.StatusOK, common.Error(400, err.Error())) return } // 根据环境决定是否返回验证码(开发环境返回,生产环境不返回) config := common.MineConfig response := map[string]interface{}{ "message": "验证码已发送", } // 仅在开发环境返回验证码,方便测试 if config != nil && config.App.Env == "development" { response["code"] = code } c.JSON(http.StatusOK, common.Success(response)) } // getClientIP 获取客户端真实IP地址 func getClientIP(c *gin.Context) string { // 优先从 X-Forwarded-For 获取(经过代理时) ip := c.GetHeader("X-Forwarded-For") if ip != "" { // X-Forwarded-For 可能包含多个IP,取第一个 ips := strings.Split(ip, ",") if len(ips) > 0 { return strings.TrimSpace(ips[0]) } } // 从 X-Real-IP 获取 ip = c.GetHeader("X-Real-IP") if ip != "" { return strings.TrimSpace(ip) } // 最后从 RemoteAddr 获取 ip = c.ClientIP() return ip }