mini_user_login_logic.go 5.5 KB
package user

import (
	"context"
	"fmt"
	"github.com/silenceper/wechat/v2"
	"github.com/silenceper/wechat/v2/cache"
	miniConfig "github.com/silenceper/wechat/v2/miniprogram/config"
	"gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/interanl/pkg/domain"
	"gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/interanl/pkg/gateway/smslib"
	"gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/pkg/tool"
	"gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/pkg/xerr"

	"gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/api/internal/svc"
	"gitlab.fjmaimaimai.com/allied-creation/sumifcc-discuss/cmd/discuss/api/internal/types"

	"github.com/zeromicro/go-zero/core/logx"
)

type MiniUserLoginLogic struct {
	logx.Logger
	ctx    context.Context
	svcCtx *svc.ServiceContext
}

func NewMiniUserLoginLogic(ctx context.Context, svcCtx *svc.ServiceContext) *MiniUserLoginLogic {
	return &MiniUserLoginLogic{
		Logger: logx.WithContext(ctx),
		ctx:    ctx,
		svcCtx: svcCtx,
	}
}

func (l *MiniUserLoginLogic) MiniUserLogin(req *types.MiniUserLoginRequest) (resp *types.MiniUserLoginResponse, err error) {
	var (
		loginInfo    *domain.LoginInfo
		token        string
		loginCreator domain.LoginCreator = WxClientLogin{svcCtx: l.svcCtx, ctx: l.ctx}
	)
	switch req.LoginType {
	case domain.LoginTypeWechatLogin:
		loginInfo, err = loginCreator.WechatLogin(domain.WechatLoginRequest{Code: req.WechatAuthCode, EncryptedData: req.WechatEncryptedData, IV: req.WechatIV})
	case domain.LoginTypeWechatPhoneLogin:
		loginInfo, err = loginCreator.WechatPhoneLogin(domain.WechatLoginRequest{Code: req.WechatAuthCode, EncryptedData: req.WechatEncryptedData, IV: req.WechatIV})
	case domain.LoginTypePhoneSmsCodeLogin:
		loginInfo, err = loginCreator.PhoneSmsCodeLogin(req.Phone, req.SmsCode)
	case domain.LoginTypePhonePasswordLogin:
		loginInfo, err = loginCreator.PhonePasswordLogin(req.Phone, req.Password)
	}
	if err != nil {
		return
	}

	var users []*domain.User
	conn := l.svcCtx.DefaultDBConn()
	_, users, err = l.svcCtx.UserRepository.Find(l.ctx, conn, domain.NewQueryOptions().
		MustWithKV("phone", loginInfo.Phone).
		MustWithKV("auditStatus", []int{domain.UserAuditStatusWait, domain.UserAuditStatusPassed}).
		WithFindOnly())
	if err != nil {
		return nil, err
	}
	if len(users) > 0 {
		for _, user := range users {
			if user.Enable == domain.UserEnable && user.AuditStatus == domain.UserAuditStatusPassed {
				loginInfo.User = user
				break
			}
		}
		if loginInfo.User == nil {
			loginInfo.User = users[0]
		}
	}
	token, err = generateToken(l.svcCtx, loginInfo.User)
	if err != nil {
		return nil, xerr.NewErrMsgErr("登录失败", err)
	}
	resp = &types.MiniUserLoginResponse{
		Token:   token,
		Phone:   loginInfo.Phone,
		Success: true,
	}
	if loginInfo.User == nil {
		resp.Token = ""
		resp.Success = false
	}
	return
}

func generateToken(svcCtx *svc.ServiceContext, user *domain.User) (token string, err error) {
	var userJwtToken = tool.UserToken{}
	if user != nil {
		userJwtToken.UserId = user.Id
		userJwtToken.CompanyId = user.CompanyId
		userJwtToken.ClientType = "mini"
	}
	token, err = userJwtToken.GenerateToken(svcCtx.Config.MiniAuth.AccessSecret, svcCtx.Config.MiniAuth.AccessExpire)
	if err != nil {
		return "", xerr.NewErrMsgErr("登录失败", err)
	}
	return
}

type WxClientLogin struct {
	svcCtx *svc.ServiceContext
	ctx    context.Context
}

func (c WxClientLogin) WechatPhoneLogin(r domain.WechatLoginRequest) (*domain.LoginInfo, error) {
	code := r.Code
	response := &domain.LoginInfo{
		Phone: "",
	}
	miniprogram := wechat.NewWechat().GetMiniProgram(&miniConfig.Config{
		AppID:     c.svcCtx.Config.Wechat.AppID,
		AppSecret: c.svcCtx.Config.Wechat.AppSecret,
		Cache:     cache.NewMemory(),
	})
	authResult, err := miniprogram.GetAuth().GetPhoneNumber(code)
	if err != nil || authResult.ErrCode != 0 || authResult.PhoneInfo.PhoneNumber == "" {
		return response, xerr.NewCodeErrMsg(xerr.ErrWxMiniAuthFailError, nil, fmt.Sprintf("发起授权请求失败1 err : %v , code : %s  , authResult : %+v", err, code, authResult))
	}
	var (
		phone = authResult.PhoneInfo.PhoneNumber
	)
	response.Phone = phone
	return response, nil
}

func (c WxClientLogin) WechatLogin(r domain.WechatLoginRequest) (*domain.LoginInfo, error) {
	return nil, nil
}

func (c WxClientLogin) GetOpenId(r domain.WechatLoginRequest) (string, error) {
	miniprogram := wechat.NewWechat().GetMiniProgram(&miniConfig.Config{
		AppID:     c.svcCtx.Config.Wechat.AppID,
		AppSecret: c.svcCtx.Config.Wechat.AppSecret,
		Cache:     cache.NewMemory(),
	})
	result, err := miniprogram.GetAuth().Code2Session(r.Code)
	if err != nil {
		return "", xerr.NewErrMsgErr("发起授权请求失败", err)
	}
	plainData, err := miniprogram.GetEncryptor().Decrypt(result.SessionKey, r.EncryptedData, r.IV)
	if err != nil {
		return "", xerr.NewErrMsgErr("获取授权用户失败", err)
	}
	return plainData.OpenID, nil
}

func (c WxClientLogin) PhonePasswordLogin(phone string, password string) (*domain.LoginInfo, error) {
	panic("implement me")
}

func (c WxClientLogin) PhoneSmsCodeLogin(phone string, code string) (*domain.LoginInfo, error) {
	var (
		err              error
		skipCheckSmsCode bool = false
	)
	if c.svcCtx.Config.DebugSmsCode != "" && c.svcCtx.Config.DebugSmsCode == code {
		skipCheckSmsCode = true
	}
	if _, err = c.svcCtx.SmsService.CheckSmsCode(c.ctx, smslib.RequestCheckSmsCode{Phone: phone, Code: code}); err != nil && !skipCheckSmsCode {
		return nil, xerr.NewErrMsgErr(err.Error(), err)
	}
	response := &domain.LoginInfo{
		Phone: phone,
	}
	return response, nil
}