Explorar o código

feat:新增中间件,微信登录,用户登录等逻辑

Roc %!s(int64=3) %!d(string=hai) anos
pai
achega
b885caa218

+ 20 - 4
controller/response/base.go

@@ -4,6 +4,12 @@ import (
 	"github.com/gin-gonic/gin"
 )
 
+var (
+	OK_CODE          = 200
+	FAIL_CODE        = 400
+	TOKEN_ERROR_CODE = 401
+)
+
 type ResultData struct {
 	Code int         `json:"code" description:"状态码"`
 	Msg  string      `json:"msg" description:"提示信息"`
@@ -19,7 +25,7 @@ func result(code int, resultData ResultData, c *gin.Context) {
 // OK 操作成功
 func Ok(msg string, c *gin.Context) {
 	resultData := ResultData{
-		Code: 200,
+		Code: OK_CODE,
 		Msg:  msg,
 	}
 	result(200, resultData, c)
@@ -28,7 +34,7 @@ func Ok(msg string, c *gin.Context) {
 // OkData 成功返回数据
 func OkData(msg string, data interface{}, c *gin.Context) {
 	resultData := ResultData{
-		Code: 200,
+		Code: OK_CODE,
 		Msg:  msg,
 		Data: data,
 	}
@@ -38,7 +44,7 @@ func OkData(msg string, data interface{}, c *gin.Context) {
 // Fail 操作失败
 func Fail(msg string, c *gin.Context) {
 	resultData := ResultData{
-		Code: 400,
+		Code: FAIL_CODE,
 		Msg:  msg,
 	}
 	result(200, resultData, c)
@@ -47,7 +53,7 @@ func Fail(msg string, c *gin.Context) {
 // FailData 成功返回数据
 func FailData(msg string, data interface{}, c *gin.Context) {
 	resultData := ResultData{
-		Code: 400,
+		Code: FAIL_CODE,
 		Msg:  msg,
 		Data: data,
 	}
@@ -72,3 +78,13 @@ func CustomData(code int, msg string, data interface{}, c *gin.Context) {
 	}
 	result(200, resultData, c)
 }
+
+//token异常
+func TokenError(data interface{}, message string, c *gin.Context) {
+	resultData := ResultData{
+		Code: TOKEN_ERROR_CODE,
+		Msg:  message,
+		Data: data,
+	}
+	result(200, resultData, c)
+}

+ 152 - 0
controller/user/user.go

@@ -0,0 +1,152 @@
+package user
+
+import (
+	"github.com/gin-gonic/gin"
+	"hongze/hongze_yb/controller/response"
+	"hongze/hongze_yb/models/request/user"
+	userResp "hongze/hongze_yb/models/response/user"
+	userService "hongze/hongze_yb/services/user"
+	"hongze/hongze_yb/utils"
+	"strings"
+)
+
+// Login 登录接口
+func Login(c *gin.Context) {
+	var req user.LoginReq
+	if c.ShouldBind(&req) != nil {
+		response.Fail("参数异常", c)
+		return
+	}
+	userInfo := userService.GetInfoByClaims(c)
+
+	openId := userInfo.OpenID
+	if openId == "" {
+		response.Fail("参数异常", c)
+		return
+	}
+	if req.LoginType == 1 {
+		//手机登录
+		if req.Mobile == "" {
+			response.Fail("手机号不能为空,请输入手机号", c)
+			return
+		}
+		req.Mobile = strings.Trim(req.Mobile, " ")
+	} else if req.LoginType == 2 {
+		//邮箱登录
+		if req.Email == "" {
+			response.Fail("邮箱不能为空,请输入邮箱", c)
+			return
+		}
+		if !utils.ValidateEmailFormatat(req.Email) {
+			response.Fail("邮箱格式错误,请重新输入", c)
+			return
+		}
+	} else {
+		response.Fail("无效的登录方式", c)
+		return
+	}
+	token, newUserInfo, err, errMsg := userService.BindWxUser(openId, req.Mobile, req.Email, req.VerifyCode, req.LoginType, req.AreaNum, 1)
+	if err != nil {
+		if errMsg != "" {
+			errMsg = "登录失败"
+		}
+		response.Fail(errMsg, c)
+		return
+	}
+
+	response.OkData("登录成功", userResp.LoginResp{
+		UserID: int(newUserInfo.UserID),
+		Token:  token,
+		Email:  newUserInfo.Email,
+		Mobile: newUserInfo.Mobile,
+	}, c)
+}
+
+//func  GetEmailCode() {
+//	br := new(models.BaseResponse).Init()
+//	defer func() {
+//		this.Data["json"] = br
+//		this.ServeJSON()
+//	}()
+//	email := this.GetString("Email")
+//	if email == "" {
+//		br.Msg = "请输入邮箱地址"
+//		return
+//	}
+//	if !utils.ValidateEmailFormatat(email) {
+//		br.Msg = "邮箱格式错误,请重新输入"
+//		return
+//	}
+//	msgCode := utils.GetRandDigit(4)
+//	content := "尊敬的用户:</br>您好,感谢您使用弘则研究,您正在进行邮箱验证,本次请求的验证码为:" + msgCode + "(为了保障您账号的安全性,请在15分钟内完成验证。)</br>弘则研究团队 </br>2019年05月11日"
+//	title := "弘则研究登陆验证"
+//	//发送邮件
+//	result, err := utils.SendEmailByHz(title, content, email)
+//	if err != nil {
+//		br.Msg = "发送失败"
+//		br.ErrMsg = "发送失败,Err:" + err.Error()
+//		return
+//	}
+//	if result {
+//		item := new(models.MsgCode)
+//		item.OpenId = ""
+//		item.Code = msgCode
+//		item.Mobile = email
+//		item.ExpiredIn = time.Now().Add(15 * time.Minute).Unix()
+//		item.Enabled = 1
+//		item.CreatedTime = time.Now()
+//		err := models.AddMsgCode(item)
+//		if err != nil {
+//			br.Msg = "发送失败"
+//			br.ErrMsg = "发送失败,Err:" + err.Error()
+//			return
+//		}
+//		br.Msg = "发送成功"
+//	} else {
+//		br.Msg = "发送失败"
+//	}
+//	br.Ret = 200
+//	br.Success = true
+//}
+//
+//func GetSmsCode() {
+//	br := new(models.BaseResponse).Init()
+//	defer func() {
+//		this.Data["json"] = br
+//		this.ServeJSON()
+//	}()
+//	mobile := this.GetString("Mobile")
+//	if mobile == "" {
+//		br.Msg = "请输入手机号"
+//		return
+//	}
+//	areaNum := this.GetString("AreaNum")
+//	msgCode := utils.GetRandDigit(4)
+//	var result bool
+//	if areaNum == "86" || areaNum == "" || areaNum == "0" {
+//		result = services.SendSmsCode(mobile, msgCode)
+//	} else {
+//		result = services.SendSmsCodeGj(mobile, msgCode, areaNum)
+//	}
+//	//发送成功
+//	if result {
+//		item := new(models.MsgCode)
+//		item.OpenId = ""
+//		item.Code = msgCode
+//		item.Mobile = mobile
+//		item.ExpiredIn = time.Now().Add(15 * time.Minute).Unix()
+//		item.Enabled = 1
+//		item.CreatedTime = time.Now()
+//		err := models.AddMsgCode(item)
+//		if err != nil {
+//			br.Msg = "发送失败"
+//			br.ErrMsg = "发送失败,Err:" + err.Error()
+//			return
+//		}
+//		br.Msg = "发送成功"
+//	} else {
+//		br.Msg = "发送失败"
+//	}
+//	br.Ret = 200
+//	br.Success = true
+//}

+ 15 - 4
controller/wechat/wechat.go

@@ -3,6 +3,8 @@ package wechat
 import (
 	"github.com/gin-gonic/gin"
 	"hongze/hongze_yb/controller/response"
+	response2 "hongze/hongze_yb/models/response"
+	"hongze/hongze_yb/services/user"
 	"hongze/hongze_yb/services/wechat"
 	"hongze/hongze_yb/services/wx_app"
 )
@@ -35,13 +37,22 @@ func GetUserSession(c *gin.Context) {
 }
 
 func Login(c *gin.Context) {
-	code, _ := c.GetQuery("code")
-	//c.Sho
-	//fmt.Println(c.Request.)
+	//code, _ := c.GetQuery("code")
+	code := c.DefaultQuery("code", "")
 	wxUserInfo, err := wx_app.GetSession(code)
 	if err != nil {
 		response.Fail("获取失败,Err:"+err.Error(), c)
 		return
 	}
-	response.OkData("获取成功", wxUserInfo, c)
+	token, userId, firstLogin, err := user.WxLogin(wx_app.WxPlatform, wxUserInfo)
+	if err != nil {
+		response.Fail("登录失败,Err:"+err.Error(), c)
+		return
+	}
+
+	response.OkData("获取成功", response2.LoginResp{
+		UserId:        userId,
+		FirstLogin:    firstLogin,
+		Authorization: token,
+	}, c)
 }

+ 4 - 0
init_serve/router.go

@@ -3,6 +3,7 @@ package init_serve
 import (
 	"github.com/gin-gonic/gin"
 	"hongze/hongze_yb/global"
+	"hongze/hongze_yb/middleware"
 	"hongze/hongze_yb/routers"
 )
 
@@ -12,6 +13,7 @@ func InitRouter() (r *gin.Engine) {
 	gin.SetMode(global.CONFIG.Serve.RunMode)
 	// 1.创建路由
 	r = gin.Default()
+	r.Use(middleware.Cors())
 
 	// 2.绑定路由规则,执行的函数
 	// gin.Context,封装了request和response
@@ -25,5 +27,7 @@ func InitRouter() (r *gin.Engine) {
 	routers.InitWechat(r)
 	// 活动相关路由
 	routers.InitActivity(r)
+	//用户接口
+	routers.InitUser(r)
 	return
 }

+ 25 - 0
middleware/cors.go

@@ -0,0 +1,25 @@
+package middleware
+
+import (
+	"github.com/gin-gonic/gin"
+	"net/http"
+)
+
+// Cors 处理跨域请求,支持options访问
+func Cors() gin.HandlerFunc {
+	return func(c *gin.Context) {
+		method := c.Request.Method
+		c.Header("Access-Control-Allow-Origin", "*")
+		c.Header("Access-Control-Allow-Headers", "Content-Type,AccessToken,X-CSRF-Token, Authorization, Token,X-Token,X-User-Id\"")
+		c.Header("Access-Control-Allow-Methods", "POST, GET, OPTIONS,DELETE,PUT")
+		c.Header("Access-Control-Expose-Headers", "Content-Length, Access-Control-Allow-Origin, Access-Control-Allow-Headers, Content-Type")
+		c.Header("Access-Control-Allow-Credentials", "true")
+
+		// 放行所有OPTIONS方法
+		if method == "OPTIONS" {
+			c.AbortWithStatus(http.StatusNoContent)
+		}
+		// 处理请求
+		c.Next()
+	}
+}

+ 77 - 0
middleware/token.go

@@ -0,0 +1,77 @@
+package middleware
+
+import (
+	"github.com/gin-gonic/gin"
+	"hongze/hongze_yb/controller/response"
+	"hongze/hongze_yb/models/tables/rddp/session"
+	services "hongze/hongze_yb/services/user"
+	"hongze/hongze_yb/utils"
+)
+
+func Token() gin.HandlerFunc {
+	return func(c *gin.Context) {
+		token := c.Request.Header.Get("Authorization")
+		if token == "" {
+			token = c.GetString("authorization")
+			if token == "" {
+				token = c.GetString("Authorization")
+			}
+		}
+		if token == "" {
+			response.TokenError(nil, "未登录或非法访问", c)
+			c.Abort()
+			return
+		}
+		sessionInfo, err := session.GetTokenByToken(token)
+		if err != nil {
+			if err == utils.ErrNoRow {
+				response.TokenError(nil, "信息已变更,请重新登陆!", c)
+				c.Abort()
+				return
+			}
+			response.TokenError(nil, "网络异常,请稍后重试!", c)
+			c.Abort()
+			return
+		}
+
+		if sessionInfo == nil {
+			response.TokenError(nil, "网络异常,请稍后重试!", c)
+			c.Abort()
+			return
+		}
+
+		var userInfo services.UserInfo
+
+		if sessionInfo.OpenID != "" {
+			tmpUserInfo, tmpErr := services.GetWxUserItemByOpenId(sessionInfo.OpenID)
+			userInfo = tmpUserInfo
+			err = tmpErr
+		} else {
+			response.TokenError(nil, "数据异常!", c)
+			c.Abort()
+			return
+		}
+
+		if err != nil {
+			//用户openid查询出来发现没有绑定用户
+			if err == services.ERR_USER_NOT_BIND {
+				response.TokenError(nil, "信息已变更,请重新登陆!", c)
+				c.Abort()
+				return
+			}
+			//没有找到记录
+			if err == utils.ErrNoRow {
+				response.TokenError(nil, "信息已变更,请重新登陆!", c)
+				c.Abort()
+				return
+			}
+
+			response.TokenError(nil, "网络异常,请稍后重试!", c)
+			c.Abort()
+			return
+		}
+
+		c.Set("userInfo", userInfo)
+		c.Next()
+	}
+}

+ 74 - 0
middleware/token_no_login.go

@@ -0,0 +1,74 @@
+package middleware
+
+import (
+	"fmt"
+	"github.com/gin-gonic/gin"
+	"hongze/hongze_yb/controller/response"
+	"hongze/hongze_yb/models/tables/rddp/session"
+	services "hongze/hongze_yb/services/user"
+	"hongze/hongze_yb/utils"
+)
+
+func TokenNoLogin() gin.HandlerFunc {
+	return func(c *gin.Context) {
+		token := c.Request.Header.Get("Authorization")
+		if token == "" {
+			token = c.GetString("authorization")
+			if token == "" {
+				token = c.GetString("Authorization")
+			}
+		}
+		if token == "" {
+			response.TokenError(nil, "未登录或非法访问", c)
+			c.Abort()
+			return
+		}
+		sessionInfo, err := session.GetTokenByToken(token)
+		if err != nil {
+			if err == utils.ErrNoRow {
+				response.TokenError(nil, "信息已变更,请重新登陆!", c)
+				c.Abort()
+				return
+			}
+			response.TokenError(nil, "网络异常,请稍后重试!", c)
+			c.Abort()
+			return
+		}
+
+		if sessionInfo == nil {
+			response.TokenError(nil, "网络异常,请稍后重试!", c)
+			c.Abort()
+			return
+		}
+
+		var userInfo services.UserInfo
+
+		if sessionInfo.OpenID != "" {
+			tmpUserInfo, tmpErr := services.GetWxUserItemByOpenId(sessionInfo.OpenID)
+			userInfo = tmpUserInfo
+			err = tmpErr
+		} else {
+			response.TokenError(nil, "数据异常!", c)
+			c.Abort()
+			return
+		}
+
+		//如果查询异常,且异常信息不是:用户openid查询出来发现没有绑定用户
+		if err != nil && err != services.ERR_USER_NOT_BIND {
+			//没有找到记录
+			if err == utils.ErrNoRow {
+				response.TokenError(nil, "信息已变更,请重新登陆!", c)
+				c.Abort()
+				return
+			}
+
+			response.TokenError(nil, "网络异常,请稍后重试!", c)
+			c.Abort()
+			return
+		}
+
+		c.Set("userInfo", &userInfo)
+		fmt.Println(userInfo)
+		c.Next()
+	}
+}

+ 9 - 0
models/request/user/user.go

@@ -0,0 +1,9 @@
+package user
+
+type LoginReq struct {
+	LoginType  int    `description:"登录方式:1:手机,2:邮箱" json:"bind_type"`
+	Mobile     string `description:"手机号" json:"mobile"`
+	Email      string `description:"邮箱" json:"email"`
+	AreaNum    int    `description:"国际区号" json:"area_num"`
+	VerifyCode string `description:"短信/邮箱 验证码" json:"verify_code"`
+}

+ 9 - 0
models/response/user/user.go

@@ -0,0 +1,9 @@
+package user
+
+// LoginResp 登录接口返回
+type LoginResp struct {
+	UserID int    `description:"用户id" json:"user_id"`
+	Token  string `description:"登录token" json:"token"`
+	Email  string `description:"邮箱" json:"email"`
+	Mobile string `description:"手机号" json:"mobile"`
+}

+ 8 - 0
models/response/wechat.go

@@ -0,0 +1,8 @@
+package response
+
+// LoginResp 登录接口返回数据
+type LoginResp struct {
+	UserId        int
+	FirstLogin    int
+	Authorization string
+}

+ 11 - 0
models/tables/rddp/db.go

@@ -0,0 +1,11 @@
+package rddp
+
+import (
+	"gorm.io/gorm"
+	"hongze/hongze_yb/global"
+)
+
+// 获取数据库链接
+func GetDb() *gorm.DB {
+	return global.MYSQL["rddp"]
+}

+ 41 - 0
models/tables/rddp/msg_code/msg_code.go

@@ -0,0 +1,41 @@
+package msg_code
+
+import "time"
+
+// MsgCode 验证码列表
+type MsgCode struct {
+	MsgCodeID       int64     `gorm:"primaryKey;column:msg_code_id;type:bigint(20);not null" json:"-"`                // 短信验证码id
+	OpenID          string    `gorm:"index:open_id;column:open_id;type:varchar(32);not null" json:"openId"`           // 用户id
+	Mobile          string    `gorm:"index:mobile;column:mobile;type:varchar(50);not null" json:"mobile"`             // 手机号/邮箱
+	Code            string    `gorm:"column:code;type:varchar(20);not null" json:"code"`                              // 验证码
+	ExpiredIn       int64     `gorm:"column:expired_in;type:bigint(20);not null" json:"expiredIn"`                    // 过期时间
+	Enabled         int8      `gorm:"column:enabled;type:tinyint(1)" json:"enabled"`                                  // 状态
+	CreatedTime     time.Time `gorm:"column:created_time;type:datetime;default:CURRENT_TIMESTAMP" json:"createdTime"` // 创建时间
+	LastUpdatedTime time.Time `gorm:"column:last_updated_time;type:timestamp;not null;default:CURRENT_TIMESTAMP" json:"lastUpdatedTime"`
+}
+
+// TableName get sql table name.获取数据库表名
+func (m *MsgCode) TableName() string {
+	return "msg_code"
+}
+
+// MsgCodeColumns get sql column name.获取数据库列名
+var MsgCodeColumns = struct {
+	MsgCodeID       string
+	OpenID          string
+	Mobile          string
+	Code            string
+	ExpiredIn       string
+	Enabled         string
+	CreatedTime     string
+	LastUpdatedTime string
+}{
+	MsgCodeID:       "msg_code_id",
+	OpenID:          "open_id",
+	Mobile:          "mobile",
+	Code:            "code",
+	ExpiredIn:       "expired_in",
+	Enabled:         "enabled",
+	CreatedTime:     "created_time",
+	LastUpdatedTime: "last_updated_time",
+}

+ 11 - 0
models/tables/rddp/msg_code/query.go

@@ -0,0 +1,11 @@
+package msg_code
+
+import (
+	"hongze/hongze_yb/models/tables/rddp"
+)
+
+// GetMsgCode 根据token获取信息
+func GetMsgCode(mobile, code string) (item *MsgCode, err error) {
+	err = rddp.GetDb().Where("mobile = ? and code = ? and FROM_UNIXTIME(expired_in)>=NOW() ", mobile, code).First(&item).Error
+	return
+}

+ 2 - 2
models/tables/rddp/session/update.go

@@ -11,8 +11,8 @@ func (session *Session) Update(updateCols []string) (err error) {
 }
 
 // UpdateSession 更新session
-func (session *Session) UpdateSession(userId int, expireTime time.Time) (err error) {
-	session.UserID = int64(userId)
+func (session *Session) UpdateSession(userId int64, expireTime time.Time) (err error) {
+	session.UserID = userId
 	session.ExpireTime = expireTime
 	var updateCols = []string{"UserID", "ExpireTime"}
 	err = session.Update(updateCols)

+ 1 - 1
models/tables/wx_token/wx_token.go

@@ -39,7 +39,7 @@ func GetById() (info WxToken, err error) {
 
 // SetAccessToken 设置accessToken
 func SetAccessToken(accessToken string, expiresIn int64) (err error) {
-	err = global.DEFAULT_MYSQL.Model(WxToken{}).Select("access_token").Where("id = 0 ").Updates(WxToken{
+	err = global.DEFAULT_MYSQL.Model(WxToken{}).Select("access_token,expires_in").Where("id = 0 ").Updates(WxToken{
 		AccessToken: accessToken,
 		ExpiresIn:   expiresIn,
 	}).Error

+ 8 - 0
models/tables/wx_user/update.go

@@ -22,3 +22,11 @@ func (wxUser *WxUser) ModifyWxUserRegisterStatus(isRegister, source int8, regist
 
 	return
 }
+
+// ModifyFirstLogin 变更联系人是否第一次登录
+func ModifyFirstLogin(userId uint64) (err error) {
+	err = global.DEFAULT_MYSQL.Model(WxUser{}).Select("FirstLogin").Where("user_id = ? ", userId).Updates(WxUser{
+		FirstLogin: 0,
+	}).Error
+	return
+}

+ 7 - 4
routers/activity.go

@@ -3,10 +3,13 @@ package routers
 import (
 	"github.com/gin-gonic/gin"
 	"hongze/hongze_yb/controller/activity"
+	"hongze/hongze_yb/middleware"
 )
 
-func InitActivity(r *gin.Engine)  {
-	rGroup := r.Group("activity")
+func InitActivity(r *gin.Engine) {
+	rGroup := r.Group("activity").Use(middleware.Token())
 
-	rGroup.GET("/getPageList", activity.GetPageList)
-}
+	{
+		rGroup.GET("/getPageList", activity.GetPageList)
+	}
+}

+ 13 - 0
routers/user.go

@@ -0,0 +1,13 @@
+package routers
+
+import (
+	"github.com/gin-gonic/gin"
+	"hongze/hongze_yb/controller/user"
+	"hongze/hongze_yb/middleware"
+)
+
+func InitUser(r *gin.Engine) {
+	rGroup := r.Group("user").Use(middleware.TokenNoLogin())
+
+	rGroup.POST("/login", user.Login)
+}

+ 1 - 0
routers/wechat.go

@@ -12,6 +12,7 @@ func InitWechat(r *gin.Engine) {
 		rGroup.GET("/qrCode", wechat.GetQrCode)
 		rGroup.GET("/userInfo", wechat.GetUserInfo)
 		rGroup.GET("/session", wechat.GetUserSession)
+		rGroup.GET("/login", wechat.Login)
 
 	}
 }

+ 21 - 135
services/user/user.go

@@ -1,13 +1,11 @@
-package services
+package user
 
 import (
-	"context"
 	"encoding/json"
 	"errors"
-	"fmt"
+	"github.com/gin-gonic/gin"
 	"github.com/silenceper/wechat/v2/miniprogram/auth"
-	"hongze/hongze_yb/global"
-	"hongze/hongze_yb/models/tables/session"
+	"hongze/hongze_yb/models/tables/rddp/session"
 	"hongze/hongze_yb/models/tables/user_record"
 	"hongze/hongze_yb/models/tables/wx_user"
 	"hongze/hongze_yb/models/tables/wx_user_log"
@@ -132,7 +130,7 @@ func GetWxUserItemByUnionId(unionId string, platform int) (userInfo UserInfo, er
 	return
 }
 
-//通过用户 关系表记录  和  用户记录  格式化返回 用户数据
+// formatWxUserAndUserRecord 通过用户 关系表记录  和  用户记录  格式化返回 用户数据
 func formatWxUserAndUserRecord(wxUser *wx_user.WxUser, userRecord *user_record.UserRecord) (userInfo UserInfo) {
 	wxUser.OpenID = userRecord.OpenID
 	wxUser.UnionID = userRecord.UnionID
@@ -147,7 +145,7 @@ func formatWxUserAndUserRecord(wxUser *wx_user.WxUser, userRecord *user_record.U
 	return
 }
 
-//通过用户 用户记录  和  来源平台  格式化返回 用户数据
+// formatWxUser 通过用户 用户记录  和  来源平台  格式化返回 用户数据
 func formatWxUser(wxUser *wx_user.WxUser, platform int) (userInfo UserInfo) {
 	//根据用户id和平台id获取用户关系
 	userRecord, userRecordErr := user_record.GetByUserId(int(wxUser.UserID), platform)
@@ -168,128 +166,10 @@ func formatWxUser(wxUser *wx_user.WxUser, platform int) (userInfo UserInfo) {
 	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) {
+// WxLogin 微信登录
+func WxLogin(wxPlatform int, wxSession auth.ResCode2Session) (token string, userId, firstLogin int, err error) {
 	openId := wxSession.OpenID
 	unionId := wxSession.UnionID
-	if unionId == "" {
-		unionId = userInfo.UnionID
-	}
 
 	//firstLogin==1,强制绑定手机号或者邮箱
 	firstLogin = 1
@@ -337,7 +217,7 @@ QUERY_WX_USER:
 		return
 	}
 
-	if tokenItem == nil || (tokenErr != nil && tokenErr == utils.ErrNoRow) {
+	if tokenErr != nil && tokenErr == utils.ErrNoRow {
 		timeUnix := time.Now().Unix()
 		timeUnixStr := strconv.FormatInt(timeUnix, 10)
 		token = utils.MD5(openId) + utils.MD5(timeUnixStr)
@@ -369,7 +249,7 @@ QUERY_WX_USER:
 		token = tokenItem.AccessToken
 		//如果联系人编号不为空,且联系人编号与session里面的联系人编号不一致的时候,需要做session变更
 		if userId > 0 && tokenItem.UserID != int64(userId) {
-			_ = tokenItem.UpdateSession(userId, time.Now().AddDate(0, 1, 0))
+			_ = tokenItem.UpdateSession(int64(userId), time.Now().AddDate(0, 1, 0))
 		}
 	}
 
@@ -391,13 +271,14 @@ QUERY_WX_USER:
 // 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 {
+	if err == nil {
+		userRecordInfo = find
 		return
 	}
-	if find != nil {
-		userRecordInfo = find
+	if err != utils.ErrNoRow {
 		return
 	}
+
 	userRecordInfo = &user_record.UserRecord{
 		OpenID:         openId,  //用户open_id
 		UnionID:        unionId, //用户union_id
@@ -414,8 +295,13 @@ func AddUserRecord(openId, unionId, nickName, realName, province, city, country,
 		SessionKey:     sessionKey,     //微信小程序会话密钥,最大长度:255
 	}
 	err = userRecordInfo.Create()
-	if err != nil {
-		return
-	}
+	return
+}
+
+// GetInfoByClaims 从Claims中获取用户信息
+func GetInfoByClaims(c *gin.Context) (userInfo *UserInfo) {
+	//获取jwt数据失败
+	claims, _ := c.Get("userInfo")
+	userInfo = claims.(*UserInfo)
 	return
 }

+ 241 - 0
services/user/user_bind.go

@@ -0,0 +1,241 @@
+package user
+
+import (
+	"context"
+	"errors"
+	"fmt"
+	"hongze/hongze_yb/global"
+	"hongze/hongze_yb/models/tables/rddp/msg_code"
+	"hongze/hongze_yb/models/tables/rddp/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"
+)
+
+// BindWxUser 用户注册/绑定
+func BindWxUser(openid, mobile, email, code string, bindType, areaNum, registerPlatform int) (token string, userInfo UserInfo, err error, errMsg string) {
+	switch bindType {
+	case 1: //手机号
+		_, tmpErr := msg_code.GetMsgCode(mobile, code)
+		if tmpErr != nil {
+			if err == utils.ErrNoRow {
+				err = errors.New("校验验证码失败,Err:" + tmpErr.Error())
+				errMsg = "校验验证码失败"
+				return
+			} else {
+				err = errors.New("校验验证码失败,Err:" + tmpErr.Error())
+				errMsg = "验证码错误,请重新输入"
+				return
+			}
+		}
+	case 2: //邮箱
+		_, tmpErr := msg_code.GetMsgCode(email, code)
+		if tmpErr != nil {
+			if err == utils.ErrNoRow {
+				err = errors.New("校验验证码失败,Err:" + tmpErr.Error())
+				errMsg = "校验验证码失败"
+				return
+			} else {
+				err = errors.New("校验验证码失败,Err:" + tmpErr.Error())
+				errMsg = "验证码错误,请重新输入"
+				return
+			}
+		}
+	default:
+		err = errors.New("无效的绑定方式,bindType:" + strconv.Itoa(bindType))
+		errMsg = "无效的绑定方式"
+		return
+	}
+
+	userInfo, err = bindWxUser(openid, mobile, email, areaNum, registerPlatform)
+
+	if err != nil {
+		errMsg = "绑定失败:" + err.Error()
+		return
+	}
+
+	sessionItem, err := session.GetTokenByOpenId(userInfo.OpenID)
+	if err != nil && err != utils.ErrNoRow {
+		errMsg = "登录失败"
+		err = errors.New("登录失败,获取token失败:" + err.Error())
+		return
+	}
+
+	if sessionItem == nil || (err != nil && err == utils.ErrNoRow) {
+		timeUnix := time.Now().Unix()
+		timeUnixStr := strconv.FormatInt(timeUnix, 10)
+		token = utils.MD5(userInfo.OpenID) + utils.MD5(timeUnixStr)
+		//新增session
+		{
+			sessionInfo := &session.Session{
+				OpenID:          userInfo.OpenID,
+				UserID:          int64(userInfo.UserID),
+				CreatedTime:     time.Now(),
+				LastUpdatedTime: time.Now(),
+				ExpireTime:      time.Now().AddDate(0, 1, 0),
+				AccessToken:     token,
+			}
+			tmpErr := sessionInfo.Create()
+			if tmpErr != nil {
+				errMsg = "登录失败"
+				err = errors.New("登录失败,新增用户session信息失败:" + tmpErr.Error())
+				return
+			}
+		}
+	} else {
+		token = sessionItem.AccessToken
+		_ = sessionItem.UpdateSession(int64(userInfo.UserID), time.Now().AddDate(0, 1, 0))
+	}
+
+	tmpErr := wx_user.ModifyFirstLogin(userInfo.UserID)
+	if err != nil {
+		fmt.Println("变更联系人是否第一次登录失败,ERR:", tmpErr)
+		return
+	}
+
+	//新增登录日志
+	//新增登录日志
+	{
+		loginLog := &wx_user_log.WxUserLog{
+			UserID:     int(userInfo.UserID),
+			OpenID:     userInfo.OpenID,
+			UnionID:    userInfo.UnionID,
+			Email:      userInfo.Email,
+			Mobile:     userInfo.Mobile,
+			CreateTime: time.Now(),
+			Handle:     "yb_login",
+			Remark:     token,
+		}
+		go loginLog.Create()
+	}
+	return
+}
+
+// bindWxUser 用户注册/绑定
+func bindWxUser(openid, mobile, email string, areaNum, registerPlatform int) (userInfo UserInfo, err error) {
+	var source int8
+	source = 6 //绑定来源,1:微信端,2:pc网页端,3:查研观向小程序,4:每日咨询
+	if mobile == "" && email == "" {
+		err = errors.New("手机号或邮箱必填一个")
+		return
+	}
+	var bindAccount string
+	var wxUser *wx_user.WxUser
+	needCreateWxUser := true
+
+	//根据手机号获取用户信息
+	if mobile != "" {
+		tmpWxUser, wxUserErr := wx_user.GetByMobile(mobile)
+		if wxUserErr != nil {
+			if wxUserErr != utils.ErrNoRow {
+				err = wxUserErr
+				return
+			}
+		} else {
+			needCreateWxUser = false
+			wxUser = tmpWxUser
+			bindAccount = mobile
+		}
+	}
+	//根据邮箱获取用户信息
+	if needCreateWxUser && email != "" {
+		tmpWxUser, wxUserErr := wx_user.GetByEmail(email)
+		if wxUserErr != nil {
+			if wxUserErr != utils.ErrNoRow {
+				err = wxUserErr
+				return
+			}
+		} else {
+			needCreateWxUser = false
+			wxUser = tmpWxUser
+			bindAccount = email
+		}
+	}
+
+	//查询openid的第三方(微信)信息
+	userRecord, err := user_record.GetByOpenID(openid)
+	if err != nil {
+		return
+	}
+
+	var userId int
+	//如果查询出来的结果是空,那么需要新增用户
+	if needCreateWxUser {
+		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
+		}
+	}
+
+	//格式化用户数据
+	userInfo = formatWxUserAndUserRecord(wxUser, userRecord)
+	return
+}

+ 0 - 1
services/wx_app/wx_app.go

@@ -44,7 +44,6 @@ func GetWxApp() (miniprogram *miniprogram.MiniProgram) {
 func GetSession(code string) (userInfo auth.ResCode2Session, err error) {
 	wechatClient := GetWxApp()
 	authClient := wechatClient.GetAuth()
-	fmt.Println("code:", code)
 	userInfo, err = authClient.Code2Session(code)
 	return
 }