You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
348 lines
11 KiB
348 lines
11 KiB
package user
|
|
|
|
import (
|
|
"context"
|
|
"yunyan/comm"
|
|
"yunyan/lego/sys/mysql"
|
|
"yunyan/lego/utils/container/id"
|
|
"yunyan/pb"
|
|
apple_auth "yunyan/sys/auth/apple"
|
|
facebook_auth "yunyan/sys/auth/facebook"
|
|
google_auth "yunyan/sys/auth/google"
|
|
wechat_auth "yunyan/sys/auth/wechat"
|
|
"yunyan/sys/ipinfo"
|
|
|
|
"fmt"
|
|
"time"
|
|
|
|
"firebase.google.com/go/v4/auth"
|
|
"github.com/golang-jwt/jwt/v4"
|
|
"golang.org/x/exp/rand"
|
|
)
|
|
|
|
// @Summary 登入接口
|
|
// @Description 根据登录类型实现登录操作
|
|
// @Tags User
|
|
// @Accept json
|
|
// @Produce json
|
|
// @Param user body pb.UserSginReq true "登录请求"
|
|
// @Success 200 {object} comm.HttpResult{data=pb.UserSginResp} "成功返回用户信息"
|
|
// @Router /api/home/user_sgin [post]
|
|
func (this *apiComp) Sgin(session comm.IUserSession, req *pb.UserSginReq) (resp *pb.UserSginResp, errdata *pb.ErrorData) {
|
|
var (
|
|
istestaccount bool
|
|
code string
|
|
apple_uuid string
|
|
wxinfo *wechat_auth.WeChatUserInfoResponse
|
|
googleinfo *auth.Token
|
|
facebookinfo *facebook_auth.FacebookTokenInfo
|
|
// firebaseinfo *auth.Token
|
|
ipdata *ipinfo.IPData
|
|
user *pb.DBUser
|
|
divices []*pb.DBUserDivice
|
|
tokenString string
|
|
err error
|
|
)
|
|
// this.module.Infof("登陆日志 options:%v req:%v", this.module.options, req)
|
|
switch req.Stype {
|
|
case pb.SginTyoe_Mail: //邮箱
|
|
if this.module.options.OpenTestAccount {
|
|
for _, account := range this.module.options.TestAccounts {
|
|
// this.module.Infof("登录日志 测试账号 account:%s req.Mail %s TestAccountPassword:%s Vcode:%s", account, req.Mail, this.module.options.TestAccountPassword, req.Vcode)
|
|
if account == req.Mail && this.module.options.TestAccountPassword == req.Vcode {
|
|
istestaccount = true
|
|
// this.module.Infof("登录日志 测试账号登录 account:%s", account)
|
|
break
|
|
}
|
|
}
|
|
}
|
|
if !istestaccount { //并非测试账号
|
|
if code, err = this.module.model.getCode(req.Mail); err != nil {
|
|
// this.module.Infof("登录日志 获取验证码失败 account:%s err:%v", req.Mail, err)
|
|
errdata = &pb.ErrorData{
|
|
Code: pb.ErrorCode_DBError,
|
|
Message: err.Error(),
|
|
}
|
|
return
|
|
}
|
|
if code != req.Vcode {
|
|
errdata = &pb.ErrorData{
|
|
Code: pb.ErrorCode_ReqParameterError,
|
|
Message: "code is error",
|
|
}
|
|
return
|
|
}
|
|
}
|
|
if user, err = this.module.model.findformail(req.Mail); err != nil && err != mysql.ErrNoDocuments {
|
|
errdata = &pb.ErrorData{
|
|
Code: pb.ErrorCode_DBError,
|
|
Message: err.Error(),
|
|
}
|
|
return
|
|
}
|
|
case pb.SginTyoe_Phone: //手机
|
|
if this.module.options.OpenTestAccount {
|
|
for _, account := range this.module.options.TestAccounts {
|
|
if account == req.Phone && this.module.options.TestAccountPassword == req.Vcode {
|
|
istestaccount = true
|
|
break
|
|
}
|
|
}
|
|
}
|
|
if !istestaccount { //并非测试账号
|
|
if code, err = this.module.model.getCode(req.Phone); err != nil {
|
|
errdata = &pb.ErrorData{
|
|
Code: pb.ErrorCode_DBError,
|
|
Message: err.Error(),
|
|
}
|
|
return
|
|
}
|
|
if code != req.Vcode {
|
|
errdata = &pb.ErrorData{
|
|
Code: pb.ErrorCode_ReqParameterError,
|
|
Message: "code is error",
|
|
}
|
|
return
|
|
}
|
|
}
|
|
|
|
if user, err = this.module.model.findforphone(req.Phone); err != nil && err != mysql.ErrNoDocuments {
|
|
errdata = &pb.ErrorData{
|
|
Code: pb.ErrorCode_DBError,
|
|
Message: err.Error(),
|
|
}
|
|
return
|
|
}
|
|
case pb.SginTyoe_WXChat: //微信
|
|
if wxinfo, err = wechat_auth.Auth(context.Background(), req.Ttoken); err != nil {
|
|
errdata = &pb.ErrorData{
|
|
Code: pb.ErrorCode_ExceptionAccountVerification,
|
|
Message: err.Error(),
|
|
}
|
|
return
|
|
}
|
|
if user, err = this.module.model.findforwx(wxinfo.OpenID); err != nil && err != mysql.ErrNoDocuments {
|
|
errdata = &pb.ErrorData{
|
|
Code: pb.ErrorCode_DBError,
|
|
Message: err.Error(),
|
|
}
|
|
return
|
|
}
|
|
case pb.SginTyoe_Google: //微信
|
|
if googleinfo, err = google_auth.Auth(context.Background(), req.Ttoken); err != nil {
|
|
errdata = &pb.ErrorData{
|
|
Code: pb.ErrorCode_ExceptionAccountVerification,
|
|
Message: err.Error(),
|
|
}
|
|
return
|
|
}
|
|
if user, err = this.module.model.findforgoogle(googleinfo.UID); err != nil && err != mysql.ErrNoDocuments {
|
|
errdata = &pb.ErrorData{
|
|
Code: pb.ErrorCode_DBError,
|
|
Message: err.Error(),
|
|
}
|
|
return
|
|
}
|
|
case pb.SginTyoe_FaceBook: //微信
|
|
if facebookinfo, err = facebook_auth.Auth(context.Background(), req.Ttoken); err != nil {
|
|
errdata = &pb.ErrorData{
|
|
Code: pb.ErrorCode_ExceptionAccountVerification,
|
|
Message: err.Error(),
|
|
}
|
|
return
|
|
}
|
|
if user, err = this.module.model.findforfacebook(facebookinfo.UserID); err != nil && err != mysql.ErrNoDocuments {
|
|
errdata = &pb.ErrorData{
|
|
Code: pb.ErrorCode_DBError,
|
|
Message: err.Error(),
|
|
}
|
|
return
|
|
}
|
|
case pb.SginTyoe_Apple: //微信
|
|
if apple_uuid, err = apple_auth.Auth(context.Background(), req.Ttoken); err != nil {
|
|
errdata = &pb.ErrorData{
|
|
Code: pb.ErrorCode_ExceptionAccountVerification,
|
|
Message: err.Error(),
|
|
}
|
|
return
|
|
}
|
|
if user, err = this.module.model.findforapple(apple_uuid); err != nil && err != mysql.ErrNoDocuments {
|
|
errdata = &pb.ErrorData{
|
|
Code: pb.ErrorCode_DBError,
|
|
Message: err.Error(),
|
|
}
|
|
return
|
|
}
|
|
case pb.SginTyoe_Tourists: //游客登录
|
|
// 按设备硬件 id 找回同一个游客账号。
|
|
//
|
|
// 这段原先是注释掉的,恒定走下面的"新建账号"分支,后果有两个:
|
|
// 游客每次登录都是新账号,实名认证记录留不住(客户端要求"实名过就能用功能"
|
|
// 就永远不成立);而且新账号分支紧接着就发新用户开户礼,等于可以无限白嫖。
|
|
if req.Phonemac == "" {
|
|
errdata = &pb.ErrorData{
|
|
Code: pb.ErrorCode_ReqParameterError,
|
|
Message: "游客登录需要设备标识",
|
|
}
|
|
return
|
|
}
|
|
if user, err = this.module.model.findtouristformac(req.Phonemac); err != nil && err != mysql.ErrNoDocuments {
|
|
errdata = &pb.ErrorData{
|
|
Code: pb.ErrorCode_DBError,
|
|
Message: err.Error(),
|
|
}
|
|
return
|
|
}
|
|
default:
|
|
errdata = &pb.ErrorData{
|
|
Code: pb.ErrorCode_ReqParameterError,
|
|
Message: "stype is no support",
|
|
}
|
|
return
|
|
}
|
|
|
|
if err == mysql.ErrNoDocuments {
|
|
user = &pb.DBUser{
|
|
Uid: id.NewSnowflakeId(int64(this.options.UserGroup)),
|
|
Phone: req.Phone,
|
|
Mail: req.Mail,
|
|
Createtime: time.Now().Unix(),
|
|
Language: req.Language,
|
|
Phonemodel: req.Phonemodel,
|
|
Phonemac: req.Phonemac,
|
|
Avatar: req.Avatar,
|
|
Name: req.Name,
|
|
Channel: req.Channel,
|
|
Version: req.Version,
|
|
}
|
|
switch req.Stype {
|
|
case pb.SginTyoe_WXChat:
|
|
user.Wxopenid = wxinfo.OpenID
|
|
user.Name = wxinfo.Nickname
|
|
user.Avatar = wxinfo.HeadImgURL
|
|
case pb.SginTyoe_Google:
|
|
user.Googleopenid = googleinfo.UID
|
|
case pb.SginTyoe_FaceBook:
|
|
user.Facebookopenid = facebookinfo.UserID
|
|
case pb.SginTyoe_Apple:
|
|
user.Appleopenid = apple_uuid
|
|
}
|
|
// if user.Phone != "" {
|
|
// user.Phone = aes.AesEncryptCBC(user.Phone, this.options.CBCKey)
|
|
// }
|
|
// if user.Mail != "" {
|
|
// user.Mail = aes.AesEncryptCBC(user.Mail, this.options.CBCKey)
|
|
// }
|
|
if user.Name == "" {
|
|
user.Name = fmt.Sprintf("User_%d", rand.Intn(10000))
|
|
}
|
|
// user.Name = aes.AesEncryptCBC(user.Name, this.options.CBCKey)
|
|
|
|
// if user.Avatar != "" {
|
|
// user.Avatar = aes.AesEncryptCBC(user.Avatar, this.options.CBCKey)
|
|
// }
|
|
// 新用户开户礼:VIP 天数 + 算力,两个数额由后台「会员与算力」页配置。
|
|
// 在 add 之前赋值,随用户一起落库,不需要额外一次写。见 newuser_gift.go。
|
|
// 参数取一次传给发放与流水两处,保证两者用同一份快照。
|
|
giftNow := time.Now().Unix()
|
|
giftParams := comm.LoadOpsParams()
|
|
applyNewUserGift(user, giftNow, giftParams)
|
|
if err = this.module.model.add(user); err != nil {
|
|
errdata = &pb.ErrorData{
|
|
Code: pb.ErrorCode_DBError,
|
|
Message: err.Error(),
|
|
}
|
|
return
|
|
}
|
|
logNewUserGift(user.Uid, giftNow, giftParams)
|
|
// 新增用户埋点
|
|
if this.module.analyze != nil {
|
|
this.module.analyze.Report(&comm.StatEvent{Type: comm.StatEventRegister, Uid: user.Uid})
|
|
}
|
|
} else if user.State == pb.UserState_Disabled {
|
|
// 账号已被禁用,拒绝登录
|
|
errdata = &pb.ErrorData{
|
|
Code: pb.ErrorCode_ExceptionAccountVerification,
|
|
Message: "account disabled",
|
|
}
|
|
return
|
|
} else if user.State == pb.UserState_Cancelled {
|
|
user.State = pb.UserState_Normal
|
|
user.Canceltime = 0
|
|
switch req.Stype {
|
|
case pb.SginTyoe_WXChat:
|
|
user.Wxopenid = wxinfo.OpenID
|
|
user.Name = wxinfo.Nickname
|
|
user.Avatar = wxinfo.HeadImgURL
|
|
case pb.SginTyoe_Google:
|
|
user.Googleopenid = googleinfo.UID
|
|
case pb.SginTyoe_FaceBook:
|
|
user.Facebookopenid = facebookinfo.UserID
|
|
case pb.SginTyoe_Apple:
|
|
user.Appleopenid = apple_uuid
|
|
}
|
|
if user.Name == "" {
|
|
user.Name = fmt.Sprintf("User_%d", rand.Intn(10000))
|
|
}
|
|
}
|
|
if istestaccount {
|
|
user.Vipexptime = time.Now().AddDate(1, 0, 0).Unix()
|
|
user.Aichattotalintegral = 1000000
|
|
user.Tradeintegral = 60 * 60 * 24 * 365
|
|
user.Tradetotalintegral = user.Tradeintegral
|
|
user.Meetintegral = 60 * 60 * 24 * 365
|
|
user.Meettotalintegral = user.Meetintegral
|
|
}
|
|
user.Lastsgintime = time.Now().Unix()
|
|
user.Channel = req.Channel
|
|
user.Version = req.Version
|
|
if ipdata, _ = ipinfo.GetIPInfo(session.GetIP()); ipdata != nil {
|
|
user.ContinentCode = ipdata.ContinentCode
|
|
user.CountryCode = ipdata.CountryCode
|
|
}
|
|
|
|
claims := &jwt.RegisteredClaims{
|
|
Issuer: "Earphone",
|
|
Subject: "Sgin",
|
|
// ExpiresAt: jwt.NewNumericDate(time.Now().Add(time.Hour * 24)), // 24 hours expiration
|
|
NotBefore: jwt.NewNumericDate(time.Now()),
|
|
IssuedAt: jwt.NewNumericDate(time.Now()),
|
|
ID: user.Uid,
|
|
}
|
|
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
|
|
if tokenString, err = token.SignedString([]byte(this.options.TokenKey)); err != nil {
|
|
errdata = &pb.ErrorData{
|
|
Code: pb.ErrorCode_ReqParameterError,
|
|
Message: pb.ErrorCode_ReqParameterError.String(),
|
|
}
|
|
this.module.Errorln(err)
|
|
return
|
|
}
|
|
if err = this.module.model.save(user); err != nil {
|
|
errdata = &pb.ErrorData{
|
|
Code: pb.ErrorCode_DBError,
|
|
Message: err.Error(),
|
|
}
|
|
return
|
|
}
|
|
// 登录埋点
|
|
if this.module.analyze != nil {
|
|
// 登录归到用户最后绑定设备的产品/渠道商名下,渠道商后台才看得到自己带来的用户活跃。
|
|
this.module.analyze.Report(&comm.StatEvent{Type: comm.StatEventLogin, ProductId: user.Lastbindproductid, ChannelId: user.Lastbindchannelid, Uid: user.Uid})
|
|
}
|
|
divices, err = this.module.model.getDevices(user.Uid)
|
|
if err != nil {
|
|
errdata = &pb.ErrorData{
|
|
Code: pb.ErrorCode_DBError,
|
|
Message: err.Error(),
|
|
}
|
|
return
|
|
}
|
|
|
|
resp = &pb.UserSginResp{
|
|
Token: tokenString,
|
|
User: user,
|
|
Devices: divices,
|
|
}
|
|
return
|
|
}
|
|
|