mh_server/controller/account.go
2022-08-04 11:57:21 +08:00

659 lines
18 KiB
Go

package controller
import (
"fmt"
"github.com/codinl/go-logger"
"github.com/gin-gonic/gin"
"github.com/medivhzhan/weapp"
"golang.org/x/sync/errgroup"
"mh-server/config"
"mh-server/lib/auth"
"mh-server/lib/status"
"mh-server/lib/utils"
"mh-server/lib/utils/crypt"
"mh-server/model"
"time"
)
func AuthLogin(c *gin.Context) {
req := struct {
Code string `json:"code" binding:"required"`
InviteUid uint32 `json:"invite_uid"`
}{}
if err := c.ShouldBindJSON(&req); err != nil {
logger.Error(err)
RespJson(c, status.BadRequest, nil)
return
}
fmt.Println("WxAppId", config.AppConfig.WxAppId)
fmt.Println("WxAppSecret", config.AppConfig.WxAppSecret)
model.AuthLoginMutex.Lock()
defer model.AuthLoginMutex.Unlock()
resp, err := weapp.Login(config.AppConfig.WxAppId, config.AppConfig.WxAppSecret, req.Code)
if err != nil {
logger.Error(err)
RespJson(c, status.BadRequest, nil)
return
}
if resp.SessionKey == "" {
logger.Error("Get SessionKey Fail")
RespJson(c, status.BadRequest, nil)
return
}
fmt.Println("用户信息 resp:", resp)
logger.Infof("OpenID=%+v", resp.OpenID)
logger.Info("resp.UnionID=", resp.UnionID)
var user = model.User{}
sqlErr := model.NewUserQuerySet(model.DB).WxOpenIDEq(resp.OpenID).One(&user)
if sqlErr != nil && sqlErr != model.RecordNotFound {
logger.Error("WxOpenIDEq:", sqlErr)
RespJson(c, status.DBOperateError, nil)
return
}
//var lastUser model.User
//if err := model.NewUserQuerySet(model.DB).OrderDescByID().One(&lastUser); err != nil && err != model.RecordNotFound {
// logger.Error(err)
// RespJson(c, status.InternalServerError, nil)
// return
//}
fmt.Println("InviteUid:", req.InviteUid)
nowTime := time.Now()
// 不存在则创建 新用户
//var invite *model.UserInvite
//if req.InviteUid != 0 && req.InviteUid != user.Uid && user.StoreId == 0 {
if req.InviteUid != 0 && req.InviteUid != user.Uid {
inviteUser := model.GetUserByUid(req.InviteUid)
user.StoreId = inviteUser.StoreId
if user.StoreId == 0 {
_, err = model.NewUserQuerySet(model.DB).UidEq(user.Uid).GetUpdater().SetStoreId(inviteUser.StoreId).
UpdateNum()
if err != nil {
logger.Error("update err:", err)
}
}
if inviteUser.UserType == 2 && user.Uid != 0 {
exist, err := model.QueryRecordExist(
fmt.Sprintf("SELECT * FROM user_invite_record WHERE to_uid = %d AND from_uid = %d ",
user.Uid, req.InviteUid))
if err != nil {
logger.Error("query err:", err)
RespJson(c, status.InternalServerError, nil)
return
}
if !exist {
firstInviteRecord := &model.UserInviteRecord{
ToUid: user.Uid,
FromUid: req.InviteUid,
Action: 2,
SpendType: 1,
MemberLevel: 0,
First: 1,
Scan: 1,
ActionTime: nowTime,
}
err = model.DB.Create(firstInviteRecord).Error
if err != nil {
logger.Error("create user invite record err:", err)
}
}
inviteRecord := &model.UserInviteRecord{
ToUid: user.Uid,
FromUid: req.InviteUid,
Action: 1,
SpendType: 1,
MemberLevel: 0,
First: 0,
Scan: 1,
ActionTime: nowTime,
}
err = model.DB.Create(inviteRecord).Error
if err != nil {
logger.Error("create user invite record err:", err)
}
var inviteNew model.UserInvite
inviteErr := model.NewUserInviteQuerySet(model.DB).ToUidEq(user.Uid).FromUidEq(req.InviteUid).ActionEq(1).
SpendTypeEq(1).One(&inviteNew)
if inviteErr != nil && inviteErr != model.RecordNotFound {
logger.Error("user invite err:", err)
}
fmt.Println("inviteErr:", inviteErr)
fmt.Printf("inviteNew:%#v \n", inviteNew)
if inviteErr == model.RecordNotFound {
memberLevel := user.MemberLevel
if memberLevel == 0 {
memberLevel = model.MemberTypeConsumer
}
invite := &model.UserInvite{
FromUid: req.InviteUid,
UserType: inviteUser.UserType,
StoreId: inviteUser.StoreId,
MemberOpenTime: time.Time{},
MemberType: memberLevel,
MemberStatus: 1,
ToUid: user.Uid,
Action: 1,
SpendType: 1,
UserInviteRecordId: inviteRecord.ID,
FirstInvite: 0, // TODO
Scan: 1,
}
fmt.Println("创建邀请:", invite)
//count, err := model.NewUserInviteQuerySet(model.DB).FromUidEq(req.InviteUid).ToUidEq(user.Uid).Count()
//if err != nil {
// logger.Error(err)
// RespJson(c, status.InternalServerError, nil)
// return
//}
//if count == 0 {
//}
if err := invite.Create(model.DB); err != nil {
logger.Error(err)
RespJson(c, status.InternalServerError, nil)
return
}
}
if inviteErr == nil {
//err = model.NewUserInviteQuerySet(model.DB).IDEq(inviteNew.ID).GetUpdater().
// SetFromUid(req.InviteUid).SetStoreId(inviteUser.StoreId).SetUserInviteRecordId(inviteRecord.ID).Update()
err = model.NewUserInviteQuerySet(model.DB).IDEq(inviteNew.ID).GetUpdater().SetCreatedAt(nowTime).
SetUserInviteRecordId(inviteRecord.ID).Update()
if err != nil {
logger.Error("from uid update user invite err:", err, req.InviteUid)
}
}
}
}
if sqlErr == model.RecordNotFound {
user = model.User{
WxOpenID: resp.OpenID,
WxUnionID: resp.UnionID,
LastLoginAt: nowTime,
MemberLevel: 1,
//Notify: common.Yes,
}
user.Uid = createUid()
var eg errgroup.Group
if req.InviteUid != 0 {
inviteRecordFirst := &model.UserInviteRecord{
ToUid: user.Uid,
FromUid: req.InviteUid,
Action: 2,
SpendType: 1,
MemberLevel: 0,
First: 1,
Scan: 1,
ActionTime: nowTime,
}
err = model.DB.Create(inviteRecordFirst).Error
if err != nil {
logger.Error("create user invite record err:", err)
}
inviteRecord := &model.UserInviteRecord{
ToUid: user.Uid,
FromUid: req.InviteUid,
Action: 1,
SpendType: 1,
MemberLevel: 0,
First: 0,
Scan: 1,
ActionTime: nowTime,
}
err = model.DB.Create(inviteRecord).Error
if err != nil {
logger.Error("create user invite record err:", err)
}
inviteUser := model.GetUserByUid(req.InviteUid)
user.StoreId = inviteUser.StoreId
user.UserType = model.UserTypeConsumer
user.CooperativeBusinessId = inviteUser.CooperativeBusinessId
user.CooperativeName = inviteUser.CooperativeName
invite := &model.UserInvite{
FromUid: req.InviteUid,
UserType: inviteUser.UserType,
StoreId: inviteUser.StoreId,
MemberType: model.MemberTypeConsumer,
ToUid: user.Uid,
MemberStatus: 1,
Action: 1,
SpendType: 1,
UserInviteRecordId: inviteRecord.ID,
Scan: 1,
}
eg.Go(func() error {
if err := invite.Create(model.DB); err != nil {
logger.Error(err)
RespJson(c, status.InternalServerError, nil)
return err
}
return nil
})
}
fmt.Println("新用户:", user.WxOpenID)
eg.Go(func() error {
if err := user.Create(model.DB); err != nil {
logger.Error(err)
RespJson(c, status.InternalServerError, nil)
return err
}
return nil
})
err := eg.Wait()
if err != nil {
logger.Error(err)
RespJson(c, status.InternalServerError, nil)
return
}
newAccessToken, err := auth.CreateAccessToken(user.Uid)
if err != nil {
logger.Error(err)
RespJson(c, status.InternalServerError, nil)
return
}
fmt.Println("JwtUserRefreshKey:", config.AppConfig.JwtUserRefreshKey)
fmt.Println("JwtUserRefreshExpire:", config.AppConfig.JwtUserRefreshExpire)
newRefreshToken, err := auth.CreateToken(user.Uid, config.AppConfig.JwtUserRefreshKey, config.AppConfig.JwtUserRefreshExpire)
if err != nil {
logger.Error(err)
RespJson(c, status.InternalServerError, nil)
return
}
refreshToken := &model.UserRefreshToken{
Uid: user.Uid,
Token: newRefreshToken,
}
err = refreshToken.Create(model.DB)
if err != nil {
logger.Error(err)
RespJson(c, status.InternalServerError, nil)
return
}
RespJson(c, status.OK, map[string]interface{}{
"access_token": newAccessToken,
"access_expire": config.AppConfig.JwtUserAccessExpire,
"refresh_token": refreshToken.Token,
"refresh_expire": config.AppConfig.JwtUserRefreshExpire,
"uid": user.Uid,
"access_created_at": nowTime,
})
return
}
fmt.Println(" user:", user.Uid)
// 旧用户
newAccessToken, err := auth.CreateAccessToken(user.Uid)
if err != nil {
logger.Error(err)
RespJson(c, status.InternalServerError, nil)
}
//fmt.Println("JwtUserRefreshKey:", config.AppConfig.JwtUserRefreshKey) 79013845
//fmt.Println("JwtUserRefreshExpire:", config.AppConfig.JwtUserRefreshExpire)
//newRefreshToken, err := auth.CreateToken(user.Uid, config.AppConfig.JwtUserRefreshKey, config.AppConfig.JwtUserRefreshExpire)
//if err != nil {
// logger.Error(err)
// RespJson(c, status.InternalServerError, nil)
// return
//}
//refreshToken := &model.UserRefreshToken{
// Uid: user.Uid,
// Token: newRefreshToken,
//}
//err = refreshToken.Create(model.DB)
//if err != nil {
// logger.Error(err)
// RespJson(c, status.InternalServerError, nil)
// return
//}
//isNew := false
//// 用户没有授权 下次进入不会提示
//if user.WxOpenID == "" {
// isNew = true
//}
newRefreshToken, err := auth.CreateToken(user.Uid, config.AppConfig.JwtUserRefreshKey, config.AppConfig.JwtUserRefreshExpire)
if err != nil {
logger.Error(err)
RespJson(c, status.InternalServerError, nil)
return
}
refreshToken, err := model.UserRefreshTokenGetOrUpdate(user.Uid, newRefreshToken)
if err != nil {
logger.Error(err)
RespJson(c, status.InternalServerError, nil)
return
}
//inviteCode := strconv.FormatUint(uint64(user.ID), 32)
err = model.NewUserQuerySet(model.DB).WxOpenIDEq(resp.OpenID).GetUpdater().SetLastLoginAt(time.Now()).Update()
if err != nil && err != model.RecordNotFound {
logger.Error(err)
}
RespJson(c, status.OK, map[string]interface{}{
"access_token": newAccessToken,
"access_expire": config.AppConfig.JwtUserAccessExpire,
"refresh_token": refreshToken.Token,
"refresh_expire": config.AppConfig.JwtUserRefreshExpire,
"uid": user.Uid,
"access_created_at": nowTime,
//"is_new": isNew,
//"invite_from_code": inviteCode,
})
return
}
func UserInfoUpload(c *gin.Context) {
req := struct {
Uid uint32 `json:"uid" binding:"required"`
Code string `json:"code" binding:"required"`
EncryptedData string `json:"encrypted_data" binding:"required"`
RawData string `json:"raw_data" binding:"required"`
Signature string `json:"signature" binding:"required"`
Iv string `json:"iv" binding:"required"`
//UserInfo weapp.Userinfo `json:"user_info" binding:"required"`
}{}
if err := c.ShouldBindJSON(&req); err != nil {
logger.Error(err)
RespJson(c, status.BadRequest, nil)
return
}
resp, err := weapp.Login(config.AppConfig.WxAppId, config.AppConfig.WxAppSecret, req.Code)
if err != nil {
logger.Error(err)
RespJson(c, status.BadRequest, nil)
return
}
if resp.SessionKey == "" {
logger.Error("Get SessionKey Fail")
RespJson(c, status.BadRequest, nil)
return
}
userInfo, err := weapp.DecryptUserInfo(req.RawData, req.EncryptedData, req.Signature, req.Iv, resp.SessionKey)
if err != nil {
logger.Error(err)
RespJson(c, status.BadRequest, nil)
return
}
logger.Infof("userInfo=%+v", userInfo)
user := new(model.User)
if err := model.NewUserQuerySet(model.DB).UidEq(req.Uid).One(user); err == nil {
user.WxUnionID = userInfo.UnionID
//user.WxName = req.UserInfo.Nickname
//user.WxAvatar = req.UserInfo.Avatar
//user.Gender = uint8(req.UserInfo.Gender)
//user.City = req.UserInfo.City
//user.Province = req.UserInfo.Province
//user.Country = req.UserInfo.Country
//user.MemberLevel = 1
user.WxName = userInfo.Nickname
user.WxAvatar = userInfo.Avatar
user.Gender = uint8(userInfo.Gender)
user.Province = userInfo.Province
user.City = userInfo.City
user.Country = userInfo.Country
as := model.UserDBSchema
if err := user.Update(model.DB, as.WxUnionID, as.WxName, as.WxAvatar, as.Gender, as.City, as.Province, as.Country, as.MemberLevel); err != nil {
logger.Error(err)
RespJson(c, status.InternalServerError, nil)
return
}
}
RespOK(c, nil)
}
func UserData(c *gin.Context) {
uc := auth.GetCurrentUser(c)
if uc == nil {
RespJson(c, status.Unauthorized, nil)
return
}
m := new(model.User)
if err := model.NewUserQuerySet(model.DB).UidEq(uc.Uid).One(m); err != nil && err != model.RecordNotFound {
logger.Error(err)
RespJson(c, status.Unauthorized, nil)
return
}
var userVm model.UserVm
err := model.NewUserVmQuerySet(model.DB).UidEq(uc.Uid).One(&userVm)
if err != nil && err != model.RecordNotFound {
logger.Error("err")
RespJson(c, status.InternalServerError, nil)
return
}
if err == model.RecordNotFound {
userVm = model.UserVm{
Uid: uc.Uid,
Vm: 0,
}
err = model.DB.Create(&userVm).Error
if err != nil {
logger.Error(err)
RespJson(c, status.InternalServerError, nil)
return
}
}
m.UserVm = &userVm
ret := m
RespOK(c, ret)
return
}
// 找一个可以用的Uid
func createUid() uint32 {
for {
uid := utils.GenUid()
if count, err := model.NewUserQuerySet(model.DB).UidEq(uid).Count(); err == nil && count > 0 {
continue
}
return uid
}
}
func TokenRefresh(c *gin.Context) {
req := struct {
RefreshToken string `json:"refresh_token" binding:"required"`
}{}
if c.ShouldBindJSON(&req) != nil {
RespJson(c, status.BadRequest, nil)
return
}
userJwt := auth.NewJWT(config.AppConfig.JwtUserRefreshKey)
uc, err := userJwt.ParseToken(req.RefreshToken)
if err != nil {
logger.Error(err)
RespJson(c, status.RefreshTokenInvalid, nil)
return
}
// 从数据库获取用户的refresh_token
m := new(model.UserRefreshToken)
if err := model.NewUserRefreshTokenQuerySet(model.DB).UidEq(uc.Uid).One(m); err == nil {
if req.RefreshToken == m.Token {
newAccessToken, err := auth.CreateToken(uc.Uid, config.AppConfig.JwtUserAccessKey, config.AppConfig.JwtUserAccessExpire)
if err != nil {
logger.Error(err)
RespJson(c, status.InternalServerError, nil)
return
}
newRefreshToken, err := auth.CreateToken(uc.Uid, config.AppConfig.JwtUserRefreshKey, config.AppConfig.JwtUserRefreshExpire)
if err != nil {
logger.Error(err)
RespJson(c, status.InternalServerError, nil)
return
}
refreshToken, err := model.UserRefreshTokenGetOrUpdate(uc.Uid, newRefreshToken)
if err != nil {
logger.Error(err)
RespJson(c, status.InternalServerError, nil)
return
}
now := time.Now()
logger.Info("now.Unix=", now.Unix())
RespJson(c, status.OK, map[string]interface{}{
"access_token": newAccessToken,
"access_expire": config.AppConfig.JwtUserAccessExpire,
"refresh_token": refreshToken.Token,
"refresh_expire": config.AppConfig.JwtUserRefreshExpire,
"uid": uc.Uid,
"access_created_at": now,
"refresh_created_at": refreshToken.CreatedAt,
})
return
} else {
RespJson(c, status.BadRequest, nil)
return
}
} else {
logger.Error(err)
RespJson(c, status.BadRequest, nil)
return
}
}
func UserTel(c *gin.Context) {
req := struct {
Code string `json:"code" `
EncryptedData string `json:"encrypted_data" `
Iv string `json:"iv" `
}{}
if c.ShouldBindJSON(&req) != nil {
RespJson(c, status.BadRequest, nil)
return
}
uc := auth.GetCurrentUser(c)
if uc == nil {
RespJson(c, status.Unauthorized, nil)
return
}
if req.Code != "" && req.EncryptedData != "" && req.Iv != "" {
resp, err := weapp.Login(config.AppConfig.WxAppId, config.AppConfig.WxAppSecret, req.Code)
if err != nil {
RespJson(c, status.BadRequest, nil)
return
}
phone, err := weapp.DecryptPhoneNumber(resp.SessionKey, req.EncryptedData, req.Iv)
if err != nil {
logger.Error(err)
RespJson(c, status.InternalServerError, nil)
return
}
_ = model.NewUserQuerySet(model.DB).UidEq(uc.Uid).GetUpdater().SetTel(phone.PhoneNumber).Update()
RespJson(c, status.OK, map[string]interface{}{
"tel": phone.PurePhoneNumber,
})
return
} else {
user := model.GetUserByUid(uc.Uid)
if user.Tel != "" {
RespJson(c, status.OK, map[string]interface{}{
"tel": user.Tel,
})
return
}
}
RespJson(c, status.OK, map[string]interface{}{
"tel": "",
})
return
}
//func StepConfig(c *gin.Context) {
// stepConfig := model.GetStepConfig()
// RespJson(c, status.OK, stepConfig)
//}
func UserInviteAppletQRCode(c *gin.Context) {
req := struct {
Uid uint32 `json:"uid" binding:"required"`
}{}
if c.ShouldBindJSON(&req) != nil || req.Uid == 0 {
RespJson(c, status.BadRequest, nil)
return
}
user := model.GetUserByUid(req.Uid)
if user.InviteCodeUrl == "" && user.Uid != 0 {
//shareCode, err := crypt.GenShareCode(req.Uid)
shareCode, err := crypt.GenDrawShareCode("", "", "", req.Uid)
if err != nil {
logger.Error("err:", err)
RespJson(c, status.InternalServerError, nil)
return
}
user.InviteCodeUrl = shareCode
user.AppletQRCodeUpdate()
}
RespOK(c, user)
}
func UserInviteList(c *gin.Context) {
req := model.UserInviteListReq{}
if c.ShouldBindJSON(&req) != nil || req.Uid == 0 {
RespJson(c, status.BadRequest, nil)
return
}
uc := auth.GetCurrentUser(c)
if uc == nil {
logger.Error("uc is nil")
RespJson(c, status.Unauthorized, nil)
return
}
if req.Uid == 0 {
req.Uid = uc.Uid
}
fmt.Println("req.MemberType:", req.MemberType)
fmt.Printf("req.MemberType:%#v \n", req)
fmt.Printf("req.MemberType:%+v \n", req)
resp, err := req.InviteUserList()
if err != nil {
logger.Error("err:", err)
RespJson(c, status.InternalServerError, nil)
return
}
RespOK(c, resp)
}