Files
workspace/code/allapp/allapp-go2/biz/handler/auth/login_service.go
T
2026-02-26 17:31:08 +08:00

262 lines
6.0 KiB
Go

// Code generated by hertz generator.
package auth
import (
"allapp/biz/model/auth"
"allapp/conf"
"allapp/db"
"allapp/db/repo"
"allapp/utils/errorx"
"allapp/utils/httpx"
"allapp/utils/idgen"
"allapp/utils/jwtx"
"allapp/utils/response"
"context"
"fmt"
"github.com/cloudwego/hertz/pkg/app"
"github.com/cloudwego/hertz/pkg/protocol/consts"
)
// LoginQq QQ 登录
// @router /auth/login/qq [POST]
func LoginQq(ctx context.Context, c *app.RequestContext) {
var req auth.LoginQqReq
if err := c.BindAndValidate(&req); err != nil {
c.String(consts.StatusBadRequest, err.Error())
return
}
resp := &auth.LoginResp{}
openid := req.Openid
nickname := req.Username
avatar := req.Avatar
// ---------- 通用逻辑:查询用户 ----------
user, err := db.Queries.FindUserByOpenID(ctx, repo.FindUserByOpenIDParams{
Openid: openid,
Type: 1,
})
isExist := true
if err != nil {
if errorx.IsNotFound(err) {
isExist = false
} else {
errorx.AddError(c, err)
return
}
}
if isExist {
if user.Status == 0 {
response.Fail(c).Message("账号已被禁用").Send()
return
}
_ = db.Queries.UpdateUserLastLoginTime(ctx, user.UserID)
token, _ := jwtx.CreateToken(user.UserID)
resp.Token = token
resp.UserId = user.UserID
resp.Username = user.Username
resp.Avatar = user.Avatar
response.Success(c).Data(resp).Send()
return
}
// ---------- 用户不存在 → 注册 ----------
registerUser(ctx, c, openid, nickname, avatar, 1)
}
// LoginWx 微信登录
// @router /auth/login/wx [POST]
func LoginWx(ctx context.Context, c *app.RequestContext) {
var req auth.LoginWxReq
if err := c.BindAndValidate(&req); err != nil {
c.String(consts.StatusBadRequest, err.Error())
return
}
resp := &auth.LoginResp{}
openid := ""
nickname := ""
avatar := ""
accessToken := ""
// 微信登录:code换access_token + openid
status, body, err := httpx.Get(ctx, "https://api.weixin.qq.com/sns/oauth2/access_token", map[string][]any{
"appid": {conf.GetConf().Wx.AppId},
"secret": {conf.GetConf().Wx.AppSecret},
"code": {req.Code},
"grant_type": {"authorization_code"},
})
if err != nil || status != 200 {
errorx.AddError(c, fmt.Errorf("获取 openid 失败: %w, body: %s", err, body))
return
}
accessMap, err := httpx.JSONStringToMap(body)
if err != nil {
errorx.AddError(c, fmt.Errorf("解析 access_token 失败: %w", err))
return
}
accessTokenVal, ok1 := accessMap["access_token"].(string)
openidVal, ok2 := accessMap["openid"].(string)
if !ok1 || !ok2 || accessTokenVal == "" || openidVal == "" {
errorx.AddError(c, fmt.Errorf("access_token 或 openid 不存在, body: %s", body))
return
}
openid = openidVal
accessToken = accessTokenVal
// ---------- 通用逻辑:查询用户 ----------
user, err := db.Queries.FindUserByOpenID(ctx, repo.FindUserByOpenIDParams{
Openid: openid,
Type: 0,
})
// 是否已注册
isExist := true
if err != nil {
if errorx.IsNotFound(err) {
isExist = false
} else {
errorx.AddError(c, err)
return
}
}
if isExist {
if user.Status == 0 {
response.Fail(c).Message("账号已被禁用").Send()
return
}
_ = db.Queries.UpdateUserLastLoginTime(ctx, user.UserID)
token, _ := jwtx.CreateToken(user.UserID)
resp.Token = token
resp.UserId = user.UserID
resp.Username = user.Username
resp.Avatar = user.Avatar
response.Success(c).Data(resp).Send()
return
}
// ---------- 用户不存在 → 注册 ----------
// 用 access_token 获取用户信息
status, body, err = httpx.Get(ctx, "https://api.weixin.qq.com/sns/userinfo", map[string][]any{
"access_token": {accessToken},
"openid": {openid},
})
if err != nil || status != 200 {
errorx.AddError(c, fmt.Errorf("获取用户信息失败: %w, body: %s", err, body))
return
}
userMap, err := httpx.JSONStringToMap(body)
if err != nil {
errorx.AddError(c, fmt.Errorf("解析用户信息失败: %w", err))
return
}
nickname, _ = userMap["nickname"].(string)
avatar, _ = userMap["headimgurl"].(string)
registerUser(ctx, c, openid, nickname, avatar, 0) // 0 = 微信
}
// registerUser 注册通用函数
func registerUser(ctx context.Context, c *app.RequestContext, openid, nickname, avatar string, loginType int32) {
userId := idgen.NextId()
if nickname == "" {
nickname = fmt.Sprintf("用户_%d", userId)
}
if avatar == "" {
avatar = "https://default-avatar-url.com/default.png"
}
err := db.WithTx(ctx, func(q *repo.Queries) error {
// 插入用户
if err := q.InsertUser(ctx, repo.InsertUserParams{
ID: userId,
Username: nickname,
Avatar: avatar,
Status: 1,
}); err != nil {
return err
}
// 插入第三方登录信息
if err := q.InsertUserOAuth(ctx, repo.InsertUserOAuthParams{
ID: idgen.NextId(),
UserID: userId,
Type: loginType,
Openid: openid,
}); err != nil {
return err
}
// 初始化记账分类
if err := initMoneyCategoryTx(ctx, q, userId); err != nil {
return fmt.Errorf("初始化记账分类失败: %w", err)
}
return nil
})
if err != nil {
errorx.AddError(c, err)
return
}
token, _ := jwtx.CreateToken(userId)
resp := &auth.LoginResp{
Token: token,
UserId: userId,
Username: nickname,
Avatar: avatar,
}
response.Success(c).Data(resp).Send()
}
func initMoneyCategoryTx(ctx context.Context, q *repo.Queries, userId int64) error {
sysCategories, err := q.ListMoneySysCategory(ctx)
if err != nil {
return err
}
if len(sysCategories) == 0 {
return nil
}
userCategories := make([]repo.BatchInsertMoneyUserCategoriesParams, 0, len(sysCategories))
for _, sysCat := range sysCategories {
userCategories = append(userCategories, repo.BatchInsertMoneyUserCategoriesParams{
ID: idgen.NextId(),
UserID: userId,
Name: sysCat.Name,
Icon: sysCat.Icon,
Type: sysCat.Type,
SortNumber: sysCat.SortNumber,
})
}
if err := q.DeleteMoneyCategoryByUserId(ctx, userId); err != nil {
return err
}
if _, err := q.BatchInsertMoneyUserCategories(ctx, userCategories); err != nil {
return err
}
return nil
}