148 lines
3.9 KiB
Go
148 lines
3.9 KiB
Go
|
package wx
|
|||
|
|
|||
|
import (
|
|||
|
"encoding/json"
|
|||
|
"fmt"
|
|||
|
"io"
|
|||
|
"mini_server/internal/config"
|
|||
|
"mini_server/internal/dao"
|
|||
|
"mini_server/internal/middleware/jwt"
|
|||
|
"mini_server/internal/server/help"
|
|||
|
"mini_server/internal/server/httpreply"
|
|||
|
"mini_server/internal/server/user"
|
|||
|
"net/http"
|
|||
|
|
|||
|
"github.com/gin-gonic/gin"
|
|||
|
"github.com/sirupsen/logrus"
|
|||
|
)
|
|||
|
|
|||
|
type LoginRequest struct {
|
|||
|
Code string `json:"code" binding:"min=1"` // 临时会话登录code
|
|||
|
}
|
|||
|
|
|||
|
type LoginReply struct {
|
|||
|
Token string `json:"token"` // 返回登录成功的jwt token
|
|||
|
UserInfo *user.UserInfo `json:"user_info"`
|
|||
|
}
|
|||
|
|
|||
|
// 微信服务器,返回的数据结构
|
|||
|
type WxHttpReply struct {
|
|||
|
Errcode int32 `json:"errcode"` // 错误码
|
|||
|
Errmsg string `json:"errmsg"` // 错误信息
|
|||
|
OpenId string `json:"openid"` // 用户唯一标识
|
|||
|
// Unionid string `json:"unionid"` // 用户在开放平台的唯一标识符,在满足 UnionID 下发条件的情况下会返回,详见微信 UnionID
|
|||
|
SessionKey string `json:"session_key"` // 会话密钥
|
|||
|
}
|
|||
|
|
|||
|
func WxLogin(c *gin.Context) {
|
|||
|
reply := httpreply.NewDefaultReplyData()
|
|||
|
defer httpreply.Reply(c, reply)
|
|||
|
|
|||
|
//解析请求参数
|
|||
|
var request LoginRequest
|
|||
|
if err := c.ShouldBindJSON(&request); err != nil {
|
|||
|
reply.Status = http.StatusBadRequest
|
|||
|
reply.Message = fmt.Sprintf("invalid json data, err:%v", err)
|
|||
|
return
|
|||
|
}
|
|||
|
logrus.Tracef("微信登录,请求参数:%v", request)
|
|||
|
|
|||
|
// 从微信查询openId
|
|||
|
openId, err := get_wx_login_open_id(request.Code)
|
|||
|
if err != nil {
|
|||
|
logrus.Errorf("请求微信获取OpenId失败,err:%v", err)
|
|||
|
reply.Status = http.StatusServiceUnavailable
|
|||
|
reply.Message = "第三方服务错误"
|
|||
|
return
|
|||
|
}
|
|||
|
|
|||
|
// 首先查询,是否存在
|
|||
|
data, err := dao.User_WX_Query(openId)
|
|||
|
if err != nil {
|
|||
|
logrus.Errorf("微信登录,数据库查询失败,err:%v", err)
|
|||
|
reply.Status = http.StatusInternalServerError
|
|||
|
reply.Message = "用户查询失败"
|
|||
|
return
|
|||
|
}
|
|||
|
|
|||
|
if data == nil { // 用户不存在,则需要添加创建
|
|||
|
|
|||
|
default_wx_username, err := get_default_wx_username()
|
|||
|
if err != nil {
|
|||
|
logrus.Errorf("生成微信默认用户名失败,err:%v", err)
|
|||
|
reply.Status = http.StatusInternalServerError
|
|||
|
reply.Message = "生成微信默认用户名失败"
|
|||
|
return
|
|||
|
}
|
|||
|
|
|||
|
data = &dao.User{
|
|||
|
AvatarId: "",
|
|||
|
OpenId: openId,
|
|||
|
Username: default_wx_username, // 默认名称
|
|||
|
Persona: "{}",
|
|||
|
Tags: "{}",
|
|||
|
}
|
|||
|
|
|||
|
if _, err = dao.User_WX_Insert(data); err != nil {
|
|||
|
logrus.Errorf("微信登录,数据库用户添加失败,err:%v", err)
|
|||
|
reply.Status = http.StatusInternalServerError
|
|||
|
reply.Message = "用户添加失败"
|
|||
|
return
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
// 生成token
|
|||
|
token, err := jwt.CreateToken(data)
|
|||
|
if err != nil {
|
|||
|
logrus.Errorf("微信登录,生成token失败,err:%v", err)
|
|||
|
reply.Status = http.StatusInternalServerError
|
|||
|
reply.Message = "token生成失败"
|
|||
|
return
|
|||
|
}
|
|||
|
|
|||
|
// 返回用户信息
|
|||
|
var info user.UserInfo
|
|||
|
user.Copy_User_Info(data, &info)
|
|||
|
loginReply := LoginReply{
|
|||
|
Token: token,
|
|||
|
UserInfo: &info,
|
|||
|
}
|
|||
|
reply.Data = &loginReply
|
|||
|
logrus.Tracef("微信登录成功,应答:%v", reply)
|
|||
|
}
|
|||
|
|
|||
|
func get_wx_login_open_id(code string) (string, error) {
|
|||
|
//接口请求url拼接
|
|||
|
url := config.WeiXin.AppUrl(code)
|
|||
|
|
|||
|
// 转发请求到微信接口
|
|||
|
resp, err := http.Get(url)
|
|||
|
if err != nil {
|
|||
|
return "", fmt.Errorf("请求微信登录接口失败,err:%v", err)
|
|||
|
}
|
|||
|
defer resp.Body.Close()
|
|||
|
|
|||
|
// 读取数据
|
|||
|
body, err := io.ReadAll(resp.Body)
|
|||
|
if err != nil {
|
|||
|
return "", fmt.Errorf("读取微信登录应答数据失败,err:%v", err)
|
|||
|
}
|
|||
|
|
|||
|
// 解码数据并赋值给返回的respData
|
|||
|
respData := new(WxHttpReply)
|
|||
|
json.Unmarshal(body, &respData)
|
|||
|
|
|||
|
openId := respData.OpenId
|
|||
|
// 检测openid是否为空
|
|||
|
if openId == "" {
|
|||
|
return "", fmt.Errorf("读取微信登录应答数据openId为空")
|
|||
|
}
|
|||
|
return openId, nil
|
|||
|
}
|
|||
|
|
|||
|
// 注册时返回随机名称
|
|||
|
func get_default_wx_username() (string, error) {
|
|||
|
id := help.GetUniqueIdEachSecond()
|
|||
|
return "微信用户" + id, nil
|
|||
|
}
|