384 lines
13 KiB
Go
384 lines
13 KiB
Go
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"
|
||
finance_service "tyapi-server/internal/domains/finance/services"
|
||
"tyapi-server/internal/domains/user/entities"
|
||
"tyapi-server/internal/domains/user/events"
|
||
user_service "tyapi-server/internal/domains/user/services"
|
||
"tyapi-server/internal/shared/interfaces"
|
||
"tyapi-server/internal/shared/middleware"
|
||
)
|
||
|
||
// UserApplicationServiceImpl 用户应用服务实现
|
||
// 负责业务流程编排、事务管理、数据转换,不直接操作仓库
|
||
type UserApplicationServiceImpl struct {
|
||
userAggregateService user_service.UserAggregateService
|
||
userAuthService *user_service.UserAuthService
|
||
smsCodeService *user_service.SMSCodeService
|
||
walletService finance_service.WalletAggregateService
|
||
eventBus interfaces.EventBus
|
||
jwtAuth *middleware.JWTAuthMiddleware
|
||
logger *zap.Logger
|
||
}
|
||
|
||
// NewUserApplicationService 创建用户应用服务
|
||
func NewUserApplicationService(
|
||
userAggregateService user_service.UserAggregateService,
|
||
userAuthService *user_service.UserAuthService,
|
||
smsCodeService *user_service.SMSCodeService,
|
||
walletService finance_service.WalletAggregateService,
|
||
eventBus interfaces.EventBus,
|
||
jwtAuth *middleware.JWTAuthMiddleware,
|
||
logger *zap.Logger,
|
||
) UserApplicationService {
|
||
return &UserApplicationServiceImpl{
|
||
userAggregateService: userAggregateService,
|
||
userAuthService: userAuthService,
|
||
smsCodeService: smsCodeService,
|
||
walletService: walletService,
|
||
eventBus: eventBus,
|
||
jwtAuth: jwtAuth,
|
||
logger: logger,
|
||
}
|
||
}
|
||
|
||
// Register 用户注册
|
||
// 业务流程:1. 验证短信验证码 2. 创建用户 3. 发布注册事件
|
||
func (s *UserApplicationServiceImpl) Register(ctx context.Context, cmd *commands.RegisterUserCommand) (*responses.RegisterUserResponse, error) {
|
||
// 1. 验证短信验证码
|
||
if err := s.smsCodeService.VerifyCode(ctx, cmd.Phone, cmd.Code, entities.SMSSceneRegister); err != nil {
|
||
return nil, fmt.Errorf("验证码错误或已过期")
|
||
}
|
||
|
||
// 2. 创建用户
|
||
user, err := s.userAggregateService.CreateUser(ctx, cmd.Phone, cmd.Password)
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
|
||
// 3. 发布用户注册事件
|
||
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: user.ID,
|
||
Phone: user.Phone,
|
||
}, nil
|
||
}
|
||
|
||
// LoginWithPassword 密码登录
|
||
// 业务流程:1. 验证用户密码 2. 生成访问令牌 3. 更新登录统计 4. 获取用户权限
|
||
func (s *UserApplicationServiceImpl) LoginWithPassword(ctx context.Context, cmd *commands.LoginWithPasswordCommand) (*responses.LoginUserResponse, error) {
|
||
// 1. 验证用户密码
|
||
user, err := s.userAuthService.ValidatePassword(ctx, cmd.Phone, cmd.Password)
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
|
||
// 2. 生成包含用户类型的token
|
||
accessToken, err := s.jwtAuth.GenerateToken(user.ID, user.Phone, user.Phone, user.UserType)
|
||
if err != nil {
|
||
s.logger.Error("生成令牌失败", zap.Error(err))
|
||
return nil, fmt.Errorf("生成访问令牌失败")
|
||
}
|
||
|
||
// 3. 如果是管理员,更新登录统计
|
||
if user.IsAdmin() {
|
||
if err := s.userAggregateService.UpdateLoginStats(ctx, user.ID); err != nil {
|
||
s.logger.Error("更新登录统计失败", zap.Error(err))
|
||
}
|
||
// 重新获取用户信息以获取最新的登录统计
|
||
updatedUser, err := s.userAggregateService.GetUserByID(ctx, user.ID)
|
||
if err != nil {
|
||
s.logger.Error("重新获取用户信息失败", zap.Error(err))
|
||
} else {
|
||
user = updatedUser
|
||
}
|
||
}
|
||
|
||
// 4. 获取用户权限(仅管理员)
|
||
var permissions []string
|
||
if user.IsAdmin() {
|
||
permissions, err = s.userAuthService.GetUserPermissions(ctx, user)
|
||
if err != nil {
|
||
s.logger.Error("获取用户权限失败", zap.Error(err))
|
||
permissions = []string{}
|
||
}
|
||
}
|
||
|
||
// 5. 构建用户信息
|
||
userProfile := &responses.UserProfileResponse{
|
||
ID: user.ID,
|
||
Phone: user.Phone,
|
||
Username: user.Username,
|
||
UserType: user.UserType,
|
||
IsActive: user.Active,
|
||
LastLoginAt: user.LastLoginAt,
|
||
LoginCount: user.LoginCount,
|
||
Permissions: permissions,
|
||
CreatedAt: user.CreatedAt,
|
||
UpdatedAt: user.UpdatedAt,
|
||
}
|
||
|
||
return &responses.LoginUserResponse{
|
||
User: userProfile,
|
||
AccessToken: accessToken,
|
||
TokenType: "Bearer",
|
||
ExpiresIn: 86400, // 24h
|
||
LoginMethod: "password",
|
||
}, nil
|
||
}
|
||
|
||
// LoginWithSMS 短信验证码登录
|
||
// 业务流程:1. 验证短信验证码 2. 验证用户登录状态 3. 生成访问令牌 4. 更新登录统计 5. 获取用户权限
|
||
func (s *UserApplicationServiceImpl) LoginWithSMS(ctx context.Context, cmd *commands.LoginWithSMSCommand) (*responses.LoginUserResponse, error) {
|
||
// 1. 验证短信验证码
|
||
if err := s.smsCodeService.VerifyCode(ctx, cmd.Phone, cmd.Code, entities.SMSSceneLogin); err != nil {
|
||
return nil, fmt.Errorf("验证码错误或已过期")
|
||
}
|
||
|
||
// 2. 验证用户登录状态
|
||
user, err := s.userAuthService.ValidateUserLogin(ctx, cmd.Phone)
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
|
||
// 3. 生成包含用户类型的token
|
||
accessToken, err := s.jwtAuth.GenerateToken(user.ID, user.Phone, user.Phone, user.UserType)
|
||
if err != nil {
|
||
s.logger.Error("生成令牌失败", zap.Error(err))
|
||
return nil, fmt.Errorf("生成访问令牌失败")
|
||
}
|
||
|
||
// 4. 如果是管理员,更新登录统计
|
||
if user.IsAdmin() {
|
||
if err := s.userAggregateService.UpdateLoginStats(ctx, user.ID); err != nil {
|
||
s.logger.Error("更新登录统计失败", zap.Error(err))
|
||
}
|
||
// 重新获取用户信息以获取最新的登录统计
|
||
updatedUser, err := s.userAggregateService.GetUserByID(ctx, user.ID)
|
||
if err != nil {
|
||
s.logger.Error("重新获取用户信息失败", zap.Error(err))
|
||
} else {
|
||
user = updatedUser
|
||
}
|
||
}
|
||
|
||
// 5. 获取用户权限(仅管理员)
|
||
var permissions []string
|
||
if user.IsAdmin() {
|
||
permissions, err = s.userAuthService.GetUserPermissions(ctx, user)
|
||
if err != nil {
|
||
s.logger.Error("获取用户权限失败", zap.Error(err))
|
||
permissions = []string{}
|
||
}
|
||
}
|
||
|
||
// 6. 构建用户信息
|
||
userProfile := &responses.UserProfileResponse{
|
||
ID: user.ID,
|
||
Phone: user.Phone,
|
||
Username: user.Username,
|
||
UserType: user.UserType,
|
||
IsActive: user.Active,
|
||
LastLoginAt: user.LastLoginAt,
|
||
LoginCount: user.LoginCount,
|
||
Permissions: permissions,
|
||
CreatedAt: user.CreatedAt,
|
||
UpdatedAt: user.UpdatedAt,
|
||
}
|
||
|
||
return &responses.LoginUserResponse{
|
||
User: userProfile,
|
||
AccessToken: accessToken,
|
||
TokenType: "Bearer",
|
||
ExpiresIn: int64(s.jwtAuth.GetExpiresIn().Seconds()), // 168h
|
||
LoginMethod: "sms",
|
||
}, nil
|
||
}
|
||
|
||
// SendSMS 发送短信验证码
|
||
// 业务流程:1. 发送短信验证码
|
||
func (s *UserApplicationServiceImpl) SendSMS(ctx context.Context, cmd *commands.SendCodeCommand) error {
|
||
return s.smsCodeService.SendCode(ctx, cmd.Phone, entities.SMSScene(cmd.Scene), "", "")
|
||
}
|
||
|
||
// ChangePassword 修改密码
|
||
// 业务流程:1. 修改用户密码
|
||
func (s *UserApplicationServiceImpl) ChangePassword(ctx context.Context, cmd *commands.ChangePasswordCommand) error {
|
||
return s.userAuthService.ChangePassword(ctx, cmd.UserID, cmd.OldPassword, cmd.NewPassword)
|
||
}
|
||
|
||
// ResetPassword 重置密码
|
||
// 业务流程:1. 验证短信验证码 2. 重置用户密码
|
||
func (s *UserApplicationServiceImpl) ResetPassword(ctx context.Context, cmd *commands.ResetPasswordCommand) error {
|
||
// 1. 验证短信验证码
|
||
if err := s.smsCodeService.VerifyCode(ctx, cmd.Phone, cmd.Code, entities.SMSSceneResetPassword); err != nil {
|
||
return fmt.Errorf("验证码错误或已过期")
|
||
}
|
||
|
||
// 2. 重置用户密码
|
||
return s.userAuthService.ResetPassword(ctx, cmd.Phone, cmd.NewPassword)
|
||
}
|
||
|
||
// GetUserProfile 获取用户资料
|
||
// 业务流程:1. 获取用户信息 2. 获取企业信息 3. 构建响应数据
|
||
func (s *UserApplicationServiceImpl) GetUserProfile(ctx context.Context, userID string) (*responses.UserProfileResponse, error) {
|
||
// 1. 获取用户信息(包含企业信息)
|
||
user, err := s.userAggregateService.GetUserWithEnterpriseInfo(ctx, userID)
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
|
||
// 2. 获取用户权限(仅管理员)
|
||
var permissions []string
|
||
if user.IsAdmin() {
|
||
permissions, err = s.userAuthService.GetUserPermissions(ctx, user)
|
||
if err != nil {
|
||
s.logger.Error("获取用户权限失败", zap.Error(err))
|
||
permissions = []string{}
|
||
}
|
||
}
|
||
|
||
// 3. 构建用户信息
|
||
userProfile := &responses.UserProfileResponse{
|
||
ID: user.ID,
|
||
Phone: user.Phone,
|
||
Username: user.Username,
|
||
UserType: user.UserType,
|
||
IsActive: user.Active,
|
||
IsCertified: user.IsCertified,
|
||
LastLoginAt: user.LastLoginAt,
|
||
LoginCount: user.LoginCount,
|
||
Permissions: permissions,
|
||
CreatedAt: user.CreatedAt,
|
||
UpdatedAt: user.UpdatedAt,
|
||
}
|
||
|
||
// 4. 添加企业信息
|
||
if user.EnterpriseInfo != nil {
|
||
userProfile.EnterpriseInfo = &responses.EnterpriseInfoResponse{
|
||
ID: user.EnterpriseInfo.ID,
|
||
CompanyName: user.EnterpriseInfo.CompanyName,
|
||
UnifiedSocialCode: user.EnterpriseInfo.UnifiedSocialCode,
|
||
LegalPersonName: user.EnterpriseInfo.LegalPersonName,
|
||
LegalPersonID: user.EnterpriseInfo.LegalPersonID,
|
||
LegalPersonPhone: user.EnterpriseInfo.LegalPersonPhone,
|
||
EnterpriseAddress: user.EnterpriseInfo.EnterpriseAddress,
|
||
EnterpriseEmail: user.EnterpriseInfo.EnterpriseEmail,
|
||
CreatedAt: user.EnterpriseInfo.CreatedAt,
|
||
UpdatedAt: user.EnterpriseInfo.UpdatedAt,
|
||
}
|
||
}
|
||
|
||
return userProfile, nil
|
||
}
|
||
|
||
// GetUser 获取用户信息
|
||
// 业务流程:1. 获取用户信息 2. 构建响应数据
|
||
func (s *UserApplicationServiceImpl) GetUser(ctx context.Context, query *queries.GetUserQuery) (*responses.UserProfileResponse, error) {
|
||
user, err := s.userAggregateService.GetUserByID(ctx, query.UserID)
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
|
||
return &responses.UserProfileResponse{
|
||
ID: user.ID,
|
||
Phone: user.Phone,
|
||
Username: user.Username,
|
||
UserType: user.UserType,
|
||
IsActive: user.Active,
|
||
LastLoginAt: user.LastLoginAt,
|
||
LoginCount: user.LoginCount,
|
||
CreatedAt: user.CreatedAt,
|
||
UpdatedAt: user.UpdatedAt,
|
||
}, nil
|
||
}
|
||
|
||
// ListUsers 获取用户列表(管理员功能)
|
||
// 业务流程:1. 查询用户列表 2. 构建响应数据
|
||
func (s *UserApplicationServiceImpl) ListUsers(ctx context.Context, query *queries.ListUsersQuery) (*responses.UserListResponse, error) {
|
||
// 1. 查询用户列表
|
||
users, total, err := s.userAggregateService.ListUsers(ctx, query.ToDomainQuery())
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
|
||
// 2. 构建响应数据
|
||
items := make([]*responses.UserListItem, 0, len(users))
|
||
for _, user := range users {
|
||
item := &responses.UserListItem{
|
||
ID: user.ID,
|
||
Phone: user.Phone,
|
||
UserType: user.UserType,
|
||
Username: user.Username,
|
||
IsActive: user.Active,
|
||
IsCertified: user.IsCertified,
|
||
LoginCount: user.LoginCount,
|
||
LastLoginAt: user.LastLoginAt,
|
||
CreatedAt: user.CreatedAt,
|
||
UpdatedAt: user.UpdatedAt,
|
||
}
|
||
|
||
// 添加企业信息
|
||
if user.EnterpriseInfo != nil {
|
||
item.EnterpriseInfo = &responses.EnterpriseInfoItem{
|
||
ID: user.EnterpriseInfo.ID,
|
||
CompanyName: user.EnterpriseInfo.CompanyName,
|
||
UnifiedSocialCode: user.EnterpriseInfo.UnifiedSocialCode,
|
||
LegalPersonName: user.EnterpriseInfo.LegalPersonName,
|
||
LegalPersonPhone: user.EnterpriseInfo.LegalPersonPhone,
|
||
EnterpriseAddress: user.EnterpriseInfo.EnterpriseAddress,
|
||
EnterpriseEmail: user.EnterpriseInfo.EnterpriseEmail,
|
||
CreatedAt: user.EnterpriseInfo.CreatedAt,
|
||
}
|
||
}
|
||
|
||
// 添加钱包余额信息
|
||
wallet, err := s.walletService.LoadWalletByUserId(ctx, user.ID)
|
||
if err == nil && wallet != nil {
|
||
item.WalletBalance = wallet.Balance.String()
|
||
} else {
|
||
item.WalletBalance = "0"
|
||
}
|
||
|
||
items = append(items, item)
|
||
}
|
||
|
||
return &responses.UserListResponse{
|
||
Items: items,
|
||
Total: total,
|
||
Page: query.Page,
|
||
Size: query.PageSize,
|
||
}, nil
|
||
}
|
||
|
||
// GetUserStats 获取用户统计信息(管理员功能)
|
||
// 业务流程:1. 查询用户统计信息 2. 构建响应数据
|
||
func (s *UserApplicationServiceImpl) GetUserStats(ctx context.Context) (*responses.UserStatsResponse, error) {
|
||
// 1. 查询用户统计信息
|
||
stats, err := s.userAggregateService.GetUserStats(ctx)
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
|
||
// 2. 构建响应数据
|
||
return &responses.UserStatsResponse{
|
||
TotalUsers: stats.TotalUsers,
|
||
ActiveUsers: stats.ActiveUsers,
|
||
CertifiedUsers: stats.CertifiedUsers,
|
||
}, nil
|
||
}
|