package user import ( "context" "fmt" "go.uber.org/zap" "tyapi-server/internal/application/user/dto/commands" "tyapi-server/internal/application/user/dto/queries" "tyapi-server/internal/application/user/dto/responses" "tyapi-server/internal/domains/user/entities" "tyapi-server/internal/domains/user/events" "tyapi-server/internal/domains/user/repositories" user_service "tyapi-server/internal/domains/user/services" "tyapi-server/internal/shared/interfaces" "tyapi-server/internal/shared/middleware" ) // UserApplicationServiceImpl 用户应用服务实现 type UserApplicationServiceImpl struct { userRepo repositories.UserRepository enterpriseInfoRepo repositories.EnterpriseInfoRepository smsCodeService *user_service.SMSCodeService eventBus interfaces.EventBus jwtAuth *middleware.JWTAuthMiddleware logger *zap.Logger } // NewUserApplicationService 创建用户应用服务 func NewUserApplicationService( userRepo repositories.UserRepository, enterpriseInfoRepo repositories.EnterpriseInfoRepository, smsCodeService *user_service.SMSCodeService, eventBus interfaces.EventBus, jwtAuth *middleware.JWTAuthMiddleware, logger *zap.Logger, ) UserApplicationService { return &UserApplicationServiceImpl{ userRepo: userRepo, enterpriseInfoRepo: enterpriseInfoRepo, smsCodeService: smsCodeService, eventBus: eventBus, jwtAuth: jwtAuth, logger: logger, } } // Register 用户注册 func (s *UserApplicationServiceImpl) Register(ctx context.Context, cmd *commands.RegisterUserCommand) (*responses.RegisterUserResponse, error) { if err := s.smsCodeService.VerifyCode(ctx, cmd.Phone, cmd.Code, entities.SMSSceneRegister); err != nil { return nil, fmt.Errorf("验证码错误或已过期") } if _, err := s.userRepo.GetByPhone(ctx, cmd.Phone); err == nil { return nil, fmt.Errorf("手机号已存在") } user, err := entities.NewUser(cmd.Phone, cmd.Password) if err != nil { return nil, fmt.Errorf("创建用户失败: %w", err) } createdUser, err := s.userRepo.Create(ctx, *user) if err != nil { s.logger.Error("创建用户失败", zap.Error(err)) return nil, fmt.Errorf("创建用户失败: %w", err) } event := events.NewUserRegisteredEvent(user, "") if err := s.eventBus.Publish(ctx, event); err != nil { s.logger.Warn("发布用户注册事件失败", zap.Error(err)) } s.logger.Info("用户注册成功", zap.String("user_id", user.ID), zap.String("phone", user.Phone)) return &responses.RegisterUserResponse{ ID: createdUser.ID, Phone: user.Phone, }, nil } // LoginWithPassword 密码登录 func (s *UserApplicationServiceImpl) LoginWithPassword(ctx context.Context, cmd *commands.LoginWithPasswordCommand) (*responses.LoginUserResponse, error) { user, err := s.userRepo.GetByPhone(ctx, cmd.Phone) if err != nil { return nil, fmt.Errorf("用户名或密码错误") } if !user.CanLogin() { return nil, fmt.Errorf("用户状态异常,无法登录") } if !user.CheckPassword(cmd.Password) { return nil, fmt.Errorf("用户名或密码错误") } accessToken, err := s.jwtAuth.GenerateToken(user.ID, user.Phone, user.Phone) if err != nil { s.logger.Error("生成令牌失败", zap.Error(err)) return nil, fmt.Errorf("生成访问令牌失败") } userProfile, err := s.GetUserProfile(ctx, user.ID) if err != nil { return nil, fmt.Errorf("获取用户信息失败: %w", err) } return &responses.LoginUserResponse{ User: userProfile, AccessToken: accessToken, TokenType: "Bearer", ExpiresIn: 86400, // 24h LoginMethod: "password", }, nil } // LoginWithSMS 短信验证码登录 func (s *UserApplicationServiceImpl) LoginWithSMS(ctx context.Context, cmd *commands.LoginWithSMSCommand) (*responses.LoginUserResponse, error) { if err := s.smsCodeService.VerifyCode(ctx, cmd.Phone, cmd.Code, entities.SMSSceneLogin); err != nil { return nil, fmt.Errorf("验证码错误或已过期") } user, err := s.userRepo.GetByPhone(ctx, cmd.Phone) if err != nil { return nil, fmt.Errorf("用户不存在") } if !user.CanLogin() { return nil, fmt.Errorf("用户状态异常,无法登录") } accessToken, err := s.jwtAuth.GenerateToken(user.ID, user.Phone, user.Phone) if err != nil { s.logger.Error("生成令牌失败", zap.Error(err)) return nil, fmt.Errorf("生成访问令牌失败") } userProfile, err := s.GetUserProfile(ctx, user.ID) if err != nil { return nil, fmt.Errorf("获取用户信息失败: %w", err) } return &responses.LoginUserResponse{ User: userProfile, AccessToken: accessToken, TokenType: "Bearer", ExpiresIn: 86400, // 24h LoginMethod: "sms", }, nil } // ChangePassword 修改密码 func (s *UserApplicationServiceImpl) ChangePassword(ctx context.Context, cmd *commands.ChangePasswordCommand) error { user, err := s.userRepo.GetByID(ctx, cmd.UserID) if err != nil { return fmt.Errorf("用户不存在: %w", err) } if err := s.smsCodeService.VerifyCode(ctx, user.Phone, cmd.Code, entities.SMSSceneChangePassword); err != nil { return fmt.Errorf("验证码错误或已过期") } if err := user.ChangePassword(cmd.OldPassword, cmd.NewPassword, cmd.ConfirmNewPassword); err != nil { return err } if err := s.userRepo.Update(ctx, user); err != nil { return fmt.Errorf("密码更新失败: %w", err) } event := events.NewUserPasswordChangedEvent(user.ID, user.Phone, "") if err := s.eventBus.Publish(ctx, event); err != nil { s.logger.Warn("发布密码修改事件失败", zap.Error(err)) } s.logger.Info("密码修改成功", zap.String("user_id", cmd.UserID)) return nil } // ResetPassword 重置密码 func (s *UserApplicationServiceImpl) ResetPassword(ctx context.Context, cmd *commands.ResetPasswordCommand) error { user, err := s.userRepo.GetByPhone(ctx, cmd.Phone) if err != nil { return fmt.Errorf("用户不存在") } if err := s.smsCodeService.VerifyCode(ctx, cmd.Phone, cmd.Code, entities.SMSSceneResetPassword); err != nil { return fmt.Errorf("验证码错误或已过期") } if err := user.ResetPassword(cmd.NewPassword, cmd.ConfirmNewPassword); err != nil { return err } if err := s.userRepo.Update(ctx, *user); err != nil { return fmt.Errorf("密码更新失败: %w", err) } event := events.NewUserPasswordChangedEvent(user.ID, user.Phone, "") if err := s.eventBus.Publish(ctx, event); err != nil { s.logger.Warn("发布密码重置事件失败", zap.Error(err)) } s.logger.Info("密码重置成功", zap.String("user_id", user.ID), zap.String("phone", user.Phone)) return nil } // GetUserProfile 获取用户信息 func (s *UserApplicationServiceImpl) GetUserProfile(ctx context.Context, userID string) (*responses.UserProfileResponse, error) { if userID == "" { return nil, fmt.Errorf("用户ID不能为空") } user, err := s.userRepo.GetByID(ctx, userID) if err != nil { return nil, fmt.Errorf("用户不存在: %w", err) } response := &responses.UserProfileResponse{ ID: user.ID, Phone: user.Phone, CreatedAt: user.CreatedAt, UpdatedAt: user.UpdatedAt, } // 获取企业信息(如果存在) enterpriseInfo, err := s.enterpriseInfoRepo.GetByUserID(ctx, userID) if err != nil { s.logger.Debug("用户暂无企业信息", zap.String("user_id", userID)) response.IsCertified = false } else { response.EnterpriseInfo = &responses.EnterpriseInfoResponse{ ID: enterpriseInfo.ID, CompanyName: enterpriseInfo.CompanyName, UnifiedSocialCode: enterpriseInfo.UnifiedSocialCode, LegalPersonName: enterpriseInfo.LegalPersonName, LegalPersonID: enterpriseInfo.LegalPersonID, IsOCRVerified: enterpriseInfo.IsOCRVerified, IsFaceVerified: enterpriseInfo.IsFaceVerified, IsCertified: enterpriseInfo.IsCertified, CertifiedAt: enterpriseInfo.CertifiedAt, CreatedAt: enterpriseInfo.CreatedAt, UpdatedAt: enterpriseInfo.UpdatedAt, } response.IsCertified = enterpriseInfo.IsCertified } return response, nil } func (s *UserApplicationServiceImpl) GetUser(ctx context.Context, query *queries.GetUserQuery) (*responses.UserProfileResponse, error) { // ... implementation return nil, fmt.Errorf("not implemented") }