|
@@ -0,0 +1,421 @@
|
|
|
+package services
|
|
|
+
|
|
|
+import (
|
|
|
+ "context"
|
|
|
+ "encoding/json"
|
|
|
+ "errors"
|
|
|
+ "fmt"
|
|
|
+ "github.com/silenceper/wechat/v2/miniprogram/auth"
|
|
|
+ "hongze/hongze_yb/global"
|
|
|
+ "hongze/hongze_yb/models/tables/session"
|
|
|
+ "hongze/hongze_yb/models/tables/user_record"
|
|
|
+ "hongze/hongze_yb/models/tables/wx_user"
|
|
|
+ "hongze/hongze_yb/models/tables/wx_user_log"
|
|
|
+ "hongze/hongze_yb/utils"
|
|
|
+ "strconv"
|
|
|
+ "time"
|
|
|
+)
|
|
|
+
|
|
|
+var ERR_NO_USER_RECORD = errors.New("用户关系没有入库")
|
|
|
+var ERR_USER_NOT_BIND = errors.New("用户没有绑定")
|
|
|
+
|
|
|
+type UserInfo struct {
|
|
|
+ wx_user.WxUser
|
|
|
+ RecordInfo *user_record.UserRecord
|
|
|
+}
|
|
|
+
|
|
|
+// GetWxUserItemByOpenId 通过openid获取用户信息
|
|
|
+func GetWxUserItemByOpenId(openid string) (userInfo UserInfo, err error) {
|
|
|
+ //通过openid获取用户关联信息
|
|
|
+ userRecord, userRecordErr := user_record.GetByOpenID(openid)
|
|
|
+ if userRecordErr != nil {
|
|
|
+ if userRecordErr == utils.ErrNoRow {
|
|
|
+ err = ERR_NO_USER_RECORD
|
|
|
+ return
|
|
|
+ } else {
|
|
|
+ err = userRecordErr
|
|
|
+ return
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ //该openid在系统中没有关联关系
|
|
|
+ if userRecord == nil {
|
|
|
+ err = ERR_NO_USER_RECORD
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ //该openid没有绑定用户
|
|
|
+ if userRecord.UserID <= 0 {
|
|
|
+ err = ERR_USER_NOT_BIND
|
|
|
+ item := new(wx_user.WxUser)
|
|
|
+ //格式化返回用户数据
|
|
|
+ userInfo = formatWxUserAndUserRecord(item, userRecord)
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ //获取用户信息
|
|
|
+ item, wxUserErr := wx_user.GetByUserId(userRecord.UserID)
|
|
|
+ if wxUserErr != nil {
|
|
|
+ err = wxUserErr
|
|
|
+
|
|
|
+ //如果是找不到数据,那么可能是该用户被删除了,但是user_record没有删除对应的关系
|
|
|
+ if wxUserErr == utils.ErrNoRow {
|
|
|
+ //用户被删除了,但是user_record没有删除对应的关系,那么去解除绑定
|
|
|
+ userUnbindErr := user_record.UnBindUserRecordByOpenid(openid)
|
|
|
+ if userUnbindErr != nil {
|
|
|
+ err = userUnbindErr
|
|
|
+ return
|
|
|
+ }
|
|
|
+ //返回状态为 用户未绑定 逻辑代码
|
|
|
+ err = ERR_USER_NOT_BIND
|
|
|
+ item := new(wx_user.WxUser)
|
|
|
+ //格式化返回用户数据
|
|
|
+ userInfo = formatWxUserAndUserRecord(item, userRecord)
|
|
|
+ return
|
|
|
+ }
|
|
|
+ return
|
|
|
+ }
|
|
|
+ //格式化返回用户数据
|
|
|
+ userInfo = formatWxUserAndUserRecord(item, userRecord)
|
|
|
+ return
|
|
|
+}
|
|
|
+
|
|
|
+// GetWxUserItemByUserId 根据用户id和平台id获取用户信息
|
|
|
+func GetWxUserItemByUserId(userId, platform int) (userInfo UserInfo, err error) {
|
|
|
+ //获取用户信息
|
|
|
+ wxUser, err := wx_user.GetByUserId(userId)
|
|
|
+ if err != nil {
|
|
|
+ return
|
|
|
+ }
|
|
|
+ //格式化返回用户数据
|
|
|
+ userInfo = formatWxUser(wxUser, platform)
|
|
|
+ return
|
|
|
+}
|
|
|
+
|
|
|
+// GetWxUserItemByEmail 根据用户邮箱和平台id获取用户信息
|
|
|
+func GetWxUserItemByEmail(email string, platform int) (userInfo UserInfo, err error) {
|
|
|
+ //获取用户信息
|
|
|
+ wxUser, err := wx_user.GetByEmail(email)
|
|
|
+ if err != nil {
|
|
|
+ return
|
|
|
+ }
|
|
|
+ //格式化返回用户数据
|
|
|
+ userInfo = formatWxUser(wxUser, platform)
|
|
|
+ return
|
|
|
+}
|
|
|
+
|
|
|
+// GetWxUserItemByMobile 根据用户手机号和平台id获取用户信息
|
|
|
+func GetWxUserItemByMobile(mobile string, platform int) (userInfo UserInfo, err error) {
|
|
|
+ //获取用户信息
|
|
|
+ wxUser, err := wx_user.GetByMobile(mobile)
|
|
|
+ if err != nil {
|
|
|
+ return
|
|
|
+ }
|
|
|
+ //格式化返回用户数据
|
|
|
+ userInfo = formatWxUser(wxUser, platform)
|
|
|
+ return
|
|
|
+}
|
|
|
+
|
|
|
+// GetWxUserItemByUnionId 根据用户unionid和平台id获取用户信息
|
|
|
+func GetWxUserItemByUnionId(unionId string, platform int) (userInfo UserInfo, err error) {
|
|
|
+ //获取用户信息
|
|
|
+ userRecord, err := user_record.GetByUnionID(unionId, platform)
|
|
|
+ if err != nil {
|
|
|
+ return
|
|
|
+ }
|
|
|
+ wxUser, err := wx_user.GetByUserId(userRecord.UserID)
|
|
|
+ if err != nil {
|
|
|
+ return
|
|
|
+ }
|
|
|
+ //格式化返回用户数据
|
|
|
+ userInfo = formatWxUserAndUserRecord(wxUser, userRecord)
|
|
|
+ return
|
|
|
+}
|
|
|
+
|
|
|
+//通过用户 关系表记录 和 用户记录 格式化返回 用户数据
|
|
|
+func formatWxUserAndUserRecord(wxUser *wx_user.WxUser, userRecord *user_record.UserRecord) (userInfo UserInfo) {
|
|
|
+ wxUser.OpenID = userRecord.OpenID
|
|
|
+ wxUser.UnionID = userRecord.UnionID
|
|
|
+ wxUser.NickName = userRecord.NickName
|
|
|
+ //wxUser.RealName = userRecord.RealName
|
|
|
+ //wxUser.BindAccount = userRecord.BindAccount
|
|
|
+ wxUser.Headimgurl = userRecord.Headimgurl
|
|
|
+
|
|
|
+ wxUserJson, _ := json.Marshal(wxUser)
|
|
|
+ _ = json.Unmarshal(wxUserJson, &userInfo)
|
|
|
+ userInfo.RecordInfo = userRecord
|
|
|
+ return
|
|
|
+}
|
|
|
+
|
|
|
+//通过用户 用户记录 和 来源平台 格式化返回 用户数据
|
|
|
+func formatWxUser(wxUser *wx_user.WxUser, platform int) (userInfo UserInfo) {
|
|
|
+ //根据用户id和平台id获取用户关系
|
|
|
+ userRecord, userRecordErr := user_record.GetByUserId(int(wxUser.UserID), platform)
|
|
|
+ if userRecordErr != nil {
|
|
|
+ if userRecordErr != utils.ErrNoRow {
|
|
|
+ return
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ //该openid在系统中没有关联关系
|
|
|
+ if userRecord == nil {
|
|
|
+ wxUserJson, _ := json.Marshal(wxUser)
|
|
|
+ _ = json.Unmarshal(wxUserJson, &userInfo)
|
|
|
+ return
|
|
|
+ } else {
|
|
|
+ userInfo = formatWxUserAndUserRecord(wxUser, userRecord)
|
|
|
+ }
|
|
|
+ return
|
|
|
+}
|
|
|
+
|
|
|
+//用户绑定
|
|
|
+func BindWxUser(openid, mobile, email string, areaNum, registerPlatform int) (wxUser *wx_user.WxUser, err error) {
|
|
|
+ var source int8
|
|
|
+ source = 6 //绑定来源,1:微信端,2:pc网页端,3:查研观向小程序,4:每日咨询
|
|
|
+ if mobile == "" && email == "" {
|
|
|
+ err = errors.New("手机号或邮箱必填一个")
|
|
|
+ return
|
|
|
+ }
|
|
|
+ var bindAccount string
|
|
|
+ //根据手机号获取用户信息
|
|
|
+ if mobile != "" {
|
|
|
+ tmpWxUser, wxUserErr := wx_user.GetByMobile(mobile)
|
|
|
+ if wxUserErr != nil && wxUserErr != utils.ErrNoRow {
|
|
|
+ err = wxUserErr
|
|
|
+ return
|
|
|
+ }
|
|
|
+ wxUser = tmpWxUser
|
|
|
+ bindAccount = mobile
|
|
|
+ }
|
|
|
+ //根据邮箱获取用户信息
|
|
|
+ if wxUser == nil && email != "" {
|
|
|
+ tmpWxUser, wxUserErr := wx_user.GetByEmail(email)
|
|
|
+ if wxUserErr != nil && wxUserErr != utils.ErrNoRow {
|
|
|
+ err = wxUserErr
|
|
|
+ return
|
|
|
+ }
|
|
|
+ wxUser = tmpWxUser
|
|
|
+ bindAccount = email
|
|
|
+ }
|
|
|
+
|
|
|
+ //查询openid的第三方(微信)信息
|
|
|
+ userRecord, err := user_record.GetByOpenID(openid)
|
|
|
+ if err != nil {
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ var userId int
|
|
|
+ //如果查询出来的用户是nil,那么需要新增用户
|
|
|
+ if wxUser == nil {
|
|
|
+ key := "bind_wx_user:mobile:" + mobile + ":email:" + email
|
|
|
+ isHas, _ := global.Redis.Exists(context.TODO(), key).Result()
|
|
|
+ if isHas > 0 {
|
|
|
+ err = errors.New("多次提交,请关闭页面重新进入")
|
|
|
+ return
|
|
|
+ }
|
|
|
+ global.Redis.SetNX(context.TODO(), key, "ok", time.Second*300)
|
|
|
+ addwxUser := &wx_user.WxUser{
|
|
|
+ CompanyID: 1,
|
|
|
+ CreatedTime: time.Now(),
|
|
|
+ FirstLogin: 1,
|
|
|
+ Enabled: 1,
|
|
|
+ RegisterPlatform: int8(registerPlatform), //账号注册来源,注册平台,1:微信端,2:PC网页端
|
|
|
+ RegisterTime: time.Now(),
|
|
|
+ Mobile: mobile,
|
|
|
+ Email: email,
|
|
|
+ IsRegister: 1,
|
|
|
+ Source: source,
|
|
|
+ CountryCode: strconv.Itoa(areaNum),
|
|
|
+ OutboundMobile: mobile,
|
|
|
+ OutboundCountryCode: strconv.Itoa(areaNum),
|
|
|
+ }
|
|
|
+
|
|
|
+ addUserErr := addwxUser.Create()
|
|
|
+ //添加完成,清除缓存
|
|
|
+ _ = global.Redis.Del(context.TODO(), key)
|
|
|
+ if addUserErr != nil {
|
|
|
+ err = addUserErr
|
|
|
+ return
|
|
|
+ }
|
|
|
+ userId = int(addwxUser.UserID)
|
|
|
+ tmpWxUser, _ := wx_user.GetByUserId(userId)
|
|
|
+ wxUser = tmpWxUser
|
|
|
+ } else {
|
|
|
+ userId = int(wxUser.UserID)
|
|
|
+ }
|
|
|
+ //如果存在该手机号/邮箱,那么需要校验
|
|
|
+ if userRecord.UserID > 0 && userRecord.UserID != userId {
|
|
|
+ err = errors.New(fmt.Sprint("用户已绑定其他账户,已绑定的用户编号:", userRecord.UserID, ",不允许重复绑定"))
|
|
|
+ return
|
|
|
+ }
|
|
|
+ if userRecord.UserID == 0 {
|
|
|
+ userRecord.BindAccount = bindAccount
|
|
|
+ userRecord.UserID = userId
|
|
|
+ var updateCols = []string{"UserID", "BindAccount"}
|
|
|
+ tmpErr := userRecord.Update(updateCols)
|
|
|
+ if tmpErr != nil {
|
|
|
+ err = tmpErr
|
|
|
+ return
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ //如果当前该第三方用户信息的昵称为空串的话,那么需要去查询该用户的第一个绑定信息的数据作为来源做数据修复
|
|
|
+ if userRecord.NickName == "" {
|
|
|
+ oldUserRecord, err := user_record.GetUserThirdRecordByUserId(userId)
|
|
|
+ if err == nil && oldUserRecord != nil {
|
|
|
+ //如果该用户绑定的第一条数据的头像信息不为空串,那么就去做新数据的修复
|
|
|
+ if oldUserRecord.NickName != "" {
|
|
|
+ _ = userRecord.ModifyUserRecordInfo(oldUserRecord.NickName, oldUserRecord.Headimgurl, oldUserRecord.City, oldUserRecord.Province, oldUserRecord.Country, oldUserRecord.Sex)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ //如果该用户 绑定注册状态 字段处于 未注册 的情况下,那么去修改该数据
|
|
|
+ if wxUser.IsRegister == 0 {
|
|
|
+ err = wxUser.ModifyWxUserRegisterStatus(1, source, time.Now())
|
|
|
+ if err != nil {
|
|
|
+ return
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ //格式化用户数据
|
|
|
+ formatWxUserAndUserRecord(wxUser, userRecord)
|
|
|
+ return
|
|
|
+}
|
|
|
+
|
|
|
+//微信登录
|
|
|
+func WxLogin(wxPlatform int, code string, wxSession auth.ResCode2Session, userInfo UserInfo) (token string, userId, firstLogin, permission int, err error) {
|
|
|
+ openId := wxSession.OpenID
|
|
|
+ unionId := wxSession.UnionID
|
|
|
+ if unionId == "" {
|
|
|
+ unionId = userInfo.UnionID
|
|
|
+ }
|
|
|
+
|
|
|
+ //firstLogin==1,强制绑定手机号或者邮箱
|
|
|
+ firstLogin = 1
|
|
|
+
|
|
|
+QUERY_WX_USER:
|
|
|
+ wxUser, wxUserErr := GetWxUserItemByOpenId(openId)
|
|
|
+ if wxUserErr == ERR_NO_USER_RECORD { //没有用户openid记录
|
|
|
+ _, recordErr := AddUserRecord(openId, unionId, "", "", "", "", "", "", "", wxPlatform, 0, 0)
|
|
|
+ //如果插入失败,那么直接将错误信息返回
|
|
|
+ if recordErr != nil {
|
|
|
+ err = recordErr
|
|
|
+ return
|
|
|
+ }
|
|
|
+ //插入成功后,需要重新查询该用户,并进入下面的逻辑
|
|
|
+ goto QUERY_WX_USER
|
|
|
+ } else if wxUserErr == ERR_USER_NOT_BIND {
|
|
|
+ //没有用户信息
|
|
|
+ //wxUser.FirstLogin = 1
|
|
|
+ } else if wxUserErr != nil {
|
|
|
+ err = wxUserErr
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ //如果已经登录注册绑定的情况下
|
|
|
+ if wxUserErr == nil {
|
|
|
+ //获取用户权限
|
|
|
+ firstLogin = int(wxUser.FirstLogin)
|
|
|
+ userId = int(wxUser.UserID)
|
|
|
+
|
|
|
+ //if wxUserInfo != nil {
|
|
|
+ // go models.ModifyUserRecordInfo(openId, wxUserInfo.Nickname, wxUserInfo.Headimgurl, wxUserInfo.City, wxUserInfo.Province, wxUserInfo.Country, wxUserInfo.Sex, userId)
|
|
|
+ //}
|
|
|
+
|
|
|
+ if wxUser.Mobile == "" && wxUser.Email == "" {
|
|
|
+ firstLogin = 1
|
|
|
+ } else {
|
|
|
+ firstLogin = 0
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ //获取登录token
|
|
|
+ tokenItem, tokenErr := session.GetTokenByOpenId(openId)
|
|
|
+ if tokenErr != nil && tokenErr != utils.ErrNoRow {
|
|
|
+ err = errors.New("登录失败,获取token失败:" + tokenErr.Error())
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ if tokenItem == nil || (tokenErr != nil && tokenErr == utils.ErrNoRow) {
|
|
|
+ timeUnix := time.Now().Unix()
|
|
|
+ timeUnixStr := strconv.FormatInt(timeUnix, 10)
|
|
|
+ token = utils.MD5(openId) + utils.MD5(timeUnixStr)
|
|
|
+ //新增session
|
|
|
+ {
|
|
|
+ //session := new(session.Session)
|
|
|
+ //session.OpenID = openId
|
|
|
+ //session.UserID = int64(userId)
|
|
|
+ //session.CreatedTime = time.Now()
|
|
|
+ //session.LastUpdatedTime = time.Now()
|
|
|
+ //session.ExpireTime = time.Now().AddDate(0, 3, 0)
|
|
|
+ //session.AccessToken = token
|
|
|
+
|
|
|
+ sessionItem := &session.Session{
|
|
|
+ OpenID: openId,
|
|
|
+ UserID: int64(userId),
|
|
|
+ CreatedTime: time.Now(),
|
|
|
+ LastUpdatedTime: time.Now(),
|
|
|
+ ExpireTime: time.Now().AddDate(0, 3, 0),
|
|
|
+ AccessToken: token,
|
|
|
+ }
|
|
|
+ sessionErr := sessionItem.Create()
|
|
|
+ if err != nil {
|
|
|
+ err = errors.New("登录失败,新增用户session信息失败:" + sessionErr.Error())
|
|
|
+ return
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ token = tokenItem.AccessToken
|
|
|
+ //如果联系人编号不为空,且联系人编号与session里面的联系人编号不一致的时候,需要做session变更
|
|
|
+ if userId > 0 && tokenItem.UserID != int64(userId) {
|
|
|
+ _ = tokenItem.UpdateSession(userId, time.Now().AddDate(0, 1, 0))
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ //新增登录日志
|
|
|
+ {
|
|
|
+ loginLog := &wx_user_log.WxUserLog{
|
|
|
+ UserID: userId,
|
|
|
+ OpenID: openId,
|
|
|
+ UnionID: unionId,
|
|
|
+ CreateTime: time.Now(),
|
|
|
+ Handle: "yb_login",
|
|
|
+ Remark: token,
|
|
|
+ }
|
|
|
+ go loginLog.Create()
|
|
|
+ }
|
|
|
+ return
|
|
|
+}
|
|
|
+
|
|
|
+// AddUserRecord 添加第三方用户(微信)记录
|
|
|
+func AddUserRecord(openId, unionId, nickName, realName, province, city, country, headimgurl, sessionKey string, platform, sex, subscribe int) (userRecordInfo *user_record.UserRecord, err error) {
|
|
|
+ find, err := user_record.GetByOpenID(openId)
|
|
|
+ if err != nil && err != utils.ErrNoRow {
|
|
|
+ return
|
|
|
+ }
|
|
|
+ if find != nil {
|
|
|
+ userRecordInfo = find
|
|
|
+ return
|
|
|
+ }
|
|
|
+ userRecordInfo = &user_record.UserRecord{
|
|
|
+ OpenID: openId, //用户open_id
|
|
|
+ UnionID: unionId, //用户union_id
|
|
|
+ Subscribe: int8(subscribe),
|
|
|
+ NickName: nickName, //用户昵称,最大长度:32
|
|
|
+ RealName: realName, //用户实际名称,最大长度:32
|
|
|
+ Sex: int64(sex), //普通用户性别,1为男性,2为女性
|
|
|
+ Province: province, //普通用户个人资料填写的省份,最大长度:30
|
|
|
+ City: city, //普通用户个人资料填写的城市,最大长度:30
|
|
|
+ Country: country, //国家,如中国为CN,最大长度:30
|
|
|
+ Headimgurl: headimgurl, //用户第三方(微信)头像,最大长度:512
|
|
|
+ CreateTime: time.Now(), //创建时间,关系添加时间、用户授权时间
|
|
|
+ CreatePlatform: int8(platform), //注册平台,1:日度点评公众号,2:管理后台,3:pc端网站,4:查研观向小程序;默认:1
|
|
|
+ SessionKey: sessionKey, //微信小程序会话密钥,最大长度:255
|
|
|
+ }
|
|
|
+ err = userRecordInfo.Create()
|
|
|
+ if err != nil {
|
|
|
+ return
|
|
|
+ }
|
|
|
+ return
|
|
|
+}
|