package service import ( "context" "errors" "gitee.com/kedaya_mp/user/biz/dal/db" "gitee.com/kedaya_mp/user/biz/model/common" "gitee.com/kedaya_mp/user/pkg/captcha" "gitee.com/kedaya_mp/user/pkg/crypto" "github.com/ArtisanCloud/PowerWeChat/v3/src/miniProgram" "gorm.io/gorm" ) var ( ErrUserNotFound = errors.New("用户不存在") ErrInvalidPassword = errors.New("密码错误") ErrGetWXUserInfo = errors.New("获取微信用户信息失败") ErrCreateUserFailed = errors.New("创建用户失败") ) type UserService struct { store db.UserStore miniProgramApp *miniProgram.MiniProgram captchaService captcha.Service } func NewUserService(_db *gorm.DB, miniProgramApp *miniProgram.MiniProgram, captchaService captcha.Service) *UserService { return &UserService{ store: db.NewUserStore(_db), miniProgramApp: miniProgramApp, captchaService: captchaService, } } func (s *UserService) Init() error { if err := s.store.AutoMigrate(); err != nil { return err } return nil } func (s *UserService) LoginByPhone(phone, password string) (*common.User, error) { user, err := s.store.Find(&db.FindUserQuery{Phone: phone}) if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) { return nil, err } if user == nil { hashedPassword := crypto.HashPassword(password) newUser := &common.User{ Phone: phone, Password: hashedPassword, } user, err = s.store.Create(newUser) if err != nil { return nil, ErrCreateUserFailed } return user, nil } if !crypto.VerifyPassword(password, user.Password) { return nil, ErrInvalidPassword } return user, nil } func (s *UserService) LoginByWechat(ctx context.Context, wxCode, phone string) (*common.User, error) { authResult, err := s.miniProgramApp.Auth.Session(ctx, wxCode) if err != nil { return nil, ErrGetWXUserInfo } user, err := s.store.Find(&db.FindUserQuery{WxUnionID: authResult.UnionID}) if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) { return nil, err } if user != nil { if user.Phone != phone { return nil, errors.New("手机号与已绑定的不符") } user.WxSession = authResult.SessionKey if err = s.store.Update(user, "wx_session"); err != nil { return nil, err } return user, nil } newUser := &common.User{ Phone: phone, WxUnionID: authResult.UnionID, } user, err = s.store.Create(newUser) if err != nil { return nil, ErrCreateUserFailed } return user, nil } func (s *UserService) LoginByPhoneAndCode(ctx context.Context, phone, captchaCode string) (*common.User, error) { if err := s.captchaService.VerifyCode(ctx, phone, captchaCode); err != nil { return nil, err } user, err := s.store.Find(&db.FindUserQuery{Phone: phone}) if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) { return nil, err } if user == nil { newUser := &common.User{ Phone: phone, } user, err = s.store.Create(newUser) if err != nil { return nil, ErrCreateUserFailed } } return user, nil } func (s *UserService) Login(ctx context.Context, phone, password, wxCode, captcha string) (*common.User, error) { if phone == "" { return nil, errors.New("手机号不能为空") } if wxCode != "" { return s.LoginByWechat(ctx, wxCode, phone) } if captcha != "" { return s.LoginByPhoneAndCode(ctx, phone, captcha) } if password == "" { return nil, errors.New("密码不能为空") } return s.LoginByPhone(phone, password) } func (s *UserService) GetUserByPhone(phone string) (*common.User, error) { user, err := s.store.Find(&db.FindUserQuery{Phone: phone}, "created_at", "nick_name", "phone", "avatar", "gender") if err != nil { return nil, err } if user == nil { return nil, ErrUserNotFound } return user, nil }