user/biz/service/user_service.go
timerzz 5c386c8c0c chore: 将模块路径从gitlab.com迁移到gitee.com
更新了所有文件中的模块导入路径,将`gitlab.com/kedaya_mp/user`替换为`gitee.com/kedaya_mp/user`,以将项目从GitLab迁移到Gitee平台。
2025-04-23 16:03:09 +08:00

156 lines
3.7 KiB
Go

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
}