297 lines
		
	
	
		
			7.4 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
		
		
			
		
	
	
			297 lines
		
	
	
		
			7.4 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
|  | package service | |||
|  | 
 | |||
|  | import ( | |||
|  | 	"context" | |||
|  | 	"database/sql" | |||
|  | 	"hm-server/app/main/api/internal/config" | |||
|  | 	"hm-server/app/main/model" | |||
|  | 	"hm-server/common/ctxdata" | |||
|  | 	jwtx "hm-server/common/jwt" | |||
|  | 	"hm-server/common/xerr" | |||
|  | 
 | |||
|  | 	"github.com/google/uuid" | |||
|  | 	"github.com/pkg/errors" | |||
|  | 	"github.com/zeromicro/go-zero/core/stores/sqlx" | |||
|  | ) | |||
|  | 
 | |||
|  | type UserService struct { | |||
|  | 	Config        *config.Config | |||
|  | 	userModel     model.UserModel | |||
|  | 	userAuthModel model.UserAuthModel | |||
|  | 	userTempModel model.UserTempModel | |||
|  | 	agentModel    model.AgentModel | |||
|  | } | |||
|  | 
 | |||
|  | // NewUserService 创建UserService实例 | |||
|  | func NewUserService(config *config.Config, userModel model.UserModel, userAuthModel model.UserAuthModel, userTempModel model.UserTempModel, agentModel model.AgentModel) *UserService { | |||
|  | 	return &UserService{ | |||
|  | 		Config:        config, | |||
|  | 		userModel:     userModel, | |||
|  | 		userAuthModel: userAuthModel, | |||
|  | 		userTempModel: userTempModel, | |||
|  | 		agentModel:    agentModel, | |||
|  | 	} | |||
|  | } | |||
|  | 
 | |||
|  | // GenerateUUIDUserId 生成UUID用户ID | |||
|  | func (s *UserService) GenerateUUIDUserId(ctx context.Context) (string, error) { | |||
|  | 	id := uuid.NewString() | |||
|  | 	return id, nil | |||
|  | } | |||
|  | 
 | |||
|  | // RegisterUUIDUser 注册UUID用户,返回用户ID | |||
|  | func (s *UserService) RegisterUUIDUser(ctx context.Context) (int64, error) { | |||
|  | 	// 生成UUID | |||
|  | 	uuidStr, err := s.GenerateUUIDUserId(ctx) | |||
|  | 	if err != nil { | |||
|  | 		return 0, err | |||
|  | 	} | |||
|  | 
 | |||
|  | 	var userId int64 | |||
|  | 	err = s.userModel.Trans(ctx, func(ctx context.Context, session sqlx.Session) error { | |||
|  | 		// 创建用户记录 | |||
|  | 		user := &model.User{} | |||
|  | 		result, err := s.userModel.Insert(ctx, session, user) | |||
|  | 		if err != nil { | |||
|  | 			return err | |||
|  | 		} | |||
|  | 		userId, err = result.LastInsertId() | |||
|  | 		if err != nil { | |||
|  | 			return err | |||
|  | 		} | |||
|  | 
 | |||
|  | 		// 创建用户认证记录 | |||
|  | 		userAuth := &model.UserAuth{ | |||
|  | 			UserId:   userId, | |||
|  | 			AuthType: model.UserAuthTypeUUID, | |||
|  | 			AuthKey:  uuidStr, | |||
|  | 		} | |||
|  | 		_, err = s.userAuthModel.Insert(ctx, session, userAuth) | |||
|  | 		return err | |||
|  | 	}) | |||
|  | 	if err != nil { | |||
|  | 		return 0, err | |||
|  | 	} | |||
|  | 
 | |||
|  | 	return userId, nil | |||
|  | } | |||
|  | 
 | |||
|  | // generalUserToken 生成用户token | |||
|  | func (s *UserService) GeneralUserToken(ctx context.Context, userID int64, userType int64) (string, error) { | |||
|  | 	platform, err := ctxdata.GetPlatformFromCtx(ctx) | |||
|  | 	if err != nil { | |||
|  | 		return "", err | |||
|  | 	} | |||
|  | 
 | |||
|  | 	var isAgent int64 | |||
|  | 	var agentID int64 | |||
|  | 	if userType == model.UserTypeNormal { | |||
|  | 		agent, err := s.agentModel.FindOneByUserId(ctx, userID) | |||
|  | 		if err != nil && !errors.Is(err, model.ErrNotFound) { | |||
|  | 			return "", err | |||
|  | 		} | |||
|  | 		if agent != nil { | |||
|  | 			agentID = agent.Id | |||
|  | 			isAgent = model.AgentStatusYes | |||
|  | 		} | |||
|  | 	} else { | |||
|  | 		userTemp, err := s.userTempModel.FindOne(ctx, userID) | |||
|  | 		if err != nil { | |||
|  | 			return "", err | |||
|  | 		} | |||
|  | 		if userTemp != nil { | |||
|  | 			userID = userTemp.Id | |||
|  | 		} | |||
|  | 	} | |||
|  | 	token, generaErr := jwtx.GenerateJwtToken(jwtx.JwtClaims{ | |||
|  | 		UserId:   userID, | |||
|  | 		AgentId:  agentID, | |||
|  | 		Platform: platform, | |||
|  | 		UserType: userType, | |||
|  | 		IsAgent:  isAgent, | |||
|  | 	}, s.Config.JwtAuth.AccessSecret, s.Config.JwtAuth.AccessExpire) | |||
|  | 	if generaErr != nil { | |||
|  | 		return "", errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "更新token, 生成token失败 : %d", userID) | |||
|  | 	} | |||
|  | 	return token, nil | |||
|  | } | |||
|  | 
 | |||
|  | // RegisterUser 注册用户,返回用户ID | |||
|  | // 传入手机号,自动注册,如果ctx存在临时用户则临时用户转为正式用户 | |||
|  | func (s *UserService) RegisterUser(ctx context.Context, mobile string) (int64, error) { | |||
|  | 	claims, err := ctxdata.GetClaimsFromCtx(ctx) | |||
|  | 	if err != nil && !errors.Is(err, ctxdata.ErrNoInCtx) { | |||
|  | 		return 0, err | |||
|  | 	} | |||
|  | 	user, err := s.userModel.FindOneByMobile(ctx, sql.NullString{String: mobile, Valid: true}) | |||
|  | 	if err != nil && !errors.Is(err, model.ErrNotFound) { | |||
|  | 		return 0, err | |||
|  | 	} | |||
|  | 	if user != nil { | |||
|  | 		return 0, errors.New("用户已注册") | |||
|  | 	} | |||
|  | 	// 普通注册 | |||
|  | 	if claims == nil { | |||
|  | 		var userId int64 | |||
|  | 		err = s.userModel.Trans(ctx, func(ctx context.Context, session sqlx.Session) error { | |||
|  | 			user := &model.User{ | |||
|  | 				Mobile: sql.NullString{String: mobile, Valid: true}, | |||
|  | 			} | |||
|  | 			result, err := s.userModel.Insert(ctx, session, user) | |||
|  | 			if err != nil { | |||
|  | 				return err | |||
|  | 			} | |||
|  | 			userId, err = result.LastInsertId() | |||
|  | 			if err != nil { | |||
|  | 				return err | |||
|  | 			} | |||
|  | 			s.userAuthModel.Insert(ctx, session, &model.UserAuth{ | |||
|  | 				UserId:   userId, | |||
|  | 				AuthType: model.UserAuthTypeMobile, | |||
|  | 				AuthKey:  mobile, | |||
|  | 			}) | |||
|  | 			return nil | |||
|  | 		}) | |||
|  | 		if err != nil { | |||
|  | 			return 0, err | |||
|  | 		} | |||
|  | 		return userId, nil | |||
|  | 	} | |||
|  | 
 | |||
|  | 	// 双重判断是否已经注册 | |||
|  | 	if claims.UserType == model.UserTypeNormal { | |||
|  | 		return 0, errors.New("用户已注册") | |||
|  | 	} | |||
|  | 	var userId int64 | |||
|  | 	// 临时转正式注册 | |||
|  | 	err = s.userModel.Trans(ctx, func(ctx context.Context, session sqlx.Session) error { | |||
|  | 		user := &model.User{ | |||
|  | 			Mobile: sql.NullString{String: mobile, Valid: true}, | |||
|  | 		} | |||
|  | 		result, err := s.userModel.Insert(ctx, session, user) | |||
|  | 		if err != nil { | |||
|  | 			return err | |||
|  | 		} | |||
|  | 		userId, err = result.LastInsertId() | |||
|  | 		if err != nil { | |||
|  | 			return err | |||
|  | 		} | |||
|  | 		_, err = s.userAuthModel.Insert(ctx, session, &model.UserAuth{ | |||
|  | 			UserId:   userId, | |||
|  | 			AuthType: model.UserAuthTypeMobile, | |||
|  | 			AuthKey:  mobile, | |||
|  | 		}) | |||
|  | 		if err != nil { | |||
|  | 			return err | |||
|  | 		} | |||
|  | 		err = s.TempUserBindUser(ctx, session, userId) | |||
|  | 		if err != nil { | |||
|  | 			return err | |||
|  | 		} | |||
|  | 		return nil | |||
|  | 	}) | |||
|  | 	if err != nil { | |||
|  | 		return 0, err | |||
|  | 	} | |||
|  | 	return userId, nil | |||
|  | } | |||
|  | 
 | |||
|  | // TempUserBindUser 临时用户绑定用户 | |||
|  | func (s *UserService) TempUserBindUser(ctx context.Context, session sqlx.Session, normalUserID int64) error { | |||
|  | 	claims, err := ctxdata.GetClaimsFromCtx(ctx) | |||
|  | 	if err != nil && !errors.Is(err, ctxdata.ErrNoInCtx) { | |||
|  | 		return err | |||
|  | 	} | |||
|  | 
 | |||
|  | 	if claims == nil || claims.UserType != model.UserTypeTemp { | |||
|  | 		return errors.New("无临时用户") | |||
|  | 	} | |||
|  | 
 | |||
|  | 	// 使用事务上下文查询临时用户 | |||
|  | 	userTemp, err := s.userTempModel.FindOne(ctx, claims.UserId) | |||
|  | 	if err != nil { | |||
|  | 		return err | |||
|  | 	} | |||
|  | 
 | |||
|  | 	// 检查是否已经注册过 | |||
|  | 	userAuth, err := s.userAuthModel.FindOneByAuthTypeAuthKey(ctx, userTemp.AuthType, userTemp.AuthKey) | |||
|  | 	if err != nil && !errors.Is(err, model.ErrNotFound) { | |||
|  | 		return err | |||
|  | 	} | |||
|  | 	if userAuth != nil { | |||
|  | 		return errors.New("临时用户已注册") | |||
|  | 	} | |||
|  | 
 | |||
|  | 	if session == nil { | |||
|  | 		err := s.userAuthModel.Trans(ctx, func(ctx context.Context, session sqlx.Session) error { | |||
|  | 			_, err = s.userAuthModel.Insert(ctx, session, &model.UserAuth{ | |||
|  | 				UserId:   normalUserID, | |||
|  | 				AuthType: userTemp.AuthType, | |||
|  | 				AuthKey:  userTemp.AuthKey, | |||
|  | 			}) | |||
|  | 			if err != nil { | |||
|  | 				return err | |||
|  | 			} | |||
|  | 
 | |||
|  | 			// 重新获取最新的userTemp数据,确保版本号是最新的 | |||
|  | 			latestUserTemp, err := s.userTempModel.FindOne(ctx, claims.UserId) | |||
|  | 			if err != nil { | |||
|  | 				return err | |||
|  | 			} | |||
|  | 			err = s.userTempModel.DeleteSoft(ctx, session, latestUserTemp) | |||
|  | 			if err != nil { | |||
|  | 				return err | |||
|  | 			} | |||
|  | 			return nil | |||
|  | 		}) | |||
|  | 		if err != nil { | |||
|  | 			return err | |||
|  | 		} | |||
|  | 		return nil | |||
|  | 	} else { | |||
|  | 		_, err = s.userAuthModel.Insert(ctx, session, &model.UserAuth{ | |||
|  | 			UserId:   normalUserID, | |||
|  | 			AuthType: userTemp.AuthType, | |||
|  | 			AuthKey:  userTemp.AuthKey, | |||
|  | 		}) | |||
|  | 		if err != nil { | |||
|  | 			return err | |||
|  | 		} | |||
|  | 
 | |||
|  | 		// 重新获取最新的userTemp数据,确保版本号是最新的 | |||
|  | 		latestUserTemp, err := s.userTempModel.FindOne(ctx, claims.UserId) | |||
|  | 		if err != nil { | |||
|  | 			return err | |||
|  | 		} | |||
|  | 		err = s.userTempModel.DeleteSoft(ctx, session, latestUserTemp) | |||
|  | 		if err != nil { | |||
|  | 			return err | |||
|  | 		} | |||
|  | 		return nil | |||
|  | 	} | |||
|  | } | |||
|  | 
 | |||
|  | // _bak_RegisterUUIDUser 注册UUID用户,返回用户ID | |||
|  | func (s *UserService) _bak_RegisterUUIDUser(ctx context.Context) error { | |||
|  | 	// 生成UUID | |||
|  | 	uuidStr, err := s.GenerateUUIDUserId(ctx) | |||
|  | 	if err != nil { | |||
|  | 		return err | |||
|  | 	} | |||
|  | 
 | |||
|  | 	err = s.userTempModel.Trans(ctx, func(ctx context.Context, session sqlx.Session) error { | |||
|  | 		// 创建用户临时记录 | |||
|  | 		userTemp := &model.UserTemp{ | |||
|  | 			AuthType: model.UserAuthTypeUUID, | |||
|  | 			AuthKey:  uuidStr, | |||
|  | 		} | |||
|  | 		_, err := s.userTempModel.Insert(ctx, session, userTemp) | |||
|  | 		return err | |||
|  | 	}) | |||
|  | 	if err != nil { | |||
|  | 		return err | |||
|  | 	} | |||
|  | 
 | |||
|  | 	return nil | |||
|  | } |