user/biz/service/user_service.go
timerzz b4448efb2a
Some checks failed
Build image / build (push) Failing after 26s
添加工作流
2025-05-21 12:29:01 +08:00

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
}