156 lines
3.7 KiB
Go
156 lines
3.7 KiB
Go
package service
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
|
|
"gitea.timerzz.com/onecat/user/biz/dal/db"
|
|
"gitea.timerzz.com/onecat/user/biz/model/common"
|
|
"gitea.timerzz.com/onecat/user/pkg/captcha"
|
|
"gitea.timerzz.com/onecat/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
|
|
}
|