package service import ( "context" "encoding/json" "errors" "fmt" "strconv" "strings" "time" "youngee_b_api/consts" "youngee_b_api/db" "youngee_b_api/model/gorm_model" "youngee_b_api/model/http_model" "youngee_b_api/model/redis_model" "youngee_b_api/model/system_model" "youngee_b_api/redis" "youngee_b_api/util" "github.com/sirupsen/logrus" ) var LoginAuth *loginAuth func LoginAuthInit(config *system_model.Session) { auth := new(loginAuth) auth.sessionTTL = time.Duration(config.TTL) * time.Minute LoginAuth = auth } type loginAuth struct { sessionTTL time.Duration } func (l *loginAuth) AuthToken(ctx context.Context, token string) (*redis_model.Auth, error) { phone, err := l.parseToken(ctx, token) if err != nil { logrus.Debug("token格式错误:%+v", token) return nil, err } auth, err := l.getSessionAuth(ctx, phone) if err != nil { logrus.Debug("获取session redis错误: token:%+v,err:%+v", token, err) return nil, err } if auth.Token != token { logrus.Debug("获取session time过期错误: token:%+v", token) return nil, errors.New("auth failed") } return auth, nil } // AuthCode 判断此手机号是否有账号存在 鉴定验证码 用户信息存入redis 并返回Token func (l *loginAuth) AuthCode(ctx context.Context, phone string, code string) (int, *http_model.CodeLoginData, error) { // 1. 验证码校验 vcode, err := l.getSessionCode(ctx, phone) if err != nil { return 0, nil, err } fmt.Printf("缓存的验证码 vcode: %v,实际填入的 code:%v", vcode, code) if vcode != code { // 验证码错误 logrus.Debugf("[AuthCode] auth fail,phone:%+v", phone) return 1, nil, nil } // 2. 查询是否存在用户信息,存在则取出,不存在则注册并取出 var userData *gorm_model.YounggeeUser userInfo, err := db.GetUserByPhone(ctx, phone) // fmt.Println("login_auth", user, err) if err != nil { // 数据库操作错误 return 0, nil, err } if userInfo == nil { subUserInfo, subUserErr := db.GetSubUserByPhone(ctx, phone) if subUserErr != nil { return 0, nil, subUserErr } if subUserInfo == nil { // fmt.Println("子账号也不存在") // 账号不存在,则默认注册商家账号 _, createEnterpriseErr := Enterprise.CreateEnterprise(ctx, phone) if createEnterpriseErr != nil { return 0, nil, createEnterpriseErr } enterpriseUserInfo, enterpriseUserErr := db.GetUserByPhone(ctx, phone) if enterpriseUserErr != nil { return 0, nil, enterpriseUserErr } userData = enterpriseUserInfo // fmt.Println("login_auth", user, err) } else { userData = subUserInfo } } else { userData = userInfo } token := l.getToken(ctx, phone, userData.Role) var jobData gorm_model.YounggeeJob var accountData gorm_model.YounggeeSubAccount var enterpriseUser gorm_model.Enterprise var loginUserData http_model.CodeLoginData var ifEnterprise int = 0 // 3. 根据用户类型的不同补充信息 // 若为商家用户 if string(userData.Role) == consts.BRole { ifEnterprise = 1 // fmt.Println("商家主账号") enterpriseUserInfo, enterpriseUserErr := db.GetEnterpriseByUID(ctx, userData.ID) if enterpriseUserErr != nil { return 0, nil, enterpriseUserErr } if enterpriseUserInfo != nil { enterpriseUser = *enterpriseUserInfo auth := &redis_model.Auth{ Phone: phone, ID: userData.ID, User: userData.User, Username: userData.Username, RealName: userData.RealName, Role: userData.Role, Email: userData.Email, Token: token, EnterpriseID: enterpriseUserInfo.EnterpriseID, } key := phone + userData.Role if sessionErr := l.setSession(ctx, key, auth); sessionErr != nil { fmt.Printf("setSession error\n") return 0, nil, sessionErr } } } else { // 若为商家子账号 fmt.Printf("商家子账号") subAccountUserInfo, subAccountUserErr := db.FindSubAccountByPhone(ctx, phone) if subAccountUserErr != nil { return 0, nil, subAccountUserErr } if subAccountUserInfo != nil { accountData = *subAccountUserInfo auth := &redis_model.Auth{ Phone: phone, ID: userData.ID, User: userData.User, Username: userData.Username, RealName: userData.RealName, Role: userData.Role, Email: userData.Email, Token: token, EnterpriseID: subAccountUserInfo.EnterpriseId, } jobInfo, jobErr := db.FindJobByJobId(ctx, subAccountUserInfo.JobId) if jobErr != nil { return 0, nil, jobErr } if jobInfo != nil { jobData = *jobInfo key := phone + userData.Role if sessionErr := l.setSession(ctx, key, auth); sessionErr != nil { fmt.Printf("setSession error\n") return 0, nil, sessionErr } } } } if ifEnterprise == 1 { loginUserData = http_model.CodeLoginData{ UserId: userData.ID, Token: token, Role: userData.Role, SubAccountId: 0, JobName: "主账号无岗位", EnterpriseId: enterpriseUser.EnterpriseID, WorkshopPermission: "1", CooperatePermission: "1", FinancialPermission: "1", TaskcenterPermission: "1", } } else { loginUserData = http_model.CodeLoginData{ UserId: userData.ID, Token: token, Role: userData.Role, SubAccountId: accountData.SubAccountId, JobName: jobData.JobName, EnterpriseId: accountData.EnterpriseId, WorkshopPermission: jobData.WorkshopPermission, CooperatePermission: jobData.CooperatePermission, FinancialPermission: jobData.FinancialPermission, TaskcenterPermission: jobData.TaskcenterPermission, } } return 0, &loginUserData, nil } // func (l *loginAuth) AuthPassword(ctx context.Context, phone string, password string) (string, error) { // // 验证是否存在 // user, err := db.GetUserByPhone(ctx, phone) // if err != nil { // return "", err // } // // 验证正确性 // if user == nil || user.Role != consts.BRole || user.Password != l.encryptPassword(password) { // // 登录失败 // logrus.Debugf("[AuthPassword] auth fail,phone:%+v", phone) // return "", errors.New("auth fail") // } // token := l.getToken(ctx, phone) // auth := &redis_model.Auth{ // Phone: phone, // ID: user.ID, // User: user.User, // Username: user.Username, // RealName: user.RealName, // Role: user.Role, // Email: user.Email, // Token: token, // } // if err := l.setSession(ctx, phone, auth); err != nil { // return "", err // } // return token, nil // } func (l *loginAuth) setSession(ctx context.Context, phone string, auth *redis_model.Auth) error { if authJson, err := json.Marshal(auth); err == nil { err = redis.Set(ctx, l.getRedisKey(phone), string(authJson), l.sessionTTL) if err == nil { return err } } return nil } func (l *loginAuth) getSessionCode(ctx context.Context, phone string) (string, error) { value, err := redis.Get(ctx, l.getRedisKey(phone)) if err != nil { if err == consts.RedisNil { return "", fmt.Errorf("not found in redis,phone:%+v", phone) } return "", err } return value, nil } func (l *loginAuth) getSessionAuth(ctx context.Context, phone string) (*redis_model.Auth, error) { value, err := redis.Get(ctx, l.getRedisKey(phone)) if err != nil { if err == consts.RedisNil { return nil, fmt.Errorf("not found in redis,phone:%+v", phone) } return nil, err } auth := new(redis_model.Auth) if err = json.Unmarshal([]byte(value), auth); err != nil { return nil, err } return auth, nil } func (l *loginAuth) getToken(ctx context.Context, phone string, role string) string { timeSeed := strconv.FormatInt(time.Now().Unix(), 10) token := phone + role + "." + timeSeed + "." + util.MD5(phone+role, timeSeed, consts.AuthSalt) return token } func (l *loginAuth) parseToken(ctx context.Context, token string) (string, error) { parts := strings.Split(token, ".") if len(parts) == 3 { phone := parts[0] timeSeed := parts[1] if parts[2] == util.MD5(phone, timeSeed, consts.AuthSalt) { return phone, nil } } return "", errors.New("token invalid") } func (l *loginAuth) encryptPassword(password string) string { return util.MD5(password) } func (l *loginAuth) getRedisKey(key string) string { return fmt.Sprintf("%s%s", consts.SessionRedisPrefix, key) } func (l *loginAuth) SubAccountAuthCode(ctx context.Context, req *http_model.AddNewSubAccountRequest) (int, error) { // 验证码校验 phoneNumber := req.PhoneNumber vCode, err := l.getSessionCode(ctx, phoneNumber) if err != nil { return 0, err } fmt.Printf("缓存的验证码 vcode: %v,实际填入的 code:%v", vCode, req.Code) if vCode != req.Code { // 验证码错误 logrus.Debugf("[AuthCode] auth fail,phone:%+v", phoneNumber) return 1, nil } subAccountUserInfo, subAccountUserErr := db.FindSubAccountByPhone(ctx, phoneNumber) if subAccountUserErr != nil { return 0, subAccountUserErr } if subAccountUserInfo == nil { // 子账号不存在,则判断此手机号码是否被商家主账号注册 bUser, bUserErr := db.GetUserByPhone(ctx, phoneNumber) if bUserErr != nil { return 0, bUserErr } if bUser == nil { createSubAccountErr := SubAccount.CreateSubAccount(ctx, req) if createSubAccountErr != nil { return 0, createSubAccountErr } } else { if bUser.AuthStatus != 1 { // 被商家主账户注册,未认证,则可以注册 createSubAccountErr := SubAccount.CreateSubAccount(ctx, req) if createSubAccountErr != nil { return 0, createSubAccountErr } } else { return 2, nil } } } else { // 子账号存在,则无法注册 logrus.Debugf("[AuthCode] subAccountExist,phone:%+v", phoneNumber) return 3, nil } return 0, nil } // UpdateEnterpriseAccountInfo 更新商家账号信息 func (l *loginAuth) UpdateEnterpriseAccountInfo(ctx context.Context, req *http_model.UpdateAccountInfoRequest) (*http_model.UpdateAccountInfoData, int, error) { var supplierUserInfo *http_model.UpdateAccountInfoData supplierUserInfo = &http_model.UpdateAccountInfoData{} supplierUserInfo.EnterpriseName = req.EnterpriseName supplierUserInfo.Avatar = req.Avatar supplierUserInfo.Phone = req.Phone supplierUserInfo.SubAccountName = req.SubAccountName if req.SubAccountId == 0 { // 商家主账号 // 1. 若修改绑定手机号 if req.Phone != "" { // 1.1. 校验验证码 vCode, err := l.getSessionCode(ctx, req.Phone) if err != nil { return nil, 0, err } if vCode != req.Code { return nil, 1, nil } // 1.2. 手机号是否已经被其他主账号绑定 enterpriseNum, enterpriseNumErr := db.CountEnterpriseUserByPhone(ctx, req.Phone) if enterpriseNumErr != nil { // log.Infof("[GetSupplierAccountInfo] fail,err:%+v", supplierNumErr) return nil, 0, enterpriseNumErr } if enterpriseNum != 0 { return nil, 2, nil } // 1.3. 手机号是否被子账号绑定 subAccountNum, SubAccountErr := db.CountSubAccountUserByPhone(ctx, req.Phone) if SubAccountErr != nil { // log.Infof("[GetSupplierAccountInfo] fail,err:%+v", SubAccountErr) return nil, 0, SubAccountErr } if subAccountNum != 0 { return nil, 3, nil } // 1.4. 修改Enterprise信息 var enterpriseInfo *gorm_model.Enterprise enterpriseInfo = &gorm_model.Enterprise{} enterpriseInfo.EnterpriseID = req.EnterpriseId enterpriseInfo.EnterpriseName = req.EnterpriseName enterpriseInfo.Avatar = req.Avatar enterpriseInfo.Phone = req.Phone updateEnterpriseErr := db.UpdateEnterpriseById(ctx, enterpriseInfo) if updateEnterpriseErr != nil { // log.Infof("[GetSupplierAccountInfo] fail,err:%+v", updateEnterpriseErr) return nil, 0, updateEnterpriseErr } // 1.5. 修改User表信息 enterpriseInfoQuery, enterpriseInfoQueryErr := db.GetEnterpriseByEnterpriseID(ctx, enterpriseInfo.EnterpriseID) if enterpriseInfoQueryErr != nil { // log.Infof("[GetSupplierAccountInfo] fail,err:%+v", supplierInfoQueryErr) return nil, 0, enterpriseInfoQueryErr } if enterpriseInfoQuery != nil { var userInfo *gorm_model.YounggeeUser userInfo = &gorm_model.YounggeeUser{} userInfo.ID = enterpriseInfoQuery.UserID userInfo.Phone = enterpriseInfoQuery.Phone userInfo.Username = enterpriseInfoQuery.Phone updateUserInfoErr := db.UpdateUserById(ctx, userInfo) if updateUserInfoErr != nil { // log.Infof("[GetSupplierAccountInfo] fail,err:%+v", updateUserInfoErr) return nil, 0, updateUserInfoErr } } } else { var enterpriseInfo *gorm_model.Enterprise enterpriseInfo = &gorm_model.Enterprise{} enterpriseInfo.EnterpriseID = req.EnterpriseId enterpriseInfo.EnterpriseName = req.EnterpriseName enterpriseInfo.Avatar = req.Avatar enterpriseInfo.Phone = req.Phone updateEnterpriseErr := db.UpdateEnterpriseById(ctx, enterpriseInfo) if updateEnterpriseErr != nil { // log.Infof("[GetSupplierAccountInfo] fail,err:%+v", updateEnterpriseErr) return nil, 0, updateEnterpriseErr } } } else { // 商家子账号 var subAccountInfo *gorm_model.YounggeeSubAccount subAccountInfo = &gorm_model.YounggeeSubAccount{} subAccountInfo.SubAccountType = 3 subAccountInfo.EnterpriseId = req.EnterpriseId subAccountInfo.SubAccountId = req.SubAccountId subAccountInfo.SubAccountName = req.SubAccountName subAccountInfo.Avatar = req.Avatar subAccountInfo.PhoneNumber = req.Phone updateSubAccountErr := db.UpdateSubAccount(ctx, subAccountInfo) if updateSubAccountErr != nil { // log.Infof("[GetSupplierAccountInfo] fail,err:%+v", updateSubAccountErr) return nil, 0, updateSubAccountErr } } return supplierUserInfo, 0, nil } // UpdateEnterpriseContactInfo 更新商家联系方式 func (l *loginAuth) UpdateEnterpriseContactInfo(ctx context.Context, req *http_model.UpdateContactInfoRequest) (*http_model.UpdateContactInfoData, bool, error) { var contactInfo *http_model.UpdateContactInfoData contactInfo = &http_model.UpdateContactInfoData{} // 主账号 if req.SubAccountId == 0 { // 1. 若更新联系电话则需要验证码校验 if req.ContactPhone != "" { vcode, err := l.getSessionCode(ctx, req.ContactPhone) if err != nil { return nil, false, err } // fmt.Printf("缓存的验证码 vcode: %v,实际填入的 code:%v", vcode, req.Code) if vcode != req.Code { // 验证码错误 return nil, true, err } var enterpriseInfo *gorm_model.Enterprise enterpriseInfo = &gorm_model.Enterprise{} enterpriseInfo.ContactPhone = req.ContactPhone enterpriseInfo.EnterpriseID = req.EnterpriseId updateEnterpriseErr := db.UpdateEnterpriseById(ctx, enterpriseInfo) if updateEnterpriseErr != nil { // log.Infof("[updateEnterpriseErr] fail,err:%+v", updateEnterpriseErr) return nil, false, updateEnterpriseErr } contactInfo.ContactPhone = req.ContactPhone } // 2. 微信二维码更新 if req.WechatQRCode != "" { var enterpriseInfo *gorm_model.Enterprise enterpriseInfo = &gorm_model.Enterprise{} enterpriseInfo.WechatQrCode = req.WechatQRCode enterpriseInfo.EnterpriseID = req.EnterpriseId updateEnterpriseErr := db.UpdateEnterpriseById(ctx, enterpriseInfo) if updateEnterpriseErr != nil { // log.Infof("[UpdateSupplierContactInfo] fail,err:%+v", updateEnterpriseErr) return nil, false, updateEnterpriseErr } contactInfo.WechatQRCode = req.WechatQRCode } // 2. 微信号码更新 if req.WechatNumber != "" { var enterpriseInfo *gorm_model.Enterprise enterpriseInfo = &gorm_model.Enterprise{} enterpriseInfo.WechatNumber = req.WechatNumber enterpriseInfo.EnterpriseID = req.EnterpriseId updateEnterpriseErr := db.UpdateEnterpriseById(ctx, enterpriseInfo) if updateEnterpriseErr != nil { // log.Infof("[UpdateSupplierContactInfo] fail,err:%+v", updateEnterpriseErr) return nil, false, updateEnterpriseErr } contactInfo.WechatNumber = req.WechatNumber } } else { // 子账号 // 1. 若更新联系电话则需要验证码校验 if req.ContactPhone != "" { vcode, err := l.getSessionCode(ctx, req.ContactPhone) if err != nil { return nil, false, err } // fmt.Printf("缓存的验证码 vcode: %v,实际填入的 code:%v", vcode, req.Code) if vcode != req.Code { // 验证码错误 return nil, true, err } var subAccountInfo *gorm_model.YounggeeSubAccount subAccountInfo = &gorm_model.YounggeeSubAccount{} subAccountInfo.ContactPhone = req.ContactPhone subAccountInfo.SubAccountId = req.SubAccountId updateSupplierErr := db.UpdateSubAccount(ctx, subAccountInfo) if updateSupplierErr != nil { // log.Infof("[UpdateSupplierContactInfo] fail,err:%+v", updateSupplierErr) return nil, false, updateSupplierErr } contactInfo.ContactPhone = req.ContactPhone } // 2. 微信二维码更新 if req.WechatQRCode != "" { var subAccountInfo *gorm_model.YounggeeSubAccount subAccountInfo = &gorm_model.YounggeeSubAccount{} subAccountInfo.WechatQRCode = req.WechatQRCode subAccountInfo.SubAccountId = req.SubAccountId updateSupplierErr := db.UpdateSubAccount(ctx, subAccountInfo) if updateSupplierErr != nil { // log.Infof("[UpdateSupplierContactInfo] fail,err:%+v", updateSupplierErr) return nil, false, updateSupplierErr } contactInfo.WechatQRCode = req.WechatQRCode } // 2. 微信号码更新 if req.WechatNumber != "" { var subAccountInfo *gorm_model.YounggeeSubAccount subAccountInfo = &gorm_model.YounggeeSubAccount{} subAccountInfo.WechatNumber = req.WechatNumber subAccountInfo.SubAccountId = req.SubAccountId updateSupplierErr := db.UpdateSubAccount(ctx, subAccountInfo) if updateSupplierErr != nil { // log.Infof("[UpdateSupplierContactInfo] fail,err:%+v", updateSupplierErr) return nil, false, updateSupplierErr } contactInfo.WechatNumber = req.WechatNumber } } return contactInfo, true, nil }