# Service层实现文档 ## 一、认证Service(AuthService) ### 1.1 功能概述 实现了用户认证相关的核心功能,包括: - 用户注册 - 用户登录 - 用户登出 - Token刷新 - Token验证 ### 1.2 接口定义 ```go type AuthService interface { // Register 注册 Register(req *pb.RegisterRequest) (*pb.RegisterResponse, error) // Login 登录 Login(req *pb.LoginRequest) (*pb.LoginResponse, error) // Logout 登出 Logout(req *pb.LogoutRequest) (*pb.LogoutResponse, error) // RefreshToken 刷新Token RefreshToken(req *pb.RefreshTokenRequest) (*pb.RefreshTokenResponse, error) // ValidateToken 验证Token(用于中间件) ValidateToken(req *pb.ValidateTokenRequest) (*pb.ValidateTokenResponse, error) } ``` ### 1.3 实现流程 #### 1.3.1 注册流程 1. 参数验证(手机号、密码、昵称、star_id) 2. 验证手机号是否已存在 3. 验证明星是否存在 4. 使用事务创建用户和粉丝档案 - 创建用户(加密密码) - 创建第一个粉丝档案 - 生成JWT Token - 更新用户Token 5. 返回Token和用户信息 #### 1.3.2 登录流程 1. 参数验证(手机号、密码) 2. 根据手机号查询用户 3. 验证密码(bcrypt比对) 4. 验证用户是否激活 5. 获取用户的粉丝档案列表 6. 生成JWT Token(包含user_id和当前star_id) 7. 更新用户Token 8. 返回Token和用户信息 #### 1.3.3 Token刷新流程 1. 解析旧Token(即使过期也要解析) 2. 查询用户 3. 验证旧Token是否匹配数据库中的Token 4. 验证updated_at是否匹配(如果用户信息更新,Token失效) 5. 生成新Token 6. 更新数据库中的Token 7. 返回新Token #### 1.3.4 Token验证流程 1. 解析和验证Token(检查签名和过期时间) 2. 查询用户验证Token是否匹配 3. 验证用户是否激活 4. 验证Token是否匹配数据库中的Token 5. 验证updated_at是否匹配 6. 返回验证结果 #### 1.3.5 登出流程 1. 从Token中提取user_id 2. 清除用户Token ### 1.4 依赖 - `UserRepository` - 用户数据访问 - `FanProfileRepository` - 粉丝档案数据访问 - `StarRepository` - 明星信息数据访问 - `JWT工具` - Token生成和解析 - `Logger` - 日志记录 - `Validator` - 参数验证 ### 1.5 使用示例 ```go // 创建Service实例 userRepo := repository.NewUserRepository() fanProfileRepo := repository.NewFanProfileRepository() starRepo := repository.NewStarRepository() db := database.GetDB() authService := NewAuthService(userRepo, fanProfileRepo, starRepo, db) // 用户注册 registerReq := &pb.RegisterRequest{ Mobile: "13800138000", Password: "123456", StarId: 1, Nickname: "粉丝昵称", } registerResp, err := authService.Register(registerReq) // 用户登录 loginReq := &pb.LoginRequest{ Mobile: "13800138000", Password: "123456", } loginResp, err := authService.Login(loginReq) // 刷新Token refreshReq := &pb.RefreshTokenRequest{ AccessToken: "old_token_here", } refreshResp, err := authService.RefreshToken(refreshReq) // 验证Token validateReq := &pb.ValidateTokenRequest{ AccessToken: "token_here", } validateResp, err := authService.ValidateToken(validateReq) // 登出 logoutReq := &pb.LogoutRequest{ AccessToken: "token_here", } logoutResp, err := authService.Logout(logoutReq) ``` ### 1.6 错误处理 Service层返回的错误类型: - `ErrUserNotFound` - 用户不存在 - `ErrUserAlreadyExists` - 用户已存在 - `ErrInvalidPassword` - 密码错误 - `ErrInvalidToken` - Token无效 - `ErrTokenExpired` - Token过期 - `ErrTokenMismatch` - Token不匹配 - `ErrUserInactive` - 用户未激活 - `ErrInvalidMobile` - 手机号格式错误 - `ErrPasswordTooShort` - 密码太短 - `ErrInvalidStarID` - 明星ID无效 - `ErrStarNotFound` - 明星不存在 所有错误都会被记录到日志中,便于调试和监控。 ### 1.7 注意事项 1. **事务处理**:注册流程使用数据库事务,确保用户和粉丝档案的创建原子性 2. **密码安全**:密码使用bcrypt加密存储,不存储明文 3. **Token管理**:Token存储在数据库中,支持单设备登录 4. **Token失效**:当用户信息更新(updated_at改变)时,旧Token会自动失效 5. **日志记录**:所有关键操作都会记录日志,包括成功和失败场景 ### 1.8 测试要点 - 注册成功和失败场景 - 登录成功和失败场景 - Token生成和验证 - Token刷新 - 修改密码后Token失效 - 用户信息更新后Token失效 --- ## 二、用户信息Service(UserService) ### 2.1 功能概述 实现了用户信息相关的核心功能,包括: - 获取用户信息 - 获取粉丝档案 - 获取个人信息页数据 - 修改昵称 - 修改密码 ### 2.2 接口定义 ```go type UserService interface { // GetUser 获取用户信息 GetUser(req *pb.GetUserRequest) (*pb.GetUserResponse, error) // GetFanProfile 获取粉丝档案 GetFanProfile(req *pb.GetFanProfileRequest) (*pb.GetFanProfileResponse, error) // GetMyProfile 获取个人信息页 GetMyProfile(req *pb.GetMyProfileRequest, userID, starID int64) (*pb.GetMyProfileResponse, error) // UpdateNickname 修改昵称 UpdateNickname(req *pb.UpdateNicknameRequest, userID, starID int64) (*pb.UpdateNicknameResponse, error) // UpdatePassword 修改密码 UpdatePassword(req *pb.UpdatePasswordRequest, userID int64) (*pb.UpdatePasswordResponse, error) } ``` ### 2.3 实现流程 #### 2.3.1 获取用户信息流程 1. 参数验证(user_id) 2. 查询用户 3. 返回用户信息 #### 2.3.2 获取粉丝档案流程 1. 参数验证(user_id, star_id) 2. 查询粉丝档案 3. 返回粉丝档案信息 #### 2.3.3 获取个人信息页流程 1. 参数验证(user_id, star_id) 2. 查询用户信息 3. 查询当前粉丝档案 4. 查询用户的所有粉丝身份 5. 聚合返回完整信息 #### 2.3.4 修改昵称流程 1. 参数验证(user_id, star_id, nickname) 2. 验证粉丝档案是否存在 3. 更新昵称 4. 查询更新后的粉丝档案 5. 返回更新后的信息 #### 2.3.5 修改密码流程 1. 参数验证(user_id, old_password, new_password) 2. 查询用户 3. 验证旧密码 4. 加密新密码 5. 使用事务更新密码和updated_at,清除Token 6. 返回成功响应 **重要**:修改密码时,会更新`updated_at`并清除Token,导致旧Token失效,需要重新登录。 ### 2.4 依赖 - `UserRepository` - 用户数据访问 - `FanProfileRepository` - 粉丝档案数据访问 ### 2.5 使用示例 ```go // 创建Service实例 userRepo := repository.NewUserRepository() fanProfileRepo := repository.NewFanProfileRepository() db := database.GetDB() userService := NewUserService(userRepo, fanProfileRepo, db) // 获取用户信息 getUserReq := &pb.GetUserRequest{ UserId: 10000001, } getUserResp, err := userService.GetUser(getUserReq) // 获取粉丝档案 getFanProfileReq := &pb.GetFanProfileRequest{ UserId: 10000001, StarId: 1, } getFanProfileResp, err := userService.GetFanProfile(getFanProfileReq) // 获取个人信息页 getMyProfileReq := &pb.GetMyProfileRequest{} getMyProfileResp, err := userService.GetMyProfile(getMyProfileReq, 10000001, 1) // 修改昵称 updateNicknameReq := &pb.UpdateNicknameRequest{ Nickname: "新昵称", } updateNicknameResp, err := userService.UpdateNickname(updateNicknameReq, 10000001, 1) // 修改密码 updatePasswordReq := &pb.UpdatePasswordRequest{ OldPassword: "旧密码", NewPassword: "新密码", } updatePasswordResp, err := userService.UpdatePassword(updatePasswordReq, 10000001) ``` ### 2.6 错误处理 Service层返回的错误类型: - `ErrUserNotFound` - 用户不存在 - `ErrFanProfileNotFound` - 粉丝档案不存在 - `ErrInvalidPassword` - 密码错误 - `ErrInvalidUserID` - 用户ID无效 - `ErrInvalidStarID` - 明星ID无效 - `ErrPasswordTooShort` - 密码太短 所有错误都会被记录到日志中,便于调试和监控。 ### 2.7 注意事项 1. **密码安全**:修改密码时使用bcrypt加密存储新密码 2. **Token失效**:修改密码后,`updated_at`会更新,旧Token会自动失效 3. **事务处理**:修改密码使用数据库事务,确保密码更新和Token清除的原子性 4. **数据聚合**:获取个人信息页需要聚合用户信息、当前粉丝档案和所有粉丝身份 5. **日志记录**:所有关键操作都会记录日志,包括成功和失败场景 ### 2.8 测试要点 - 获取用户信息成功和失败场景 - 获取粉丝档案成功和失败场景 - 获取个人信息页(数据聚合) - 修改昵称成功和失败场景 - 修改密码成功和失败场景 - 修改密码后Token失效验证 --- ## 三、粉丝身份Service(IdentityService) ### 3.1 功能概述 实现了粉丝身份相关的核心功能,包括: - 获取可选粉丝身份列表(支持搜索) - 新增粉丝身份(最多2个) - 切换粉丝身份(生成新Token) ### 3.2 接口定义 ```go type IdentityService interface { // GetFanIdentities 获取可选粉丝身份列表 GetFanIdentities(req *pb.GetFanIdentitiesRequest) (*pb.GetFanIdentitiesResponse, error) // AddIdentity 新增粉丝身份 AddIdentity(req *pb.AddIdentityRequest, userID int64) (*pb.AddIdentityResponse, error) // SwitchIdentity 切换粉丝身份 SwitchIdentity(req *pb.SwitchIdentityRequest, userID int64, currentStarID int64) (*pb.SwitchIdentityResponse, error) } ``` ### 3.3 实现流程 #### 3.3.1 获取可选粉丝身份列表流程 1. 如果有关键词,调用Search搜索;否则调用GetAllActive获取所有可用明星 2. 转换为proto类型 3. 返回明星列表 #### 3.3.2 新增粉丝身份流程 1. 参数验证(user_id, star_id, nickname) 2. 检查用户已有的粉丝身份数量(最多2个) 3. 验证明星是否存在 4. 检查该用户是否已有该明星的身份 5. 创建新的粉丝档案 6. 返回新创建的粉丝档案 #### 3.3.3 切换粉丝身份流程 1. 参数验证(user_id, new_star_id) 2. 检查是否切换到相同的身份 3. 查询用户 4. 验证新身份是否存在 5. 生成新Token(包含新的star_id) 6. 更新用户Token 7. 返回新Token和粉丝档案 ### 3.4 依赖 - `FanProfileRepository` - 粉丝档案数据访问 - `StarRepository` - 明星信息数据访问 - `UserRepository` - 用户数据访问(用于切换身份时更新Token) - `JWT工具` - Token生成(切换身份时) ### 3.5 使用示例 ```go // 创建Service实例 fanProfileRepo := repository.NewFanProfileRepository() starRepo := repository.NewStarRepository() userRepo := repository.NewUserRepository() db := database.GetDB() identityService := NewIdentityService(fanProfileRepo, starRepo, userRepo, db) // 获取可选粉丝身份列表 getFanIdentitiesReq := &pb.GetFanIdentitiesRequest{ Keyword: "明星", // 可选,为空则返回所有 } getFanIdentitiesResp, err := identityService.GetFanIdentities(getFanIdentitiesReq) // 新增粉丝身份 addIdentityReq := &pb.AddIdentityRequest{ StarId: 2, Nickname: "新身份昵称", } addIdentityResp, err := identityService.AddIdentity(addIdentityReq, 10000001) // 切换粉丝身份 switchIdentityReq := &pb.SwitchIdentityRequest{ NewStarId: 2, } switchIdentityResp, err := identityService.SwitchIdentity(switchIdentityReq, 10000001, 1) ``` ### 3.6 错误处理 Service层返回的错误类型: - `ErrFanProfileNotFound` - 粉丝档案不存在 - `ErrStarNotFound` - 明星不存在 - `ErrInvalidStarID` - 明星ID无效 - `ErrMaxIdentitiesReached` - 已达到最大身份数量(最多2个) 所有错误都会被记录到日志中,便于调试和监控。 ### 3.7 注意事项 1. **身份数量限制**:一个用户最多可以拥有2个粉丝身份,新增时会检查 2. **Token更新**:切换身份时会生成新的JWT Token,包含新的star_id 3. **重复检查**:新增身份时会检查用户是否已有该明星的身份 4. **日志记录**:所有关键操作都会记录日志,包括成功和失败场景 ### 3.8 测试要点 - 获取可选粉丝身份列表(带关键词和不带关键词) - 新增粉丝身份成功和失败场景 - 新增身份时数量限制检查(最多2个) - 切换粉丝身份成功和失败场景 - 切换到相同身份的处理 - 切换身份后Token更新验证