// Copyright 2019 getensh.com. All rights reserved. // Use of this source code is governed by getensh.com. package user import ( "context" "encoding/json" "fmt" "github.com/go-pay/gopay/wechat" "gorm.io/gorm" "property-household/errors" dbmodel "property-household/model" "property-household/pb" pb_v1 "property-household/pb/v1" "property-household/utils" "strings" "time" "git.getensh.com/common/gopkgs/database" "git.getensh.com/common/gopkgs/logger" "go.uber.org/zap" "google.golang.org/grpc/status" ) // 后端测试使用写死,后期改为微信小程序登录 func loginForTesting(phone string) (reply *pb_v1.LoginReply, err error) { user := &dbmodel.TUser{} where := map[string]interface{}{ "phone": phone, } err = user.Find(database.DB(), where) if err != nil && err != gorm.ErrRecordNotFound { return nil, errors.DataBaseError } if user.ID == 0 { return nil, errors.UserNotExist } reply = &pb_v1.LoginReply{Phone: phone, Uid: user.ID} reply.List, err = getHouses(user.ID) if err != nil { return nil, err } return reply, nil } func getGardenInfos(ids []int64) (map[int64]pb_v1.GardenItem, error) { ret := map[int64]pb_v1.GardenItem{} if len(ids) == 0 { return ret, nil } mreq := pb_v1.GardenInfosRequest{ Ids: ids, } mreply, err := pb.System.GardenInfos(context.Background(), &mreq) if err != nil { return nil, err } for _, v := range mreply.List { ret[v.Id] = *v } return ret, nil } func getHouses(uid int64) ([]*pb_v1.HouseholdHouseInfo, error) { p := dbmodel.THouseApproved{} where := map[string]interface{}{ "uid": uid, } list, err := p.List(database.DB(), where, nil, -1, -1) if err != nil { return nil, errors.DataBaseError } gardenIdsM := map[int64]bool{} gardenIds := []int64{} for _, v := range list { if gardenIdsM[v.GardenId] { continue } gardenIdsM[v.GardenId] = true gardenIds = append(gardenIds, v.GardenId) } gardenInfosM, err := getGardenInfos(gardenIds) if err != nil { return nil, err } ret := make([]*pb_v1.HouseholdHouseInfo, len(list)) for i, v := range list { ret[i] = &pb_v1.HouseholdHouseInfo{ Id: v.ID, GardenName: gardenInfosM[v.GardenId].GardenName, GardenId: v.GardenId, HouseId: v.HouseId, UserType: v.UserType, HouseName: fmt.Sprintf("%v-%v-%v", v.BuildingNumber, v.UnitNumber, v.HouseNumber), } } return ret, nil } func userChange(uid int64, userInfo dbmodel.TUser) (err error) { db := database.DB().Begin() defer func() { if err != nil { db.Rollback() } }() p1 := dbmodel.THouseApproved{} p2 := dbmodel.THouse{} where := map[string]interface{}{ "uid": uid, } uvalues := map[string]interface{}{"updated_at": time.Now()} p1values := map[string]interface{}{} p2values := map[string]interface{}{} if userInfo.Phone != "" { uvalues["phone"] = userInfo.Phone p1values["phone"] = userInfo.Phone p2values["phone"] = userInfo.Phone } if userInfo.PublicOpenId != "" { uvalues["public_open_id"] = userInfo.PublicOpenId p1values["public_open_id"] = userInfo.PublicOpenId } if userInfo.NickName != "" { uvalues["nick_name"] = userInfo.NickName } if userInfo.IdNumber != "" { uvalues["id_number"] = userInfo.IdNumber p2values["id_number"] = userInfo.IdNumber } if userInfo.IdType != 0 { uvalues["id_type"] = userInfo.IdType p2values["id_type"] = userInfo.IdType } if userInfo.RealName != "" { uvalues["real_name"] = userInfo.RealName p2values["name"] = userInfo.RealName } u := dbmodel.TUser{} uwhere := map[string]interface{}{ "id": uid, } err = u.Update(db, uwhere, uvalues) if err != nil { return errors.DataBaseError } approvedList, err := p1.List(database.DB(), where, nil, -1, -1) if err != nil { return errors.DataBaseError } if len(p1values) > 0 { p1values["updated_at"] = time.Now() err = p1.Update(db, where, p1values) if err != nil { return errors.DataBaseError } } if len(p2values) > 0 { p2values["updated_at"] = time.Now() err = p2.Update(db, where, p2values) if err != nil { return errors.DataBaseError } } mreq := pb_v1.HouseholdChangeRequest{ Phone: userInfo.Phone, PublicOpenId: userInfo.PublicOpenId, Uid: uid, NickName: userInfo.NickName, Name: userInfo.RealName, IdType: userInfo.IdType, IdNumber: userInfo.IdNumber, } m := map[int64]bool{} for _, v := range approvedList { if m[v.GardenId] { continue } m[v.GardenId] = true mreq.GardenIds = append(mreq.GardenIds, v.GardenId) } m = nil if len(mreq.GardenIds) > 0 { _, err = pb.Garden.HouseholdChange(context.Background(), &mreq) if err != nil { return err } } db.Commit() return nil } func getPublicOpenId(unionId string) (string, error) { if unionId == "" { return "", nil } p := dbmodel.TUserWxPublic{} where := map[string]interface{}{ "union_id": unionId, } err := p.Find(database.DB(), where) if err != nil && err != gorm.ErrRecordNotFound { return "", errors.DataBaseError } return p.OpenId, nil } func openimRegister(userId int64, realName string, phone string, face string, gender int32) string { if realName == "" { realName = phone } openimId := fmt.Sprintf("household%d", userId) mreq := pb_v1.OpenImRegisterRequest{UserId: openimId, Platform: 5, NickName: realName, FaceUrl: face, Gender: gender} _, err := pb.Thirdparty.OpenImRegister(context.Background(), &mreq) if err != nil { return "" } user := dbmodel.TUser{} where := map[string]interface{}{ "id": userId, } values := map[string]interface{}{ "openim_id": openimId, } err = user.Update(database.DB(), where, values) if err != nil { return "" } return openimId } // 手机号登录 func Login(ctx context.Context, req *pb_v1.LoginRequest) (reply *pb_v1.LoginReply, err error) { reply = &pb_v1.LoginReply{} // 捕获各个task中的异常并返回给调用者 defer func() { if r := recover(); r != nil { err = fmt.Errorf("%+v", r) e := &status.Status{} if er := json.Unmarshal([]byte(err.Error()), e); er != nil { logger.Error("err", zap.String("system_err", err.Error()), zap.Stack("stacktrace")) } } }() if false { return loginForTesting(req.Code) } if req.Code == "" || req.PhoneEncrypt == "" || req.PhoneIv == "" || req.UserEncrypt == "" || req.UserIv == "" { return nil, errors.ParamsError } mreq := &pb_v1.WxAppletLoginAuthRequest{Code: req.Code} mreply, err := pb.Thirdparty.WxAppletLoginAuth(ctx, mreq) if err != nil { return nil, err } fmt.Printf("xxxxxxxxxxx:%v,%v,%v\n", mreply.SessionKey, mreply.OpenId, mreply.UnionId) // 解密手机和用户信息 phoneInfo := wechat.UserPhone{} userInfo := wechat.AppletUserInfo{} err = wechat.DecryptOpenDataToStruct(req.PhoneEncrypt, req.PhoneIv, mreply.SessionKey, &phoneInfo) if err != nil { logger.Error("func", zap.String("call", "wechat.DecryptOpenDataToStruct1"), zap.String("params", fmt.Sprintf("%s,%s,%s", req.PhoneEncrypt, phoneInfo, mreply.SessionKey)), zap.String("error", err.Error())) return nil, status.Error(10003, "信息获取失败") } err = wechat.DecryptOpenDataToStruct(req.UserEncrypt, req.UserIv, mreply.SessionKey, &userInfo) if err != nil { logger.Error("func", zap.String("call", "wechat.DecryptOpenDataToStruct2"), zap.String("params", fmt.Sprintf("%s,%s,%s", req.UserEncrypt, req.UserIv, mreply.SessionKey)), zap.String("error", err.Error())) return nil, status.Error(10003, "信息获取失败") } user := &dbmodel.TUser{} where := map[string]interface{}{ "open_id": mreply.OpenId, } err = user.Find(database.DB(), where) if err != nil && err != gorm.ErrRecordNotFound { return nil, errors.DataBaseError } // 已存在,登录成功 if user.ID > 0 { needChange := false publicOpendId := user.PublicOpenId if publicOpendId == "" { publicOpendId, err = getPublicOpenId(user.UnionId) if err != nil { return nil, err } needChange = true } if user.Phone != phoneInfo.PhoneNumber { needChange = true } if needChange { uinfo := dbmodel.TUser{Phone: phoneInfo.PhoneNumber, PublicOpenId: publicOpendId} err = userChange(user.ID, uinfo) if err != nil { return nil, err } } reply.OpenId = user.OpenId reply.Phone = phoneInfo.PhoneNumber reply.NickName = user.NickName reply.Uid = user.ID reply.RealName = user.RealName reply.Avatar = user.Avatar reply.List, err = getHouses(user.ID) reply.OpenimId = user.OpenimId if reply.OpenimId == "" { reply.OpenimId = openimRegister(user.ID, user.RealName, user.Phone, user.Avatar, user.Gender) } idNumber := "" if user.IdNumber != "" { idNumber = utils.CertDecrypt(user.IdNumber) } reply.IdNumber = idNumber return reply, nil } // 不存在 publicOpendId, err := getPublicOpenId(mreply.UnionId) if err != nil { return nil, err } user.NickName = userInfo.NickName user.Phone = phoneInfo.PhoneNumber user.OpenId = mreply.OpenId user.UnionId = mreply.UnionId user.Avatar = userInfo.AvatarUrl user.PublicOpenId = publicOpendId user.Gender = int32(userInfo.Gender) err = user.Insert(database.DB()) if err != nil { msg := strings.ToLower(err.Error()) if strings.Contains(msg, "duplicate") { return nil, errors.ErrDuplicate } return nil, errors.DataBaseError } reply.OpenId = user.OpenId reply.Phone = user.Phone reply.NickName = user.NickName reply.Uid = user.ID reply.Avatar = userInfo.AvatarUrl reply.OpenimId = openimRegister(user.ID, user.NickName, user.Phone, user.Avatar, user.Gender) reply.IdNumber = "" return reply, nil }