From e8302dd3d765721949b2c603c90dda545cae35ad Mon Sep 17 00:00:00 2001 From: mayiming <1627832236@qq.com> Date: Tue, 23 Sep 2025 18:39:01 +0800 Subject: [PATCH] =?UTF-8?q?=E6=9B=B4=E6=96=B0=E7=94=A8=E6=88=B7=E7=99=BB?= =?UTF-8?q?=E5=BD=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- config.yaml | 2 +- controllers/user/userLogin.go | 280 ++++++++++++++++++---------------- 2 files changed, 150 insertions(+), 132 deletions(-) diff --git a/config.yaml b/config.yaml index 603b842..9475799 100644 --- a/config.yaml +++ b/config.yaml @@ -7,7 +7,7 @@ database: params: "charset=utf8mb4&parseTime=True&loc=Local" redis: host: "localhost" - port: 30079 + port: 6379 username: "default" password: "" jwtsecret: "clka1af83af15vhyt8s652avre" diff --git a/controllers/user/userLogin.go b/controllers/user/userLogin.go index 49e72f2..49a8030 100644 --- a/controllers/user/userLogin.go +++ b/controllers/user/userLogin.go @@ -4,148 +4,147 @@ import ( "crypto/aes" "crypto/cipher" "encoding/base64" - "github.com/gin-gonic/gin" + "encoding/json" + "errors" + "fmt" "math/rand" + "net/http" + "net/url" "strconv" "time" + "toutoukan/init/config" + "toutoukan/init/databaseInit" + "toutoukan/model/usermodel" + "toutoukan/utill/jwt" + + "github.com/gin-gonic/gin" + "gorm.io/gorm" ) const wxLoginURL = "https://api.weixin.qq.com/sns/jscode2session" func UserLogin(c *gin.Context) { + fmt.Println("Request Body:", c.Request.Body) + var req usermodel.WxLoginM + if err := c.ShouldBindJSON(&req); err != nil { + c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) + } + fmt.Println("req:123") + fmt.Println(req.EncryptedData) + fmt.Println(req.Code) + fmt.Println(req.Iv) + fmt.Println("使用的appid:", config.Conf.WxID) + fmt.Println("使用的secret:", config.Conf.Wxsecret) + //----------------发送验证请求 + params := url.Values{} + params.Add("appid", config.Conf.WxID) + params.Add("secret", config.Conf.Wxsecret) + params.Add("js_code", req.Code) + params.Add("grant_type", "authorization_code") + requestURL := fmt.Sprintf("%s?%s", wxLoginURL, params.Encode()) + fmt.Println("微信接口请求URL:", requestURL) + resp, err := http.Get(fmt.Sprintf("%s?%s", wxLoginURL, params.Encode())) + if err != nil { + c.JSON(http.StatusInternalServerError, gin.H{"error": "调用微信登录接口失败: " + err.Error()}) + return + } + fmt.Println("微信登录返回结果:", resp.Body) + defer resp.Body.Close() + + var wxResp usermodel.WxLoginResponse + if err := json.NewDecoder(resp.Body).Decode(&wxResp); err != nil { + c.JSON(http.StatusInternalServerError, gin.H{"error": "解析微信登录响应失败: " + err.Error(), "code": "10026"}) + return + } + + if wxResp.ErrCode != 0 { + c.JSON(http.StatusBadRequest, gin.H{ + "error": fmt.Sprintf("微信登录失败: %s (错误码: %d)", wxResp.ErrCode, wxResp.ErrMsg), + "code": "10027", + }) + return + } + + phoneData, err := decryptWxData(wxResp.SessionKey, req.EncryptedData, req.Iv) + if err != nil { + c.JSON(http.StatusInternalServerError, gin.H{"error": "解密失败: " + err.Error()}) + return + } + + var phoneInfo usermodel.WxPhoneInfo + if err := json.Unmarshal(phoneData, &phoneInfo); err != nil { + c.JSON(http.StatusInternalServerError, gin.H{"error": "解析手机号失败"}) + return + } + + if phoneInfo.Watermark.AppID != config.Conf.WxID { + c.JSON(http.StatusForbidden, gin.H{"error": "数据水印验证失败"}) + return + } + + fmt.Println("用户手机号为:", phoneInfo.PhoneNumber) + + openid := wxResp.OpenID + + // 业务逻辑实现 + var user UserInfo + var username string + // 查找用户是否存在 + result := databaseInit.UserDB.Where("uid = ?", openid).First(&user) + + if result.Error != nil { + if errors.Is(result.Error, gorm.ErrRecordNotFound) { + // 用户不存在,创建新用户 + username := generateUsername() + now := time.Now() + newUser := UserInfo{ + Uid: openid, + Gender: 2, // 这里假设 gender 传 2,可根据实际需求修改 + CreatedTime: now, + UpdatedTime: now, + Username: username, + Telephone: phoneInfo.PhoneNumber, + // 若还有 password、avatar_url、birthdate、bio 等字段需要赋值,可在此补充 + // 比如 Password: "默认密码"(实际中密码应加密存储),AvatarUrl: "默认头像地址" 等 + } + + if err := databaseInit.UserDB.Create(&newUser).Error; err != nil { + c.JSON(http.StatusInternalServerError, gin.H{ + "error": "插入新用户失败: " + err.Error(), + "code": "10029", + }) + return + } + username = newUser.Username + } else { + // 数据库查询错误 + c.JSON(http.StatusInternalServerError, gin.H{ + "error": "查询用户存在性失败: " + result.Error.Error(), + "code": "10029", + }) + return + } + } else { + // 用户已存在,获取用户名 + username = user.Username + } + + token, err := jwt.GenerateJWTAndStore(openid) + if err != nil { + c.JSON(500, gin.H{"error": "生成令牌失败", "code": "10036"}) + return + } + + c.JSON(http.StatusOK, gin.H{"result": "success", "error": nil, "code": "20001", "token": token, + "userinfo": map[string]string{ + "username": username, + "uid": openid, + "telephone": phoneInfo.PhoneNumber, + }, + }) } -//func UserLogin(c *gin.Context) { -// fmt.Println("Request Body:", c.Request.Body) -// var req usermodel.WxLoginM -// if err := c.ShouldBindJSON(&req); err != nil { -// c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) -// } -// fmt.Println("req:123") -// fmt.Println(req.EncryptedData) -// fmt.Println(req.Code) -// fmt.Println(req.Iv) -// fmt.Println("使用的appid:", config.Conf.WxID) -// fmt.Println("使用的secret:", config.Conf.Wxsecret) -// //----------------发送验证请求 -// params := url.Values{} -// params.Add("appid", config.Conf.WxID) -// params.Add("secret", config.Conf.Wxsecret) -// params.Add("js_code", req.Code) -// params.Add("grant_type", "authorization_code") -// requestURL := fmt.Sprintf("%s?%s", wxLoginURL, params.Encode()) -// fmt.Println("微信接口请求URL:", requestURL) -// -// resp, err := http.Get(fmt.Sprintf("%s?%s", wxLoginURL, params.Encode())) -// if err != nil { -// c.JSON(http.StatusInternalServerError, gin.H{"error": "调用微信登录接口失败: " + err.Error()}) -// return -// } -// fmt.Println("微信登录返回结果:", resp.Body) -// defer resp.Body.Close() -// -// var wxResp usermodel.WxLoginResponse -// if err := json.NewDecoder(resp.Body).Decode(&wxResp); err != nil { -// c.JSON(http.StatusInternalServerError, gin.H{"error": "解析微信登录响应失败: " + err.Error(), "code": "10026"}) -// return -// } -// -// if wxResp.ErrCode != 0 { -// c.JSON(http.StatusBadRequest, gin.H{ -// "error": fmt.Sprintf("微信登录失败: %s (错误码: %d)", wxResp.ErrCode, wxResp.ErrMsg), -// "code": "10027", -// }) -// return -// } -// -// phoneData, err := decryptWxData(wxResp.SessionKey, req.EncryptedData, req.Iv) -// if err != nil { -// c.JSON(http.StatusInternalServerError, gin.H{"error": "解密失败: " + err.Error()}) -// return -// } -// -// var phoneInfo usermodel.WxPhoneInfo -// if err := json.Unmarshal(phoneData, &phoneInfo); err != nil { -// c.JSON(http.StatusInternalServerError, gin.H{"error": "解析手机号失败"}) -// return -// } -// -// if phoneInfo.Watermark.AppID != config.Conf.WxID { -// c.JSON(http.StatusForbidden, gin.H{"error": "数据水印验证失败"}) -// return -// } -// -// fmt.Println("用户手机号为:", phoneInfo.PhoneNumber) -// -// openid := wxResp.OpenID -// ctx := c.Request.Context() -// -// var username string -// -// var exists bool -// query := "SELECT EXISTS(SELECT 1 FROM user_info WHERE uid = ? LIMIT 1)" -// err = databaseInit.UserDB.QueryRowContext(ctx, query, openid).Scan(&exists) -// if err != nil { -// c.JSON(http.StatusInternalServerError, gin.H{ -// "error": "查询用户存在性失败: " + err.Error(), -// "code": "10029", -// }) -// return -// } -// -// if !exists { -// username = generateUsername() -// now := time.Now() -// insertSQL := ` -// INSERT INTO user_info ( -// uid, gender,createdtime, updatedtime,username,telephone -// ) VALUES (?, ?, ?,?,?,?) -// ` -// _, err := databaseInit.UserDB.ExecContext( -// ctx, -// insertSQL, -// openid, // uid(使用微信 openid) -// 2, -// now, -// now, -// username, -// phoneInfo.PhoneNumber, -// ) -// if err != nil { -// c.JSON(http.StatusInternalServerError, gin.H{ -// "error": "插入新用户失败: " + err.Error(), -// "code": "10029", -// }) -// return -// } -// } else { -// queryUser := "SELECT username FROM user_info WHERE uid = ? LIMIT 1" -// err = databaseInit.UserDB.QueryRowContext(ctx, queryUser, openid).Scan(&username) -// if err != nil { -// c.JSON(http.StatusInternalServerError, gin.H{ -// "error": "查询用户信息失败: " + err.Error(), -// "code": "10030", -// }) -// return -// } -// } -// -// token, err := utill.GenerateJWTAndStore(openid) -// if err != nil { -// c.JSON(500, gin.H{"error": "生成令牌失败", "code": "10036"}) -// return -// } -// -// c.JSON(http.StatusOK, gin.H{"result": "success", "error": nil, "code": "20001", "token": token, -// "userinfo": map[string]string{ -// "username": username, -// "uid": openid, -// "telephone": phoneInfo.PhoneNumber, -// }, -// }) -//} - func generateUsername() string { rand.Seed(time.Now().UnixNano()) randomNum := 10000000 + rand.Intn(90000000) @@ -178,3 +177,22 @@ func pkcs7Unpad(data []byte) []byte { } return data[:len(data)-padding] } + +// 定义与表结构对应的用户模型 +type UserInfo struct { + Uid string `gorm:"column:uid;primaryKey"` + Telephone string `gorm:"column:telephone"` + Password string `gorm:"column:password"` + AvatarUrl string `gorm:"column:avatar_url"` + Gender int `gorm:"column:gender"` + Birthdate time.Time `gorm:"column:birthdate;type:datetime"` + CreatedTime time.Time `gorm:"column:createdtime;type:datetime"` + UpdatedTime time.Time `gorm:"column:updatedtime;type:datetime"` + Bio string `gorm:"column:bio"` + Username string `gorm:"column:username"` +} + +// 自定义表名 +func (UserInfo) TableName() string { + return "user_info" +}