修改扫码接口,实现小妖自动登录后绑定微信

This commit is contained in:
2025-07-10 10:12:39 +08:00
parent 413decab8f
commit c1943e9b7e
3 changed files with 93 additions and 58 deletions

View File

@ -29,8 +29,7 @@ func (c *ControllerV1) WeChatEvent(ctx context.Context, req *v1.WeChatEventReq)
switch req.Event { switch req.Event {
case "subscribe": case "subscribe":
key := strings.TrimPrefix(req.EventKey, "qrscene_") key := strings.TrimPrefix(req.EventKey, "qrscene_")
split := strings.Split(req.EventKey, "_") out, err := service.User().Login(ctx, &model.UserLoginIn{OpenId: unionid, SceneId: key})
out, err := service.User().Login(ctx, &model.UserLoginIn{OpenId: unionid, StoreCode: split[0]})
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -39,8 +38,7 @@ func (c *ControllerV1) WeChatEvent(ctx context.Context, req *v1.WeChatEventReq)
} }
return nil, nil return nil, nil
case "SCAN": case "SCAN":
split := strings.Split(req.EventKey, "_") out, err := service.User().Login(ctx, &model.UserLoginIn{OpenId: unionid, SceneId: req.EventKey})
out, err := service.User().Login(ctx, &model.UserLoginIn{OpenId: unionid, StoreCode: split[0]})
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@ -6,6 +6,7 @@ import (
"github.com/gogf/gf/v2/frame/g" "github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/os/glog" "github.com/gogf/gf/v2/os/glog"
"github.com/gogf/gf/v2/os/gtime" "github.com/gogf/gf/v2/os/gtime"
"github.com/gogf/gf/v2/util/gconv"
"github.com/gogf/gf/v2/util/grand" "github.com/gogf/gf/v2/util/grand"
"server/internal/consts" "server/internal/consts"
"server/internal/dao" "server/internal/dao"
@ -19,6 +20,7 @@ import (
"server/utility/gamelife" "server/utility/gamelife"
"server/utility/jwt" "server/utility/jwt"
"server/utility/sms" "server/utility/sms"
"strings"
) )
type sUser struct{} type sUser struct{}
@ -53,34 +55,39 @@ func New() service.IUser {
} }
func (s *sUser) Login(ctx context.Context, in *model.UserLoginIn) (out *model.UserLoginOut, err error) { func (s *sUser) Login(ctx context.Context, in *model.UserLoginIn) (out *model.UserLoginOut, err error) {
// Fetch role information
value, err := dao.Roles.Ctx(ctx).Where(do.Roles{Code: consts.UserRoleCode}).Fields(dao.Roles.Columns().Code, dao.Roles.Columns().Id).One() value, err := dao.Roles.Ctx(ctx).Where(do.Roles{Code: consts.UserRoleCode}).Fields(dao.Roles.Columns().Code, dao.Roles.Columns().Id).One()
if err != nil { if err != nil {
return nil, ecode.Fail.Sub("查找角色失败") return nil, ecode.Fail.Sub("查找角色失败")
} }
// 根据 OpenId 查找用户
split := strings.Split(in.SceneId, "_")
if len(split) < 3 {
return nil, ecode.Fail.Sub("SceneId格式错误")
}
storeId := gconv.Int64(split[0])
var xyUserId string
var userId int64
if split[1] == "0" {
// Case 1: split[1] == "0", use in.OpenId to find or create user
exist, err := dao.Users.Ctx(ctx).Where(do.Users{WxOpenId: in.OpenId}).Exist() exist, err := dao.Users.Ctx(ctx).Where(do.Users{WxOpenId: in.OpenId}).Exist()
if err != nil { if err != nil {
return nil, ecode.Fail.Sub("查找用户失败") return nil, ecode.Fail.Sub("查找用户失败")
} }
var userId int64
v, err := dao.Stores.Ctx(ctx).Where(do.Stores{StoreCode: in.StoreCode}).Fields(dao.Stores.Columns().Id).Value()
if err != nil {
return nil, ecode.Fail.Sub("查找门店失败")
}
if !exist { if !exist {
// 用户不存在,创建新用户 // User does not exist, create new user
// 生成 username: qy_ + 8位随机字母数字
var username string var username string
for { for {
randomStr := grand.Str("abcdefghijklmnopqrstuvwxyz0123456789", 8) randomStr := grand.Str("abcdefghijklmnopqrstuvwxyz0123456789", 8)
username = "qy_" + randomStr username = "qy_" + randomStr
// 检查 username 是否唯一
count, err := dao.Users.Ctx(ctx).Where(do.Users{Username: username}).Count() count, err := dao.Users.Ctx(ctx).Where(do.Users{Username: username}).Count()
if err != nil { if err != nil {
return nil, ecode.Fail.Sub("检查用户名失败") return nil, ecode.Fail.Sub("检查用户名失败")
} }
if count == 0 { if count == 0 {
break // username 唯一,退出循环 break // Username is unique
} }
} }
password, err := encrypt.EncryptPassword(consts.DefaultPassword) password, err := encrypt.EncryptPassword(consts.DefaultPassword)
@ -98,7 +105,7 @@ func (s *sUser) Login(ctx context.Context, in *model.UserLoginIn) (out *model.Us
WxPopenId: utility.GenerateUserID("WX"), WxPopenId: utility.GenerateUserID("WX"),
QqPopenId: utility.GenerateUserID("QQ"), QqPopenId: utility.GenerateUserID("QQ"),
RoleId: value[dao.Roles.Columns().Id].Int64(), RoleId: value[dao.Roles.Columns().Id].Int64(),
LastLoginStoreId: v.Int64(), LastLoginStoreId: storeId,
} }
result, err := dao.Users.Ctx(ctx).Insert(user) result, err := dao.Users.Ctx(ctx).Insert(user)
if err != nil { if err != nil {
@ -109,18 +116,48 @@ func (s *sUser) Login(ctx context.Context, in *model.UserLoginIn) (out *model.Us
return nil, ecode.Fail.Sub("获取用户ID失败") return nil, ecode.Fail.Sub("获取用户ID失败")
} }
} else { } else {
// 用户存在,更新最后登录时间 // User exists, update last login store ID and time
var user entity.Users var user entity.Users
if err := dao.Users.Ctx(ctx).Where(do.Users{WxOpenId: in.OpenId}).Scan(&user); err != nil { if err := dao.Users.Ctx(ctx).Where(do.Users{WxOpenId: in.OpenId}).Scan(&user); err != nil {
return nil, ecode.Fail.Sub("查找用户失败") return nil, ecode.Fail.Sub("查找用户失败")
} }
userId = user.Id userId = user.Id
if _, err := dao.Users.Ctx(ctx).Where(do.Users{Id: userId}).Update(do.Users{LastLoginAt: gtime.Now(), LastLoginStoreId: v.Int64()}); err != nil { if _, err := dao.Users.Ctx(ctx).Where(do.Users{Id: userId}).Update(do.Users{
LastLoginAt: gtime.Now(),
LastLoginStoreId: storeId,
}); err != nil {
return nil, ecode.Fail.Sub("更新登录时间失败") return nil, ecode.Fail.Sub("更新登录时间失败")
} }
} }
} else if split[1] == "1" {
// Case 2: split[1] == "1", use xyUserId to find user and bind in.OpenId
xyUserId = split[2]
var user entity.Users
exist, err := dao.Users.Ctx(ctx).Where(do.Users{XyUserId: xyUserId}).Exist()
if err != nil {
return nil, ecode.Fail.Sub("查找用户失败")
}
if !exist {
return nil, ecode.Fail.Sub("参数错误:用户不存在")
}
// 生成 token // User exists, bind in.OpenId and update last login store ID
if err := dao.Users.Ctx(ctx).Where(do.Users{XyUserId: xyUserId}).Scan(&user); err != nil {
return nil, ecode.Fail.Sub("查找用户失败")
}
userId = user.Id
if _, err := dao.Users.Ctx(ctx).Where(do.Users{Id: userId}).Update(do.Users{
WxOpenId: in.OpenId,
LastLoginAt: gtime.Now(),
LastLoginStoreId: storeId,
}); err != nil {
return nil, ecode.Fail.Sub("绑定OpenId失败")
}
} else {
return nil, ecode.Fail.Sub("无效的SceneId类型")
}
// Generate token
token, err := jwt.GenerateToken(&jwt.TokenIn{ token, err := jwt.GenerateToken(&jwt.TokenIn{
UserId: userId, UserId: userId,
Role: value[dao.Roles.Columns().Code].String(), Role: value[dao.Roles.Columns().Code].String(),
@ -132,7 +169,7 @@ func (s *sUser) Login(ctx context.Context, in *model.UserLoginIn) (out *model.Us
out = &model.UserLoginOut{ out = &model.UserLoginOut{
Token: token, Token: token,
} }
return return out, nil
} }
func (s *sUser) WeChatLogin(ctx context.Context, in *model.WeChatLogin) (out *model.WeChatLoginOut, err error) { func (s *sUser) WeChatLogin(ctx context.Context, in *model.WeChatLogin) (out *model.WeChatLoginOut, err error) {
return return

View File

@ -60,7 +60,7 @@ type LoginCache struct {
type UserLoginIn struct { type UserLoginIn struct {
OpenId string OpenId string
StoreCode string // 门店编码,登录时根据门店编码查询,填写最近一次登录门店 id SceneId string
} }
type WeChatLogin struct { type WeChatLogin struct {
UUID string // 使用的是微信的唯一 id而不是openid保证微信服务号小程序绑定的系统用户为同一个 UUID string // 使用的是微信的唯一 id而不是openid保证微信服务号小程序绑定的系统用户为同一个