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 }