package logic import ( "context" "lone-services/pkg/modelbase" "lone-services/pkg/utils" "lone-services/pkg/validate" analysispb "lone-services/rpc/analysis/pb" user "lone-services/rpc/user/pb" userconfig "lone-services/services/user/internal/config" "lone-services/services/user/internal/dao" "lone-services/services/user/internal/model" "lone-services/services/user/internal/svc" "lone-services/services/user/validator" "github.com/zeromicro/go-zero/core/logx" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" ) const clientCodeUserSkin = "user_skin" type BindMobileLogic struct { ctx context.Context svcCtx *svc.ServiceContext logx.Logger } func NewBindMobileLogic(ctx context.Context, svcCtx *svc.ServiceContext) *BindMobileLogic { return &BindMobileLogic{ ctx: ctx, svcCtx: svcCtx, Logger: logx.WithContext(ctx), } } func (l *BindMobileLogic) BindMobile(in *user.BindMobileReq) (*user.Response, error) { loginUser := utils.GetUserFromCtx(l.ctx) if loginUser.ID < utils.NumberOne { return failResponse(utils.ErrorNoLoginInfo), nil } var req validator.BindMobileValidator if msg := validate.ValidateFromProto(in, &req); msg != utils.StringEmpty { return outResponse(utils.ErrorParams, msg), nil } if loginUser.ClientCode == utils.StringEmpty { return outResponse(utils.ErrorParams, "端编码不能为空"), nil } client, err := loadEnabledClient(loginUser.ClientCode) if err != nil { l.Errorf("bind mobile load client: %v", err) return failResponse(utils.Fail), nil } wxCfg, cfgErr := userconfig.LoadWechatConfig(loginUser.ClientCode) if cfgErr != nil { l.Errorf("bind mobile wechat config: %v", cfgErr) return outResponse(utils.Fail, "微信配置缺失"), nil } token, tokenErr := wxCfg.NewAuthClient().AccessToken(l.ctx) if tokenErr != nil { l.Errorf("bind mobile access token: %v", tokenErr) return failResponse(utils.Fail), nil } phone, phoneErr := wxCfg.NewAuthClient().GetPhoneNumber(token.AccessToken, req.Code) if phoneErr != nil { l.Errorf("bind mobile get phone: %v", phoneErr) return failResponse(utils.Fail), nil } mobile := phone.PhoneNumber if mobile == utils.StringEmpty { mobile = phone.PurePhoneNumber } if mobile == utils.StringEmpty { return failResponse(utils.Fail), nil } encryptMobile, encErr := utils.EncryptPhone(mobile) if encErr != nil { l.Errorf("bind mobile encrypt: %v", encErr) return failResponse(utils.ErrorEncryptAesError), nil } finalUserId := loginUser.ID occupied, occErr := l.findUserByMobile(encryptMobile) if occErr != nil { l.Errorf("bind mobile find by mobile: %v", occErr) return failResponse(utils.Fail), nil } if occupied != nil && occupied.Id > utils.NumberZero && occupied.Id != loginUser.ID { if err := mergeUserInto(l.ctx, l.svcCtx, loginUser.ID, occupied.Id); err != nil { l.Errorf("bind mobile merge: %v", err) return failResponse(utils.Fail), nil } finalUserId = occupied.Id row, userErr := loadEnabledUser(finalUserId) if userErr != nil { l.Errorf("bind mobile load merged user: %v", userErr) return failResponse(utils.Fail), nil } session := toSession(*row, mobile, client) if fillErr := fillSessionBizIds(l.ctx, &session, finalUserId, client); fillErr != nil { l.Errorf("bind mobile fill session: %v", fillErr) return failResponse(utils.Fail), nil } if remapErr := remaponUserLoginAfterMerge(l.svcCtx.JWT, loginUser.ID, finalUserId, session); remapErr != nil { l.Errorf("bind mobile remapon login: %v", remapErr) return failResponse(utils.Fail), nil } } else { _, updateErr := NewInternalUpdateMobileLogic(l.ctx, l.svcCtx).InternalUpdateMobile(&user.InternalUpdateMobileReq{ UserId: loginUser.ID, Mobile: mobile, }) if updateErr != nil { l.Errorf("bind mobile update: %v", updateErr) if st, ok := status.FromError(updateErr); ok { switch st.Code() { case codes.InvalidArgument: return outResponse(utils.ErrorParams, st.Message()), nil case codes.AlreadyExists: return failResponse(utils.ErrorDataIsExist), nil case codes.NotFound: return failResponse(utils.ErrorNotFund), nil } } return failResponse(utils.Fail), nil } } if loginUser.ClientCode == clientCodeUserSkin { if err := l.markAnalysisRegistered(finalUserId, loginUser.ClientCode, utils.NumberZero); err != nil { l.Errorf("bind mobile set registered: %v", err) return failResponse(utils.Fail), nil } } return okResponse(nil), nil } func (l *BindMobileLogic) findUserByMobile(encryptMobile string) (*dao.UserRow, error) { var occupied dao.UserRow userModel := model.UserModel{}.Init() err := userModel.GetOne(modelbase.Params{ Eq: map[string]string{"mobile": encryptMobile}, }, &occupied) if err != nil { return nil, err } if occupied.Id < utils.NumberOne { return nil, nil } return &occupied, nil } func (l *BindMobileLogic) markAnalysisRegistered(userId int64, clientCode string, bizId int64) error { if bizId < utils.NumberOne { if err := ensureClientBizUser(l.ctx, l.svcCtx, userId, clientCode); err != nil { return err } loaded, err := loadUserClientBizId(userId, clientCode) if err != nil { return err } bizId = loaded } if bizId < utils.NumberOne { return status.Error(codes.FailedPrecondition, "业务用户不存在") } cli, err := svc.GetRpcClient(l.svcCtx.AnalysisSvcName) if err != nil { return err } _, err = analysispb.NewAnalysisClient(cli.Conn()).InternalSetRegistered(l.ctx, &analysispb.InternalSetRegisteredReq{ Id: bizId, }) return err }