2025-05-11 19:39:56 +08:00
|
|
|
|
package service
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"context"
|
2025-06-17 23:46:37 +08:00
|
|
|
|
"database/sql"
|
|
|
|
|
"qnc-server/app/main/api/internal/config"
|
2025-06-09 12:34:52 +08:00
|
|
|
|
"qnc-server/app/main/model"
|
2025-06-17 23:46:37 +08:00
|
|
|
|
"qnc-server/common/ctxdata"
|
|
|
|
|
jwtx "qnc-server/common/jwt"
|
|
|
|
|
"qnc-server/common/xerr"
|
2025-05-11 19:39:56 +08:00
|
|
|
|
|
|
|
|
|
"github.com/google/uuid"
|
2025-06-17 23:46:37 +08:00
|
|
|
|
"github.com/pkg/errors"
|
2025-05-11 19:39:56 +08:00
|
|
|
|
"github.com/zeromicro/go-zero/core/stores/sqlx"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
type UserService struct {
|
2025-06-17 23:46:37 +08:00
|
|
|
|
Config *config.Config
|
2025-05-11 19:39:56 +08:00
|
|
|
|
userModel model.UserModel
|
|
|
|
|
userAuthModel model.UserAuthModel
|
2025-06-17 23:46:37 +08:00
|
|
|
|
userTempModel model.UserTempModel
|
|
|
|
|
agentModel model.AgentModel
|
2025-05-11 19:39:56 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// NewUserService 创建UserService实例
|
2025-06-17 23:46:37 +08:00
|
|
|
|
func NewUserService(config *config.Config, userModel model.UserModel, userAuthModel model.UserAuthModel, userTempModel model.UserTempModel, agentModel model.AgentModel) *UserService {
|
2025-05-11 19:39:56 +08:00
|
|
|
|
return &UserService{
|
2025-06-17 23:46:37 +08:00
|
|
|
|
Config: config,
|
2025-05-11 19:39:56 +08:00
|
|
|
|
userModel: userModel,
|
|
|
|
|
userAuthModel: userAuthModel,
|
2025-06-17 23:46:37 +08:00
|
|
|
|
userTempModel: userTempModel,
|
|
|
|
|
agentModel: agentModel,
|
2025-05-11 19:39:56 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 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
|
|
|
|
|
}
|
2025-06-17 23:46:37 +08:00
|
|
|
|
|
|
|
|
|
// generalUserToken 生成用户token
|
2025-06-19 14:34:32 +08:00
|
|
|
|
func (s *UserService) GeneralUserToken(ctx context.Context, userID int64, userType int64) (string, error) {
|
2025-06-17 23:46:37 +08:00
|
|
|
|
platform, err := ctxdata.GetPlatformFromCtx(ctx)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return "", err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var isAgent int64
|
|
|
|
|
var agentID int64
|
2025-06-19 14:34:32 +08:00
|
|
|
|
if userType == model.UserTypeNormal {
|
2025-06-17 23:46:37 +08:00
|
|
|
|
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("无临时用户")
|
|
|
|
|
}
|
|
|
|
|
|
2025-06-25 21:46:11 +08:00
|
|
|
|
// 使用事务上下文查询临时用户
|
2025-06-17 23:46:37 +08:00
|
|
|
|
userTemp, err := s.userTempModel.FindOne(ctx, claims.UserId)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
|
2025-06-25 21:46:11 +08:00
|
|
|
|
// 检查是否已经注册过
|
2025-06-17 23:46:37 +08:00
|
|
|
|
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
|
|
|
|
|
}
|
2025-06-25 21:46:11 +08:00
|
|
|
|
|
|
|
|
|
// 重新获取最新的userTemp数据,确保版本号是最新的
|
|
|
|
|
latestUserTemp, err := s.userTempModel.FindOne(ctx, claims.UserId)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
err = s.userTempModel.DeleteSoft(ctx, session, latestUserTemp)
|
2025-06-17 23:46:37 +08:00
|
|
|
|
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
|
|
|
|
|
}
|
2025-06-25 21:46:11 +08:00
|
|
|
|
|
|
|
|
|
// 重新获取最新的userTemp数据,确保版本号是最新的
|
|
|
|
|
latestUserTemp, err := s.userTempModel.FindOne(ctx, claims.UserId)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
err = s.userTempModel.DeleteSoft(ctx, session, latestUserTemp)
|
2025-06-17 23:46:37 +08:00
|
|
|
|
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
|
|
|
|
|
}
|