手机号适配双端

This commit is contained in:
liangzai 2025-06-18 16:31:32 +08:00
parent a738c711de
commit 301a80447d
39 changed files with 1423 additions and 1348 deletions

View File

@ -35,7 +35,6 @@ type ProductConfig {
PriceRangeMin float64 `json:"price_range_min"` PriceRangeMin float64 `json:"price_range_min"`
PriceRangeMax float64 `json:"price_range_max"` PriceRangeMax float64 `json:"price_range_max"`
} }
@server ( @server (
prefix: api/v1/agent prefix: api/v1/agent
group: agent group: agent
@ -46,6 +45,16 @@ service main {
@handler GetAgentInfo @handler GetAgentInfo
get /info returns (AgentInfoResp) get /info returns (AgentInfoResp)
@handler GetAgentRevenueInfo
get /revenue (GetAgentRevenueInfoReq) returns (GetAgentRevenueInfoResp)
}
@server (
prefix: api/v1/agent
group: agent
jwt: JwtAuth
middleware: UserAuthInterceptor
)
service main {
// 查询代理申请状态 // 查询代理申请状态
@handler GetAgentAuditStatus @handler GetAgentAuditStatus
get /audit/status returns (AgentAuditStatusResp) get /audit/status returns (AgentAuditStatusResp)
@ -169,6 +178,8 @@ type (
prefix: api/v1/agent prefix: api/v1/agent
group: agent group: agent
jwt: JwtAuth jwt: JwtAuth
middleware: UserAuthInterceptor
) )
service main { service main {
@handler GetAgentMembershipProductConfig @handler GetAgentMembershipProductConfig
@ -204,11 +215,10 @@ type (
prefix: api/v1/agent prefix: api/v1/agent
group: agent group: agent
jwt: JwtAuth jwt: JwtAuth
middleware: UserAuthInterceptor
) )
service main { service main {
@handler GetAgentRevenueInfo
get /revenue (GetAgentRevenueInfoReq) returns (GetAgentRevenueInfoResp)
@handler GetAgentCommission @handler GetAgentCommission
get /commission (GetCommissionReq) returns (GetCommissionResp) get /commission (GetCommissionReq) returns (GetCommissionResp)
@ -327,6 +337,8 @@ type (
@server ( @server (
prefix: api/v1/agent prefix: api/v1/agent
group: agent group: agent
middleware: AuthInterceptor
) )
service main { service main {
// 提交代理申请 // 提交代理申请

View File

@ -30,7 +30,8 @@ service main {
prefix: api/v1 prefix: api/v1
group: pay group: pay
jwt: JwtAuth jwt: JwtAuth
middleware: SourceInterceptor middleware: UserAuthInterceptor
) )
service main { service main {
// 支付 // 支付

View File

@ -26,6 +26,8 @@ type Product {
prefix: api/v1/product prefix: api/v1/product
group: product group: product
jwt: JwtAuth jwt: JwtAuth
middleware: UserAuthInterceptor
) )
service main { service main {
@handler GetProductByID @handler GetProductByID

View File

@ -70,6 +70,8 @@ type (
prefix: api/v1 prefix: api/v1
group: query group: query
jwt: JwtAuth jwt: JwtAuth
middleware: UserAuthInterceptor
) )
service main { service main {
@doc "query service" @doc "query service"
@ -81,6 +83,8 @@ service main {
prefix: api/v1 prefix: api/v1
group: query group: query
jwt: JwtAuth jwt: JwtAuth
middleware: UserAuthInterceptor
) )
service main { service main {
@doc "获取查询临时订单" @doc "获取查询临时订单"

View File

@ -14,6 +14,7 @@ type User {
Id int64 `json:"id"` Id int64 `json:"id"`
Mobile string `json:"mobile"` Mobile string `json:"mobile"`
NickName string `json:"nickName"` NickName string `json:"nickName"`
UserType int64 `json:"userType"`
} }
//no need login //no need login
@ -22,22 +23,10 @@ type User {
group: user group: user
) )
service main { service main {
@doc "register"
@handler register
post /user/register (RegisterReq) returns (RegisterResp)
@doc "mobile login"
@handler mobileLogin
post /user/mobileLogin (MobileLoginReq) returns (MobileLoginResp)
@doc "mobile code login" @doc "mobile code login"
@handler mobileCodeLogin @handler mobileCodeLogin
post /user/mobileCodeLogin (MobileCodeLoginReq) returns (MobileCodeLoginResp) post /user/mobileCodeLogin (MobileCodeLoginReq) returns (MobileCodeLoginResp)
@doc "agent mobile code login"
@handler agentMobileCodeLogin
post /user/agent_mobile_code_login (MobileCodeLoginReq) returns (MobileCodeLoginResp)
@doc "wechat mini auth" @doc "wechat mini auth"
@handler wxMiniAuth @handler wxMiniAuth
post /user/wxMiniAuth (WXMiniAuthReq) returns (WXMiniAuthResp) post /user/wxMiniAuth (WXMiniAuthReq) returns (WXMiniAuthResp)
@ -47,31 +36,6 @@ service main {
post /user/wxh5Auth (WXH5AuthReq) returns (WXH5AuthResp) post /user/wxh5Auth (WXH5AuthReq) returns (WXH5AuthResp)
} }
type (
RegisterReq {
Mobile string `json:"mobile" validate:"required,mobile"`
Password string `json:"password" validate:"required,min=11,max=11,password"`
Code string `json:"code" validate:"required"`
}
RegisterResp {
AccessToken string `json:"accessToken"`
AccessExpire int64 `json:"accessExpire"`
RefreshAfter int64 `json:"refreshAfter"`
}
)
type (
MobileLoginReq {
Mobile string `json:"mobile" validate:"required,mobile"`
Password string `json:"password" validate:"required"`
}
MobileLoginResp {
AccessToken string `json:"accessToken"`
AccessExpire int64 `json:"accessExpire"`
RefreshAfter int64 `json:"refreshAfter"`
}
)
type ( type (
MobileCodeLoginReq { MobileCodeLoginReq {
Mobile string `json:"mobile"` Mobile string `json:"mobile"`
@ -107,6 +71,16 @@ type (
RefreshAfter int64 `json:"refreshAfter"` RefreshAfter int64 `json:"refreshAfter"`
} }
) )
@server (
prefix: api/v1
group: user
middleware: AuthInterceptor
)
service main {
@doc "绑定手机号"
@handler bindMobile
post /user/bindMobile (BindMobileReq) returns (BindMobileResp)
}
//need login //need login
@server ( @server (
@ -125,10 +99,6 @@ service main {
@handler cancelOut @handler cancelOut
post /user/cancelOut post /user/cancelOut
@doc "绑定手机号"
@handler bindMobile
post /user/bindMobile (BindMobileReq) returns (BindMobileResp)
} }
type ( type (
@ -141,6 +111,9 @@ type (
Code string `json:"code" validate:"required"` Code string `json:"code" validate:"required"`
} }
BindMobileResp { BindMobileResp {
AccessToken string `json:"accessToken"`
AccessExpire int64 `json:"accessExpire"`
RefreshAfter int64 `json:"refreshAfter"`
} }
) )

View File

@ -515,6 +515,25 @@ func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
) )
server.AddRoutes( server.AddRoutes(
[]rest.Route{
{
Method: http.MethodGet,
Path: "/info",
Handler: agent.GetAgentInfoHandler(serverCtx),
},
{
Method: http.MethodGet,
Path: "/revenue",
Handler: agent.GetAgentRevenueInfoHandler(serverCtx),
},
},
rest.WithJwt(serverCtx.Config.JwtAuth.AccessSecret),
rest.WithPrefix("/api/v1/agent"),
)
server.AddRoutes(
rest.WithMiddlewares(
[]rest.Middleware{serverCtx.UserAuthInterceptor},
[]rest.Route{ []rest.Route{
{ {
Method: http.MethodGet, Method: http.MethodGet,
@ -526,11 +545,6 @@ func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
Path: "/generating_link", Path: "/generating_link",
Handler: agent.GeneratingLinkHandler(serverCtx), Handler: agent.GeneratingLinkHandler(serverCtx),
}, },
{
Method: http.MethodGet,
Path: "/info",
Handler: agent.GetAgentInfoHandler(serverCtx),
},
{ {
Method: http.MethodGet, Method: http.MethodGet,
Path: "/product_config", Path: "/product_config",
@ -551,12 +565,15 @@ func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
Path: "/subordinate/list", Path: "/subordinate/list",
Handler: agent.GetAgentSubordinateListHandler(serverCtx), Handler: agent.GetAgentSubordinateListHandler(serverCtx),
}, },
}, }...,
),
rest.WithJwt(serverCtx.Config.JwtAuth.AccessSecret), rest.WithJwt(serverCtx.Config.JwtAuth.AccessSecret),
rest.WithPrefix("/api/v1/agent"), rest.WithPrefix("/api/v1/agent"),
) )
server.AddRoutes( server.AddRoutes(
rest.WithMiddlewares(
[]rest.Middleware{serverCtx.UserAuthInterceptor},
[]rest.Route{ []rest.Route{
{ {
Method: http.MethodPost, Method: http.MethodPost,
@ -568,12 +585,15 @@ func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
Path: "/membership/user_config", Path: "/membership/user_config",
Handler: agent.GetAgentMembershipProductConfigHandler(serverCtx), Handler: agent.GetAgentMembershipProductConfigHandler(serverCtx),
}, },
}, }...,
),
rest.WithJwt(serverCtx.Config.JwtAuth.AccessSecret), rest.WithJwt(serverCtx.Config.JwtAuth.AccessSecret),
rest.WithPrefix("/api/v1/agent"), rest.WithPrefix("/api/v1/agent"),
) )
server.AddRoutes( server.AddRoutes(
rest.WithMiddlewares(
[]rest.Middleware{serverCtx.UserAuthInterceptor},
[]rest.Route{ []rest.Route{
{ {
Method: http.MethodGet, Method: http.MethodGet,
@ -585,11 +605,6 @@ func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
Path: "/membership/activate", Path: "/membership/activate",
Handler: agent.ActivateAgentMembershipHandler(serverCtx), Handler: agent.ActivateAgentMembershipHandler(serverCtx),
}, },
{
Method: http.MethodGet,
Path: "/revenue",
Handler: agent.GetAgentRevenueInfoHandler(serverCtx),
},
{ {
Method: http.MethodGet, Method: http.MethodGet,
Path: "/rewards", Path: "/rewards",
@ -605,12 +620,15 @@ func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
Path: "/withdrawal", Path: "/withdrawal",
Handler: agent.AgentWithdrawalHandler(serverCtx), Handler: agent.AgentWithdrawalHandler(serverCtx),
}, },
}, }...,
),
rest.WithJwt(serverCtx.Config.JwtAuth.AccessSecret), rest.WithJwt(serverCtx.Config.JwtAuth.AccessSecret),
rest.WithPrefix("/api/v1/agent"), rest.WithPrefix("/api/v1/agent"),
) )
server.AddRoutes( server.AddRoutes(
rest.WithMiddlewares(
[]rest.Middleware{serverCtx.AuthInterceptor},
[]rest.Route{ []rest.Route{
{ {
Method: http.MethodPost, Method: http.MethodPost,
@ -622,7 +640,8 @@ func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
Path: "/link", Path: "/link",
Handler: agent.GetLinkDataHandler(serverCtx), Handler: agent.GetLinkDataHandler(serverCtx),
}, },
}, }...,
),
rest.WithPrefix("/api/v1/agent"), rest.WithPrefix("/api/v1/agent"),
) )
@ -690,7 +709,7 @@ func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
server.AddRoutes( server.AddRoutes(
rest.WithMiddlewares( rest.WithMiddlewares(
[]rest.Middleware{serverCtx.SourceInterceptor}, []rest.Middleware{serverCtx.UserAuthInterceptor},
[]rest.Route{ []rest.Route{
{ {
Method: http.MethodPost, Method: http.MethodPost,
@ -714,6 +733,8 @@ func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
) )
server.AddRoutes( server.AddRoutes(
rest.WithMiddlewares(
[]rest.Middleware{serverCtx.UserAuthInterceptor},
[]rest.Route{ []rest.Route{
{ {
Method: http.MethodGet, Method: http.MethodGet,
@ -725,7 +746,8 @@ func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
Path: "/en/:product_en", Path: "/en/:product_en",
Handler: product.GetProductByEnHandler(serverCtx), Handler: product.GetProductByEnHandler(serverCtx),
}, },
}, }...,
),
rest.WithJwt(serverCtx.Config.JwtAuth.AccessSecret), rest.WithJwt(serverCtx.Config.JwtAuth.AccessSecret),
rest.WithPrefix("/api/v1/product"), rest.WithPrefix("/api/v1/product"),
) )
@ -762,6 +784,8 @@ func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
) )
server.AddRoutes( server.AddRoutes(
rest.WithMiddlewares(
[]rest.Middleware{serverCtx.UserAuthInterceptor},
[]rest.Route{ []rest.Route{
{ {
// query service // query service
@ -769,12 +793,15 @@ func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
Path: "/query/service/:product", Path: "/query/service/:product",
Handler: query.QueryServiceHandler(serverCtx), Handler: query.QueryServiceHandler(serverCtx),
}, },
}, }...,
),
rest.WithJwt(serverCtx.Config.JwtAuth.AccessSecret), rest.WithJwt(serverCtx.Config.JwtAuth.AccessSecret),
rest.WithPrefix("/api/v1"), rest.WithPrefix("/api/v1"),
) )
server.AddRoutes( server.AddRoutes(
rest.WithMiddlewares(
[]rest.Middleware{serverCtx.UserAuthInterceptor},
[]rest.Route{ []rest.Route{
{ {
// 生成分享链接 // 生成分享链接
@ -818,7 +845,8 @@ func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
Path: "/query/update_data", Path: "/query/update_data",
Handler: query.UpdateQueryDataHandler(serverCtx), Handler: query.UpdateQueryDataHandler(serverCtx),
}, },
}, }...,
),
rest.WithJwt(serverCtx.Config.JwtAuth.AccessSecret), rest.WithJwt(serverCtx.Config.JwtAuth.AccessSecret),
rest.WithPrefix("/api/v1"), rest.WithPrefix("/api/v1"),
) )
@ -848,30 +876,12 @@ func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
server.AddRoutes( server.AddRoutes(
[]rest.Route{ []rest.Route{
{
// agent mobile code login
Method: http.MethodPost,
Path: "/user/agent_mobile_code_login",
Handler: user.AgentMobileCodeLoginHandler(serverCtx),
},
{ {
// mobile code login // mobile code login
Method: http.MethodPost, Method: http.MethodPost,
Path: "/user/mobileCodeLogin", Path: "/user/mobileCodeLogin",
Handler: user.MobileCodeLoginHandler(serverCtx), Handler: user.MobileCodeLoginHandler(serverCtx),
}, },
{
// mobile login
Method: http.MethodPost,
Path: "/user/mobileLogin",
Handler: user.MobileLoginHandler(serverCtx),
},
{
// register
Method: http.MethodPost,
Path: "/user/register",
Handler: user.RegisterHandler(serverCtx),
},
{ {
// wechat mini auth // wechat mini auth
Method: http.MethodPost, Method: http.MethodPost,
@ -889,6 +899,8 @@ func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
) )
server.AddRoutes( server.AddRoutes(
rest.WithMiddlewares(
[]rest.Middleware{serverCtx.AuthInterceptor},
[]rest.Route{ []rest.Route{
{ {
// 绑定手机号 // 绑定手机号
@ -896,6 +908,13 @@ func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
Path: "/user/bindMobile", Path: "/user/bindMobile",
Handler: user.BindMobileHandler(serverCtx), Handler: user.BindMobileHandler(serverCtx),
}, },
}...,
),
rest.WithPrefix("/api/v1"),
)
server.AddRoutes(
[]rest.Route{
{ {
Method: http.MethodPost, Method: http.MethodPost,
Path: "/user/cancelOut", Path: "/user/cancelOut",

View File

@ -1,30 +0,0 @@
package user
import (
"net/http"
"tydata-server/app/main/api/internal/logic/user"
"tydata-server/app/main/api/internal/svc"
"tydata-server/app/main/api/internal/types"
"tydata-server/common/result"
"tydata-server/pkg/lzkit/validator"
"github.com/zeromicro/go-zero/rest/httpx"
)
func AgentMobileCodeLoginHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
var req types.MobileCodeLoginReq
if err := httpx.Parse(r, &req); err != nil {
result.ParamErrorResult(r, w, err)
return
}
if err := validator.Validate(req); err != nil {
result.ParamValidateErrorResult(r, w, err)
return
}
l := user.NewAgentMobileCodeLoginLogic(r.Context(), svcCtx)
resp, err := l.AgentMobileCodeLogin(&req)
result.HttpResult(r, w, resp, err)
}
}

View File

@ -1,30 +0,0 @@
package user
import (
"net/http"
"tydata-server/app/main/api/internal/logic/user"
"tydata-server/app/main/api/internal/svc"
"tydata-server/app/main/api/internal/types"
"tydata-server/common/result"
"tydata-server/pkg/lzkit/validator"
"github.com/zeromicro/go-zero/rest/httpx"
)
func MobileLoginHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
var req types.MobileLoginReq
if err := httpx.Parse(r, &req); err != nil {
result.ParamErrorResult(r, w, err)
return
}
if err := validator.Validate(req); err != nil {
result.ParamValidateErrorResult(r, w, err)
return
}
l := user.NewMobileLoginLogic(r.Context(), svcCtx)
resp, err := l.MobileLogin(&req)
result.HttpResult(r, w, resp, err)
}
}

View File

@ -1,30 +0,0 @@
package user
import (
"net/http"
"tydata-server/app/main/api/internal/logic/user"
"tydata-server/app/main/api/internal/svc"
"tydata-server/app/main/api/internal/types"
"tydata-server/common/result"
"tydata-server/pkg/lzkit/validator"
"github.com/zeromicro/go-zero/rest/httpx"
)
func RegisterHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
var req types.RegisterReq
if err := httpx.Parse(r, &req); err != nil {
result.ParamErrorResult(r, w, err)
return
}
if err := validator.Validate(req); err != nil {
result.ParamValidateErrorResult(r, w, err)
return
}
l := user.NewRegisterLogic(r.Context(), svcCtx)
resp, err := l.Register(&req)
result.HttpResult(r, w, resp, err)
}
}

View File

@ -5,6 +5,7 @@ import (
"tydata-server/app/main/api/internal/svc" "tydata-server/app/main/api/internal/svc"
"tydata-server/app/main/api/internal/types" "tydata-server/app/main/api/internal/types"
"tydata-server/app/main/model"
jwtx "tydata-server/common/jwt" jwtx "tydata-server/common/jwt"
"tydata-server/common/xerr" "tydata-server/common/xerr"
"tydata-server/pkg/lzkit/crypto" "tydata-server/pkg/lzkit/crypto"
@ -71,7 +72,14 @@ func (l *AdminLoginLogic) AdminLogin(req *types.AdminLoginReq) (resp *types.Admi
// 5. 生成token // 5. 生成token
refreshToken := l.svcCtx.Config.JwtAuth.RefreshAfter refreshToken := l.svcCtx.Config.JwtAuth.RefreshAfter
expiresAt := l.svcCtx.Config.JwtAuth.AccessExpire expiresAt := l.svcCtx.Config.JwtAuth.AccessExpire
token, err := jwtx.GenerateJwtToken(user.Id, l.svcCtx.Config.JwtAuth.AccessSecret, expiresAt) claims := jwtx.JwtClaims{
UserId: user.Id,
AgentId: 0,
Platform: model.PlatformAdmin,
UserType: model.UserTypeAdmin,
IsAgent: model.AgentStatusNo,
}
token, err := jwtx.GenerateJwtToken(claims, l.svcCtx.Config.JwtAuth.AccessSecret, expiresAt)
if err != nil { if err != nil {
return nil, errors.Wrapf(xerr.NewErrMsg("生成token失败"), "用户登录, 生成token失败, 用户名: %s", req.Username) return nil, errors.Wrapf(xerr.NewErrMsg("生成token失败"), "用户登录, 生成token失败, 用户名: %s", req.Username)
} }

View File

@ -6,7 +6,7 @@ import (
"fmt" "fmt"
"time" "time"
"tydata-server/app/main/model" "tydata-server/app/main/model"
jwtx "tydata-server/common/jwt" "tydata-server/common/ctxdata"
"tydata-server/common/xerr" "tydata-server/common/xerr"
"tydata-server/pkg/lzkit/crypto" "tydata-server/pkg/lzkit/crypto"
@ -35,6 +35,10 @@ func NewApplyForAgentLogic(ctx context.Context, svcCtx *svc.ServiceContext) *App
} }
func (l *ApplyForAgentLogic) ApplyForAgent(req *types.AgentApplyReq) (resp *types.AgentApplyResp, err error) { func (l *ApplyForAgentLogic) ApplyForAgent(req *types.AgentApplyReq) (resp *types.AgentApplyResp, err error) {
claims, err := ctxdata.GetClaimsFromCtx(l.ctx)
if err != nil && !errors.Is(err, ctxdata.ErrNoInCtx) {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "代理申请, %v", err)
}
secretKey := l.svcCtx.Config.Encrypt.SecretKey secretKey := l.svcCtx.Config.Encrypt.SecretKey
encryptedMobile, err := crypto.EncryptMobile(req.Mobile, secretKey) encryptedMobile, err := crypto.EncryptMobile(req.Mobile, secretKey)
if err != nil { if err != nil {
@ -63,29 +67,20 @@ func (l *ApplyForAgentLogic) ApplyForAgent(req *types.AgentApplyReq) (resp *type
return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "代理申请, 读取数据库获取用户失败, mobile: %s, err: %+v", encryptedMobile, err) return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "代理申请, 读取数据库获取用户失败, mobile: %s, err: %+v", encryptedMobile, err)
} }
if user == nil { if user == nil {
user = &model.User{Mobile: sql.NullString{String: encryptedMobile, Valid: true}} userID, err = l.svcCtx.UserService.RegisterUser(l.ctx, encryptedMobile)
// if len(main.Nickname) == 0 { if err != nil {
// main.Nickname = encryptedMobile return errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "代理申请, 注册用户失败: %+v", err)
// }
insertResult, userInsertErr := l.svcCtx.UserModel.Insert(transCtx, session, user)
if userInsertErr != nil {
return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "代理申请, 数据库插入新用户失败, mobile%s, err: %+v", encryptedMobile, userInsertErr)
} }
lastId, lastInsertIdErr := insertResult.LastInsertId() } else {
if lastInsertIdErr != nil { if claims != nil && claims.UserType == model.UserTypeTemp {
return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "代理申请, 获取新用户ID失败, err:%+v, main:%+v", lastInsertIdErr, user) // 临时用户,转为正式用户
} err = l.svcCtx.UserService.TempUserBindUser(l.ctx, session, user.Id)
user.Id = lastId if err != nil {
userID = lastId return errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "代理申请, 注册用户失败: %+v", err)
userAuth := new(model.UserAuth)
userAuth.UserId = lastId
userAuth.AuthKey = encryptedMobile
userAuth.AuthType = model.UserAuthTypeAgentDirect
if _, userAuthInsertErr := l.svcCtx.UserAuthModel.Insert(transCtx, session, userAuth); userAuthInsertErr != nil {
return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "代理申请, 数据库插入用户认证失败, err:%+v", userAuthInsertErr)
} }
} }
userID = user.Id userID = user.Id
}
// 使用SelectBuilder构建查询查找符合user_id的记录并按创建时间降序排序获取最新一条 // 使用SelectBuilder构建查询查找符合user_id的记录并按创建时间降序排序获取最新一条
builder := l.svcCtx.AgentAuditModel.SelectBuilder().Where("user_id = ?", user.Id).OrderBy("create_time DESC").Limit(1) builder := l.svcCtx.AgentAuditModel.SelectBuilder().Where("user_id = ?", user.Id).OrderBy("create_time DESC").Limit(1)
@ -113,23 +108,12 @@ func (l *ApplyForAgentLogic) ApplyForAgent(req *types.AgentApplyReq) (resp *type
return errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "代理申请, 保存代理审核信息失败: %v", insetAgentAuditErr) return errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "代理申请, 保存代理审核信息失败: %v", insetAgentAuditErr)
} }
//agentAuditID, _ := agentAuditInsert.LastInsertId()
//agentAuditRow, findAgentAuditModelErr := l.svcCtx.AgentAuditModel.FindOne(l.ctx, agentAuditID)
//if findAgentAuditModelErr != nil {
// return errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "代理申请, 查找代理审核信息失败: %v", insetAgentAuditErr)
//}
//agentAuditRow.Status = 1
//updateAgentAuditErr := l.svcCtx.AgentAuditModel.UpdateWithVersion(transCtx, session, agentAuditRow)
//if updateAgentAuditErr != nil {
// return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "代理申请, 通过代理审核失败: %+v", updateAgentAuditErr)
//}
// 新增代理 // 新增代理
var agentModel model.Agent var agentModel model.Agent
agentModel.Mobile = agentAudit.Mobile agentModel.Mobile = agentAudit.Mobile
agentModel.Region = agentAudit.Region agentModel.Region = agentAudit.Region
agentModel.LevelName = model.AgentLeveNameNormal
agentModel.UserId = agentAudit.UserId agentModel.UserId = agentAudit.UserId
agentModel.LevelName = model.AgentLeveNameNormal
agentModelInsert, insertAgentModelErr := l.svcCtx.AgentModel.Insert(transCtx, session, &agentModel) agentModelInsert, insertAgentModelErr := l.svcCtx.AgentModel.Insert(transCtx, session, &agentModel)
if insertAgentModelErr != nil { if insertAgentModelErr != nil {
return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "代理申请, 新增代理失败: %+v", insertAgentModelErr) return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "代理申请, 新增代理失败: %+v", insertAgentModelErr)
@ -169,9 +153,9 @@ func (l *ApplyForAgentLogic) ApplyForAgent(req *types.AgentApplyReq) (resp *type
if transErr != nil { if transErr != nil {
return nil, transErr return nil, transErr
} }
token, generaErr := jwtx.GenerateJwtToken(userID, l.svcCtx.Config.JwtAuth.AccessSecret, l.svcCtx.Config.JwtAuth.AccessExpire) token, err := l.svcCtx.UserService.GeneralUserToken(l.ctx, userID)
if generaErr != nil { if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "代理申请, 生成token失败 : %d", userID) return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "手机登录, 生成token失败 : %d", userID)
} }
// 获取当前时间戳 // 获取当前时间戳

View File

@ -31,9 +31,31 @@ func NewGetAgentRevenueInfoLogic(ctx context.Context, svcCtx *svc.ServiceContext
} }
func (l *GetAgentRevenueInfoLogic) GetAgentRevenueInfo(req *types.GetAgentRevenueInfoReq) (resp *types.GetAgentRevenueInfoResp, err error) { func (l *GetAgentRevenueInfoLogic) GetAgentRevenueInfo(req *types.GetAgentRevenueInfoReq) (resp *types.GetAgentRevenueInfoResp, err error) {
userID, err := ctxdata.GetUidFromCtx(l.ctx) claims, err := ctxdata.GetClaimsFromCtx(l.ctx)
if err != nil { if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "获取代理奖励, %v", err) return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "获取代理信息, %v", err)
}
userID := claims.UserId
userType := claims.UserType
if userType == model.UserTypeTemp {
return &types.GetAgentRevenueInfoResp{
Balance: 0,
TotalEarnings: 0,
FrozenBalance: 0,
DirectPush: types.DirectPushReport{
TotalCommission: 0,
TotalReport: 0,
Today: types.TimeRangeReport{},
Last7D: types.TimeRangeReport{},
Last30D: types.TimeRangeReport{},
},
ActiveReward: types.ActiveReward{
TotalReward: 0,
Today: types.ActiveRewardData{},
Last7D: types.ActiveRewardData{},
Last30D: types.ActiveRewardData{},
},
}, nil
} }
agentModel, err := l.svcCtx.AgentModel.FindOneByUserId(l.ctx, userID) agentModel, err := l.svcCtx.AgentModel.FindOneByUserId(l.ctx, userID)
if err != nil { if err != nil {

View File

@ -8,7 +8,6 @@ import (
"time" "time"
"tydata-server/app/main/api/internal/service" "tydata-server/app/main/api/internal/service"
"tydata-server/common/ctxdata" "tydata-server/common/ctxdata"
jwtx "tydata-server/common/jwt"
"tydata-server/common/xerr" "tydata-server/common/xerr"
"tydata-server/pkg/lzkit/crypto" "tydata-server/pkg/lzkit/crypto"
"tydata-server/pkg/lzkit/validator" "tydata-server/pkg/lzkit/validator"
@ -125,8 +124,8 @@ func (l *QueryServiceLogic) ProcessMarriageLogic(req *types.QueryServiceReq) (*t
if cacheDataErr != nil { if cacheDataErr != nil {
return nil, cacheDataErr return nil, cacheDataErr
} }
token, generaErr := jwtx.GenerateJwtToken(userID, l.svcCtx.Config.JwtAuth.AccessSecret, l.svcCtx.Config.JwtAuth.AccessExpire) token, err := l.svcCtx.UserService.GeneralUserToken(l.ctx, userID)
if generaErr != nil { if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "查询服务, 生成token失败 : %d", userID) return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "查询服务, 生成token失败 : %d", userID)
} }
@ -186,8 +185,8 @@ func (l *QueryServiceLogic) ProcessHomeServiceLogic(req *types.QueryServiceReq)
return nil, cacheDataErr return nil, cacheDataErr
} }
token, generaErr := jwtx.GenerateJwtToken(userID, l.svcCtx.Config.JwtAuth.AccessSecret, l.svcCtx.Config.JwtAuth.AccessExpire) token, err := l.svcCtx.UserService.GeneralUserToken(l.ctx, userID)
if generaErr != nil { if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "查询服务, 生成token失败 : %d", userID) return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "查询服务, 生成token失败 : %d", userID)
} }
@ -247,8 +246,8 @@ func (l *QueryServiceLogic) ProcessRiskAssessmentLogic(req *types.QueryServiceRe
return nil, cacheDataErr return nil, cacheDataErr
} }
token, generaErr := jwtx.GenerateJwtToken(userID, l.svcCtx.Config.JwtAuth.AccessSecret, l.svcCtx.Config.JwtAuth.AccessExpire) token, err := l.svcCtx.UserService.GeneralUserToken(l.ctx, userID)
if generaErr != nil { if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "查询服务, 生成token失败 : %d", userID) return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "查询服务, 生成token失败 : %d", userID)
} }
@ -307,8 +306,8 @@ func (l *QueryServiceLogic) ProcessCompanyInfoLogic(req *types.QueryServiceReq)
return nil, cacheDataErr return nil, cacheDataErr
} }
token, generaErr := jwtx.GenerateJwtToken(userID, l.svcCtx.Config.JwtAuth.AccessSecret, l.svcCtx.Config.JwtAuth.AccessExpire) token, err := l.svcCtx.UserService.GeneralUserToken(l.ctx, userID)
if generaErr != nil { if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "查询服务, 生成token失败 : %d", userID) return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "查询服务, 生成token失败 : %d", userID)
} }
@ -368,8 +367,8 @@ func (l *QueryServiceLogic) ProcessRentalInfoLogic(req *types.QueryServiceReq) (
return nil, cacheDataErr return nil, cacheDataErr
} }
token, generaErr := jwtx.GenerateJwtToken(userID, l.svcCtx.Config.JwtAuth.AccessSecret, l.svcCtx.Config.JwtAuth.AccessExpire) token, err := l.svcCtx.UserService.GeneralUserToken(l.ctx, userID)
if generaErr != nil { if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "查询服务, 生成token失败 : %d", userID) return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "查询服务, 生成token失败 : %d", userID)
} }
@ -429,8 +428,8 @@ func (l *QueryServiceLogic) ProcessPreLoanBackgroundCheckLogic(req *types.QueryS
return nil, cacheDataErr return nil, cacheDataErr
} }
token, generaErr := jwtx.GenerateJwtToken(userID, l.svcCtx.Config.JwtAuth.AccessSecret, l.svcCtx.Config.JwtAuth.AccessExpire) token, err := l.svcCtx.UserService.GeneralUserToken(l.ctx, userID)
if generaErr != nil { if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "查询服务, 生成token失败 : %d", userID) return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "查询服务, 生成token失败 : %d", userID)
} }
@ -489,8 +488,8 @@ func (l *QueryServiceLogic) ProcessBackgroundCheckLogic(req *types.QueryServiceR
return nil, cacheDataErr return nil, cacheDataErr
} }
token, generaErr := jwtx.GenerateJwtToken(userID, l.svcCtx.Config.JwtAuth.AccessSecret, l.svcCtx.Config.JwtAuth.AccessExpire) token, err := l.svcCtx.UserService.GeneralUserToken(l.ctx, userID)
if generaErr != nil { if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "查询服务, 生成token失败 : %d", userID) return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "查询服务, 生成token失败 : %d", userID)
} }
@ -1393,30 +1392,32 @@ func (l *QueryServiceLogic) CacheData(params map[string]interface{}, Product str
// 3. 其他情况返回未登录错误 // 3. 其他情况返回未登录错误
func (l *QueryServiceLogic) GetOrCreateUser() (int64, error) { func (l *QueryServiceLogic) GetOrCreateUser() (int64, error) {
// 尝试获取用户ID // 尝试获取用户ID
userID, err := ctxdata.GetUidFromCtx(l.ctx) claims, err := ctxdata.GetClaimsFromCtx(l.ctx)
if err == nil { if err != nil {
return userID, nil // 已有用户ID直接返回
}
// 如果不是未登录错误,说明是其他错误,直接返回
if !ctxdata.IsNoUserIdError(err) {
return 0, err return 0, err
} }
userID := claims.UserId
return userID, nil
// 检查是否是代理查询或APP请求 // // 如果不是未登录错误,说明是其他错误,直接返回
isAgentQuery := false // if !ctxdata.IsNoUserIdError(err) {
if agentID, ok := l.ctx.Value("agentIdentifier").(string); ok && agentID != "" { // return 0, err
isAgentQuery = true // }
}
if app, ok := l.ctx.Value("app").(bool); ok && app {
isAgentQuery = true
}
// 如果不是代理查询或APP请求返回未登录错误 // // 检查是否是代理查询或APP请求
if !isAgentQuery { // isAgentQuery := false
return 0, ctxdata.ErrNoUserIdInCtx // if agentID, ok := l.ctx.Value("agentIdentifier").(string); ok && agentID != "" {
} // isAgentQuery = true
// }
// if app, ok := l.ctx.Value("app").(bool); ok && app {
// isAgentQuery = true
// }
// 创建新用户 // // 如果不是代理查询或APP请求返回未登录错误
return l.svcCtx.UserService.RegisterUUIDUser(l.ctx) // if !isAgentQuery {
// return 0, ctxdata.ErrNoUserIdInCtx
// }
// // 创建新用户
// return l.svcCtx.UserService.RegisterUUIDUser(l.ctx)
} }

View File

@ -1,99 +0,0 @@
package user
import (
"context"
"database/sql"
"fmt"
"time"
"tydata-server/app/main/api/internal/svc"
"tydata-server/app/main/api/internal/types"
"tydata-server/app/main/model"
jwtx "tydata-server/common/jwt"
"tydata-server/common/xerr"
"tydata-server/pkg/lzkit/crypto"
"github.com/pkg/errors"
"github.com/zeromicro/go-zero/core/stores/redis"
"github.com/zeromicro/go-zero/core/stores/sqlx"
"github.com/zeromicro/go-zero/core/logx"
)
type AgentMobileCodeLoginLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
func NewAgentMobileCodeLoginLogic(ctx context.Context, svcCtx *svc.ServiceContext) *AgentMobileCodeLoginLogic {
return &AgentMobileCodeLoginLogic{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
func (l *AgentMobileCodeLoginLogic) AgentMobileCodeLogin(req *types.MobileCodeLoginReq) (resp *types.MobileCodeLoginResp, err error) {
secretKey := l.svcCtx.Config.Encrypt.SecretKey
encryptedMobile, err := crypto.EncryptMobile(req.Mobile, secretKey)
if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "手机登录, 加密手机号失败: %+v", err)
}
// 检查手机号是否在一分钟内已发送过验证码
redisKey := fmt.Sprintf("%s:%s", "query", encryptedMobile)
cacheCode, err := l.svcCtx.Redis.Get(redisKey)
if err != nil {
if errors.Is(err, redis.Nil) {
return nil, errors.Wrapf(xerr.NewErrMsg("验证码已过期"), "手机登录, 验证码过期")
}
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "手机登录, 读取验证码redis缓存失败, err: %+v", err)
}
if cacheCode != req.Code {
return nil, errors.Wrapf(xerr.NewErrMsg("验证码不正确"), "手机登录, 验证码不正确")
}
user, findUserErr := l.svcCtx.UserModel.FindOneByMobile(l.ctx, sql.NullString{String: encryptedMobile, Valid: true})
if findUserErr != nil && findUserErr != model.ErrNotFound {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "手机登录, 读取数据库获取用户失败, mobile: %s, err: %+v", encryptedMobile, err)
}
if user == nil {
user = &model.User{Mobile: sql.NullString{String: encryptedMobile, Valid: true}}
// if len(main.Nickname) == 0 {
// main.Nickname = ""
// }
if transErr := l.svcCtx.UserModel.Trans(l.ctx, func(ctx context.Context, session sqlx.Session) error {
insertResult, userInsertErr := l.svcCtx.UserModel.Insert(ctx, session, user)
if userInsertErr != nil {
return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "手机注册, 数据库插入新用户失败, mobile%s, err: %+v", encryptedMobile, err)
}
lastId, lastInsertIdErr := insertResult.LastInsertId()
if lastInsertIdErr != nil {
return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "手机注册, 获取新用户ID失败, err:%+v, main:%+v", lastInsertIdErr, user)
}
user.Id = lastId
userAuth := new(model.UserAuth)
userAuth.UserId = lastId
userAuth.AuthKey = encryptedMobile
userAuth.AuthType = model.UserAuthTypeH5Mobile
if _, userAuthInsertErr := l.svcCtx.UserAuthModel.Insert(ctx, session, userAuth); userAuthInsertErr != nil {
return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "手机注册, 数据库插入用户认证失败, err:%+v", userAuthInsertErr)
}
return nil
}); transErr != nil {
return nil, transErr
}
}
token, generaErr := jwtx.GenerateJwtToken(user.Id, l.svcCtx.Config.JwtAuth.AccessSecret, l.svcCtx.Config.JwtAuth.AccessExpire)
if generaErr != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "手机登录, 生成token失败 : %d", user.Id)
}
// 获取当前时间戳
now := time.Now().Unix()
return &types.MobileCodeLoginResp{
AccessToken: token,
AccessExpire: now + l.svcCtx.Config.JwtAuth.AccessExpire,
RefreshAfter: now + l.svcCtx.Config.JwtAuth.RefreshAfter,
}, nil
}

View File

@ -4,6 +4,7 @@ import (
"context" "context"
"database/sql" "database/sql"
"fmt" "fmt"
"time"
"tydata-server/app/main/api/internal/svc" "tydata-server/app/main/api/internal/svc"
"tydata-server/app/main/api/internal/types" "tydata-server/app/main/api/internal/types"
@ -15,7 +16,6 @@ import (
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/zeromicro/go-zero/core/logx" "github.com/zeromicro/go-zero/core/logx"
"github.com/zeromicro/go-zero/core/stores/redis" "github.com/zeromicro/go-zero/core/stores/redis"
"github.com/zeromicro/go-zero/core/stores/sqlx"
) )
type BindMobileLogic struct { type BindMobileLogic struct {
@ -33,22 +33,15 @@ func NewBindMobileLogic(ctx context.Context, svcCtx *svc.ServiceContext) *BindMo
} }
func (l *BindMobileLogic) BindMobile(req *types.BindMobileReq) (resp *types.BindMobileResp, err error) { func (l *BindMobileLogic) BindMobile(req *types.BindMobileReq) (resp *types.BindMobileResp, err error) {
userID, getUserIdErr := ctxdata.GetUidFromCtx(l.ctx) claims, err := ctxdata.GetClaimsFromCtx(l.ctx)
if getUserIdErr != nil { if err != nil && !errors.Is(err, ctxdata.ErrNoInCtx) {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "绑定手机号, %v", getUserIdErr) return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "绑定手机号, %v", err)
} }
secretKey := l.svcCtx.Config.Encrypt.SecretKey secretKey := l.svcCtx.Config.Encrypt.SecretKey
encryptedMobile, err := crypto.EncryptMobile(req.Mobile, secretKey) encryptedMobile, err := crypto.EncryptMobile(req.Mobile, secretKey)
if err != nil { if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "绑定手机号, 加密手机号失败: %v", err) return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "绑定手机号, 加密手机号失败: %v", err)
} }
user, err := l.svcCtx.UserModel.FindOneByMobile(l.ctx, sql.NullString{String: encryptedMobile, Valid: true})
if err != nil && !errors.Is(err, model.ErrNotFound) {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "绑定手机号, %v", err)
}
if user != nil {
return nil, errors.Wrapf(xerr.NewErrMsg("该手机号已绑定"), "绑定手机号, %v", err)
}
// 检查手机号是否在一分钟内已发送过验证码 // 检查手机号是否在一分钟内已发送过验证码
redisKey := fmt.Sprintf("%s:%s", "bindMobile", encryptedMobile) redisKey := fmt.Sprintf("%s:%s", "bindMobile", encryptedMobile)
cacheCode, err := l.svcCtx.Redis.Get(redisKey) cacheCode, err := l.svcCtx.Redis.Get(redisKey)
@ -61,44 +54,38 @@ func (l *BindMobileLogic) BindMobile(req *types.BindMobileReq) (resp *types.Bind
if cacheCode != req.Code { if cacheCode != req.Code {
return nil, errors.Wrapf(xerr.NewErrMsg("验证码不正确"), "手机登录, 验证码不正确: %s", encryptedMobile) return nil, errors.Wrapf(xerr.NewErrMsg("验证码不正确"), "手机登录, 验证码不正确: %s", encryptedMobile)
} }
var userID int64
userModel, err := l.svcCtx.UserModel.FindOne(l.ctx, userID) user, err := l.svcCtx.UserModel.FindOneByMobile(l.ctx, sql.NullString{String: encryptedMobile, Valid: true})
if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "绑定手机号, %v", err)
}
if userModel.Mobile.Valid && userModel.Mobile.String != "" {
return nil, errors.Wrapf(xerr.NewErrMsg("账号已绑定手机号,无法再次绑定"), "绑定手机号, %v", err)
}
userAuthModel, err := l.svcCtx.UserAuthModel.FindOneByUserIdAuthType(l.ctx, userID, model.UserAuthTypeH5Mobile)
if err != nil && !errors.Is(err, model.ErrNotFound) { if err != nil && !errors.Is(err, model.ErrNotFound) {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "绑定手机号, %v", err) return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "绑定手机号, %v", err)
} }
if userAuthModel != nil { if user != nil {
return nil, errors.Wrapf(xerr.NewErrMsg("账号已绑定手机号,无法再次绑定"), "绑定手机号, %v", err) // 进行平台绑定
if claims != nil {
if claims.UserType == model.UserTypeTemp {
err = l.svcCtx.UserService.TempUserBindUser(l.ctx, nil, user.Id)
if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "绑定手机号, 临时用户绑定用户失败: %+v", err)
}
}
}
userID = user.Id
} else {
// 创建账号,并绑定手机号
userID, err = l.svcCtx.UserService.RegisterUser(l.ctx, encryptedMobile)
if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "绑定手机号, 注册用户失败: %+v", err)
}
} }
var userAuth model.UserAuth token, err := l.svcCtx.UserService.GeneralUserToken(l.ctx, userID)
userAuth.UserId = userID
userAuth.AuthType = model.UserAuthTypeH5Mobile
userAuth.AuthKey = encryptedMobile
transErr := l.svcCtx.UserAuthModel.Trans(l.ctx, func(ctx context.Context, session sqlx.Session) error {
_, err = l.svcCtx.UserAuthModel.Insert(ctx, session, &userAuth)
if err != nil { if err != nil {
return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "绑定手机号, %v", err) return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "绑定手机号, 生成token失败: %+v", err)
} }
userModel.Mobile = sql.NullString{ now := time.Now().Unix()
String: encryptedMobile, return &types.BindMobileResp{
Valid: true, AccessToken: token,
} AccessExpire: now + l.svcCtx.Config.JwtAuth.AccessExpire,
_, err = l.svcCtx.UserModel.Update(l.ctx, session, userModel) RefreshAfter: now + l.svcCtx.Config.JwtAuth.RefreshAfter,
if err != nil { }, nil
return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "绑定手机号, %v", err)
}
return nil
})
if transErr != nil {
return nil, transErr
}
return &types.BindMobileResp{}, nil
} }

View File

@ -30,10 +30,23 @@ func NewDetailLogic(ctx context.Context, svcCtx *svc.ServiceContext) *DetailLogi
} }
func (l *DetailLogic) Detail() (resp *types.UserInfoResp, err error) { func (l *DetailLogic) Detail() (resp *types.UserInfoResp, err error) {
userID, err := ctxdata.GetUidFromCtx(l.ctx) claims, err := ctxdata.GetClaimsFromCtx(l.ctx)
if err != nil { if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "用户信息, %v", err) return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "用户信息, %v", err)
} }
userID := claims.UserId
userType := claims.UserType
if userType == model.UserTypeTemp {
return &types.UserInfoResp{
UserInfo: types.User{
Id: userID,
UserType: userType,
Mobile: "",
NickName: "",
},
}, nil
}
user, err := l.svcCtx.UserModel.FindOne(l.ctx, userID) user, err := l.svcCtx.UserModel.FindOne(l.ctx, userID)
if err != nil { if err != nil {
if errors.Is(err, model.ErrNotFound) { if errors.Is(err, model.ErrNotFound) {
@ -46,12 +59,15 @@ func (l *DetailLogic) Detail() (resp *types.UserInfoResp, err error) {
if err != nil { if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "用户信息, 用户信息结构体复制失败, %v", err) return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "用户信息, 用户信息结构体复制失败, %v", err)
} }
if user.Mobile.Valid { if user.Mobile.Valid {
userInfo.Mobile, err = crypto.DecryptMobile(user.Mobile.String, l.svcCtx.Config.Encrypt.SecretKey) userInfo.Mobile, err = crypto.DecryptMobile(user.Mobile.String, l.svcCtx.Config.Encrypt.SecretKey)
if err != nil { if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "用户信息, 解密手机号失败, %v", err) return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "用户信息, 解密手机号失败, %v", err)
} }
} }
userInfo.UserType = claims.UserType
return &types.UserInfoResp{ return &types.UserInfoResp{
UserInfo: userInfo, UserInfo: userInfo,
}, nil }, nil

View File

@ -4,7 +4,6 @@ import (
"context" "context"
"time" "time"
"tydata-server/common/ctxdata" "tydata-server/common/ctxdata"
jwtx "tydata-server/common/jwt"
"tydata-server/common/xerr" "tydata-server/common/xerr"
"github.com/pkg/errors" "github.com/pkg/errors"
@ -32,11 +31,11 @@ func NewGetTokenLogic(ctx context.Context, svcCtx *svc.ServiceContext) *GetToken
func (l *GetTokenLogic) GetToken() (resp *types.MobileCodeLoginResp, err error) { func (l *GetTokenLogic) GetToken() (resp *types.MobileCodeLoginResp, err error) {
userID, err := ctxdata.GetUidFromCtx(l.ctx) userID, err := ctxdata.GetUidFromCtx(l.ctx)
if err != nil { if err != nil {
return nil, errors.Wrapf(xerr.NewErrMsg(""), "用户信息, %v", err) return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "用户信息, %v", err)
} }
token, generaErr := jwtx.GenerateJwtToken(userID, l.svcCtx.Config.JwtAuth.AccessSecret, l.svcCtx.Config.JwtAuth.AccessExpire) token, err := l.svcCtx.UserService.GeneralUserToken(l.ctx, userID)
if generaErr != nil { if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "更新token, 生成token失败 : %d", userID) return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "用户信息, %v", err)
} }
// 获取当前时间戳 // 获取当前时间戳
now := time.Now().Unix() now := time.Now().Unix()

View File

@ -8,13 +8,11 @@ import (
"tydata-server/app/main/api/internal/svc" "tydata-server/app/main/api/internal/svc"
"tydata-server/app/main/api/internal/types" "tydata-server/app/main/api/internal/types"
"tydata-server/app/main/model" "tydata-server/app/main/model"
jwtx "tydata-server/common/jwt"
"tydata-server/common/xerr" "tydata-server/common/xerr"
"tydata-server/pkg/lzkit/crypto" "tydata-server/pkg/lzkit/crypto"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/zeromicro/go-zero/core/stores/redis" "github.com/zeromicro/go-zero/core/stores/redis"
"github.com/zeromicro/go-zero/core/stores/sqlx"
"github.com/zeromicro/go-zero/core/logx" "github.com/zeromicro/go-zero/core/logx"
) )
@ -53,42 +51,22 @@ func (l *MobileCodeLoginLogic) MobileCodeLogin(req *types.MobileCodeLoginReq) (r
return nil, errors.Wrapf(xerr.NewErrMsg("验证码不正确"), "手机登录, 验证码不正确: %s", encryptedMobile) return nil, errors.Wrapf(xerr.NewErrMsg("验证码不正确"), "手机登录, 验证码不正确: %s", encryptedMobile)
} }
} }
var userID int64
user, findUserErr := l.svcCtx.UserModel.FindOneByMobile(l.ctx, sql.NullString{String: encryptedMobile, Valid: true}) user, findUserErr := l.svcCtx.UserModel.FindOneByMobile(l.ctx, sql.NullString{String: encryptedMobile, Valid: true})
if findUserErr != nil && findUserErr != model.ErrNotFound { if findUserErr != nil && findUserErr != model.ErrNotFound {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "手机登录, 读取数据库获取用户失败, mobile: %s, err: %+v", encryptedMobile, err) return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "手机登录, 读取数据库获取用户失败, mobile: %s, err: %+v", encryptedMobile, err)
} }
if user == nil { if user == nil {
user = &model.User{Mobile: sql.NullString{String: encryptedMobile, Valid: true}} userID, err = l.svcCtx.UserService.RegisterUser(l.ctx, encryptedMobile)
// if len(main.Nickname) == 0 { if err != nil {
// main.Nickname = encryptedMobile return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "手机登录, 注册用户失败: %+v", err)
// }
if transErr := l.svcCtx.UserModel.Trans(l.ctx, func(ctx context.Context, session sqlx.Session) error {
insertResult, userInsertErr := l.svcCtx.UserModel.Insert(ctx, session, user)
if userInsertErr != nil {
return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "手机注册, 数据库插入新用户失败, mobile%s, err: %+v", encryptedMobile, err)
} }
lastId, lastInsertIdErr := insertResult.LastInsertId() } else {
if lastInsertIdErr != nil { userID = user.Id
return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "手机注册, 获取新用户ID失败, err:%+v, main:%+v", lastInsertIdErr, user)
} }
user.Id = lastId token, err := l.svcCtx.UserService.GeneralUserToken(l.ctx, userID)
if err != nil {
userAuth := new(model.UserAuth) return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "手机登录, 生成token失败 : %d", userID)
userAuth.UserId = lastId
userAuth.AuthKey = encryptedMobile
userAuth.AuthType = model.UserAuthTypeAppMobile
if _, userAuthInsertErr := l.svcCtx.UserAuthModel.Insert(ctx, session, userAuth); userAuthInsertErr != nil {
return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "手机注册, 数据库插入用户认证失败, err:%+v", userAuthInsertErr)
}
return nil
}); transErr != nil {
return nil, transErr
}
}
token, generaErr := jwtx.GenerateJwtToken(user.Id, l.svcCtx.Config.JwtAuth.AccessSecret, l.svcCtx.Config.JwtAuth.AccessExpire)
if generaErr != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "手机登录, 生成token失败 : %d", user.Id)
} }
// 获取当前时间戳 // 获取当前时间戳

View File

@ -1,65 +0,0 @@
package user
import (
"context"
"database/sql"
"time"
"tydata-server/app/main/model"
jwtx "tydata-server/common/jwt"
"tydata-server/common/tool"
"tydata-server/common/xerr"
"tydata-server/pkg/lzkit/crypto"
"tydata-server/pkg/lzkit/lzUtils"
"github.com/pkg/errors"
"tydata-server/app/main/api/internal/svc"
"tydata-server/app/main/api/internal/types"
"github.com/zeromicro/go-zero/core/logx"
)
type MobileLoginLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
func NewMobileLoginLogic(ctx context.Context, svcCtx *svc.ServiceContext) *MobileLoginLogic {
return &MobileLoginLogic{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
func (l *MobileLoginLogic) MobileLogin(req *types.MobileLoginReq) (resp *types.MobileCodeLoginResp, err error) {
secretKey := l.svcCtx.Config.Encrypt.SecretKey
encryptedMobile, err := crypto.EncryptMobile(req.Mobile, secretKey)
if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "手机登录, 加密手机号失败: %+v", err)
}
user, findUserErr := l.svcCtx.UserModel.FindOneByMobile(l.ctx, sql.NullString{String: encryptedMobile, Valid: true})
if findUserErr != nil && findUserErr != model.ErrNotFound {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "手机登录, 读取数据库获取用户失败, mobile%s, err: %+v", encryptedMobile, err)
}
if user == nil {
return nil, errors.Wrapf(xerr.NewErrMsg("手机号码未注册"), "手机登录, 手机号未注册:%s", encryptedMobile)
}
if !(tool.Md5ByString(req.Password) == lzUtils.NullStringToString(user.Password)) {
return nil, errors.Wrapf(xerr.NewErrMsg("密码不正确"), "手机登录, 密码匹配不正确%s", encryptedMobile)
}
token, generaErr := jwtx.GenerateJwtToken(user.Id, l.svcCtx.Config.JwtAuth.AccessSecret, l.svcCtx.Config.JwtAuth.AccessExpire)
if generaErr != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "手机登录, 生成token失败 : %d", user.Id)
}
// 获取当前时间戳
now := time.Now().Unix()
return &types.MobileCodeLoginResp{
AccessToken: token,
AccessExpire: now + l.svcCtx.Config.JwtAuth.AccessExpire,
RefreshAfter: now + l.svcCtx.Config.JwtAuth.RefreshAfter,
}, nil
}

View File

@ -1,106 +0,0 @@
package user
import (
"context"
"database/sql"
"fmt"
"time"
"tydata-server/app/main/api/internal/svc"
"tydata-server/app/main/api/internal/types"
"tydata-server/app/main/model"
jwtx "tydata-server/common/jwt"
"tydata-server/common/tool"
"tydata-server/common/xerr"
"tydata-server/pkg/lzkit/crypto"
"tydata-server/pkg/lzkit/lzUtils"
"github.com/pkg/errors"
"github.com/zeromicro/go-zero/core/stores/redis"
"github.com/zeromicro/go-zero/core/stores/sqlx"
"github.com/zeromicro/go-zero/core/logx"
)
type RegisterLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
func NewRegisterLogic(ctx context.Context, svcCtx *svc.ServiceContext) *RegisterLogic {
return &RegisterLogic{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
func (l *RegisterLogic) Register(req *types.RegisterReq) (resp *types.RegisterResp, err error) {
secretKey := l.svcCtx.Config.Encrypt.SecretKey
encryptedMobile, err := crypto.EncryptMobile(req.Mobile, secretKey)
if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "手机注册, 加密手机号失败: %+v", err)
}
// 检查手机号是否在一分钟内已发送过验证码
redisKey := fmt.Sprintf("%s:%s", "register", encryptedMobile)
cacheCode, err := l.svcCtx.Redis.Get(redisKey)
if err != nil {
if errors.Is(err, redis.Nil) {
return nil, errors.Wrapf(xerr.NewErrMsg("验证码已过期"), "手机注册, 验证码过期: %s", encryptedMobile)
}
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "手机注册, 读取验证码redis缓存失败, mobile: %s, err: %+v", encryptedMobile, err)
}
if cacheCode != req.Code {
return nil, errors.Wrapf(xerr.NewErrMsg("验证码不正确"), "手机注册, 验证码不正确: %s", encryptedMobile)
}
hasUser, findUserErr := l.svcCtx.UserModel.FindOneByMobile(l.ctx, sql.NullString{String: encryptedMobile, Valid: true})
if findUserErr != nil && findUserErr != model.ErrNotFound {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "手机注册, 读取数据库获取用户失败, mobile%s, err: %+v", encryptedMobile, err)
}
if hasUser != nil {
return nil, errors.Wrapf(xerr.NewErrMsg("该手机号码已注册"), "手机注册, 手机号码已注册, mobile:%s", encryptedMobile)
}
var userId int64
if transErr := l.svcCtx.UserModel.Trans(l.ctx, func(ctx context.Context, session sqlx.Session) error {
user := new(model.User)
user.Mobile = sql.NullString{String: encryptedMobile, Valid: true}
// if len(main.Nickname) == 0 {
// main.Nickname = encryptedMobile
// }
if len(req.Password) > 0 {
user.Password = lzUtils.StringToNullString(tool.Md5ByString(req.Password))
}
insertResult, userInsertErr := l.svcCtx.UserModel.Insert(ctx, session, user)
if userInsertErr != nil {
return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "手机注册, 数据库插入新用户失败, mobile%s, err: %+v", encryptedMobile, err)
}
lastId, lastInsertIdErr := insertResult.LastInsertId()
if lastInsertIdErr != nil {
return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "手机注册, 获取新用户ID失败, err:%+v, main:%+v", lastInsertIdErr, user)
}
userId = lastId
userAuth := new(model.UserAuth)
userAuth.UserId = lastId
userAuth.AuthKey = encryptedMobile
userAuth.AuthType = model.UserAuthTypeAppMobile
if _, userAuthInsertErr := l.svcCtx.UserAuthModel.Insert(ctx, session, userAuth); userAuthInsertErr != nil {
return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "手机注册, 数据库插入用户认证失败, err:%+v", userAuthInsertErr)
}
return nil
}); transErr != nil {
return nil, transErr
}
token, generaErr := jwtx.GenerateJwtToken(userId, l.svcCtx.Config.JwtAuth.AccessSecret, l.svcCtx.Config.JwtAuth.AccessExpire)
if generaErr != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "手机注册, 生成jwt token失败, userid: %d, err:%+v", userId, generaErr)
}
// 获取当前时间戳
now := time.Now().Unix()
return &types.RegisterResp{
AccessToken: token,
AccessExpire: now + l.svcCtx.Config.JwtAuth.AccessExpire,
RefreshAfter: now + l.svcCtx.Config.JwtAuth.RefreshAfter,
}, nil
}

View File

@ -8,11 +8,9 @@ import (
"net/http" "net/http"
"time" "time"
"tydata-server/app/main/model" "tydata-server/app/main/model"
jwtx "tydata-server/common/jwt"
"tydata-server/common/xerr" "tydata-server/common/xerr"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/zeromicro/go-zero/core/stores/sqlx"
"tydata-server/app/main/api/internal/svc" "tydata-server/app/main/api/internal/svc"
"tydata-server/app/main/api/internal/types" "tydata-server/app/main/api/internal/types"
@ -40,60 +38,51 @@ func (l *WxH5AuthLogic) WxH5Auth(req *types.WXH5AuthReq) (resp *types.WXH5AuthRe
if err != nil { if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "获取access_token失败: %v", err) return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "获取access_token失败: %v", err)
} }
if accessTokenResp.AccessToken == "" || accessTokenResp.Openid == "" {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "获取access_token为空: %v", accessTokenResp)
}
// Step 2: 查找用户授权信息 // Step 2: 查找用户授权信息
userAuth, findErr := l.svcCtx.UserAuthModel.FindOneByAuthTypeAuthKey(l.ctx, model.UserAuthTypeWxh5, accessTokenResp.Openid) userAuth, findErr := l.svcCtx.UserAuthModel.FindOneByAuthTypeAuthKey(l.ctx, model.UserAuthTypeWxh5OpenID, accessTokenResp.Openid)
if findErr != nil && !errors.Is(findErr, model.ErrNotFound) { if findErr != nil && !errors.Is(findErr, model.ErrNotFound) {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "查询用户授权失败findErr: %v", findErr) return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "查询用户授权失败: %v", findErr)
} }
// Step 3: 查找或创建用户 // Step 3: 处理用户信息
var user *model.User var userID int64
if userAuth != nil { if userAuth != nil {
// 授权信息存在,查找用户 // 已存在用户,直接登录
userModel, findUserErr := l.svcCtx.UserModel.FindOne(l.ctx, userAuth.UserId) userID = userAuth.UserId
if findUserErr != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "查询用户失败userId: %v", findUserErr)
}
user = userModel
} else { } else {
// 授权信息不存在,创建新用户 // 检查临时用户表
user = &model.User{} userTemp, err := l.svcCtx.UserTempModel.FindOneByAuthTypeAuthKey(l.ctx, model.UserAuthTypeWxh5OpenID, accessTokenResp.Openid)
if transErr := l.svcCtx.UserModel.Trans(l.ctx, func(context context.Context, session sqlx.Session) error { if err != nil && !errors.Is(err, model.ErrNotFound) {
// 插入数据库 return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "查询用户临时信息失败: %v", err)
insertResult, insertErr := l.svcCtx.UserModel.Insert(l.ctx, session, user)
if insertErr != nil {
return errors.Wrapf(insertErr, "创建新用户失败openid: %s", accessTokenResp.Openid)
} }
// 获取插入后生成的 main.Id
lastInsertId, lastInsertIdErr := insertResult.LastInsertId() if userTemp == nil {
if lastInsertIdErr != nil { // 创建临时用户记录
return errors.Wrapf(lastInsertIdErr, "获取新用户ID失败openid: %s", accessTokenResp.Openid) userTemp = &model.UserTemp{
} AuthType: model.UserAuthTypeWxh5OpenID,
user.Id = lastInsertId
// 创建用户授权信息
userAuth = &model.UserAuth{
UserId: user.Id,
AuthKey: accessTokenResp.Openid, AuthKey: accessTokenResp.Openid,
AuthType: model.UserAuthTypeWxh5, // 微信小程序
} }
if _, insertUserAuthErr := l.svcCtx.UserAuthModel.Insert(l.ctx, session, userAuth); insertUserAuthErr != nil { result, err := l.svcCtx.UserTempModel.Insert(l.ctx, nil, userTemp)
return errors.Wrapf(insertUserAuthErr, "创建用户授权失败openid: %s", accessTokenResp.Openid) if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "创建临时用户信息失败: %v", err)
} }
return nil userID, err = result.LastInsertId()
}); transErr != nil { if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "创建新用户事务失败: %v", transErr) return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "获取新创建的临时用户ID失败: %v", err)
}
} else {
userID = userTemp.Id
} }
} }
// Step 4: 生成JWT Token // Step 4: 生成JWT Token
token, genErr := jwtx.GenerateJwtToken(user.Id, l.svcCtx.Config.JwtAuth.AccessSecret, l.svcCtx.Config.JwtAuth.AccessExpire) token, err := l.svcCtx.UserService.GeneralUserToken(l.ctx, userID)
if genErr != nil { if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "生成JWT token失败: %v", genErr) return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "生成JWT token失败: %v", err)
} }
// Step 5: 返回登录结果
now := time.Now().Unix() now := time.Now().Unix()
return &types.WXH5AuthResp{ return &types.WXH5AuthResp{
AccessToken: token, AccessToken: token,
@ -130,9 +119,9 @@ func (l *WxH5AuthLogic) GetAccessToken(code string) (*AccessTokenResp, error) {
return nil, err return nil, err
} }
//if accessTokenResp.AccessToken == "" { if accessTokenResp.AccessToken == "" || accessTokenResp.Openid == "" {
// return nil, errors.New("accessTokenResp.AccessToken为空") return nil, errors.New("accessTokenResp.AccessToken为空")
//} }
return &accessTokenResp, nil return &accessTokenResp, nil
} }

View File

@ -2,12 +2,9 @@ package middleware
import ( import (
"context" "context"
"encoding/json"
"fmt"
"net/http" "net/http"
"tydata-server/app/main/api/internal/config" "tydata-server/app/main/api/internal/config"
"tydata-server/common/ctxdata"
jwtx "tydata-server/common/jwt" jwtx "tydata-server/common/jwt"
"tydata-server/common/xerr" "tydata-server/common/xerr"
@ -42,17 +39,14 @@ func (m *AuthInterceptorMiddleware) Handle(next http.HandlerFunc) http.HandlerFu
} }
// 解析JWT令牌 // 解析JWT令牌
userId, err := jwtx.ParseJwtToken(authHeader, m.Config.JwtAuth.AccessSecret) claims, err := jwtx.ParseJwtToken(authHeader, m.Config.JwtAuth.AccessSecret)
if err != nil { if err != nil {
// JWT解析失败返回401错误 // JWT解析失败返回401错误
httpx.Error(w, errors.Wrapf(xerr.NewErrCode(ErrCodeUnauthorized), "token解析失败: %v", err)) httpx.Error(w, errors.Wrapf(xerr.NewErrCode(ErrCodeUnauthorized), "token解析失败: %v", err))
return return
} }
// 将用户ID转换为json.Number类型后添加到请求上下文 ctx := context.WithValue(r.Context(), jwtx.ExtraKey, claims)
userIdStr := fmt.Sprintf("%d", userId)
userIdJsonNum := json.Number(userIdStr)
ctx := context.WithValue(r.Context(), ctxdata.CtxKeyJwtUserId, userIdJsonNum)
// 使用新的上下文继续处理请求 // 使用新的上下文继续处理请求
next(w, r.WithContext(ctx)) next(w, r.WithContext(ctx))

View File

@ -6,28 +6,16 @@ import (
) )
const ( const (
BrandKey = "X-Brand"
PlatformKey = "X-Platform" PlatformKey = "X-Platform"
) )
type SourceInterceptorMiddleware struct { func GlobalSourceInterceptor(next http.HandlerFunc) http.HandlerFunc {
}
func NewSourceInterceptorMiddleware() *SourceInterceptorMiddleware {
return &SourceInterceptorMiddleware{}
}
func (m *SourceInterceptorMiddleware) Handle(next http.HandlerFunc) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) { return func(w http.ResponseWriter, r *http.Request) {
// 获取请求头 X-Brand 和 X-Platform 的值 // 获取请求头 X-Platform 的值
brand := r.Header.Get(BrandKey)
platform := r.Header.Get(PlatformKey) platform := r.Header.Get(PlatformKey)
// 将值放入新的 context 中 // 将值放入新的 context 中
ctx := r.Context() ctx := r.Context()
if brand != "" {
ctx = context.WithValue(ctx, "brand", brand)
}
if platform != "" { if platform != "" {
ctx = context.WithValue(ctx, "platform", platform) ctx = context.WithValue(ctx, "platform", platform)
} }

View File

@ -0,0 +1,33 @@
package middleware
import (
"net/http"
"tydata-server/app/main/model"
"tydata-server/common/ctxdata"
"tydata-server/common/xerr"
"github.com/pkg/errors"
"github.com/zeromicro/go-zero/rest/httpx"
)
type UserAuthInterceptorMiddleware struct {
}
func NewUserAuthInterceptorMiddleware() *UserAuthInterceptorMiddleware {
return &UserAuthInterceptorMiddleware{}
}
func (m *UserAuthInterceptorMiddleware) Handle(next http.HandlerFunc) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
claims, err := ctxdata.GetClaimsFromCtx(r.Context())
if err != nil {
httpx.Error(w, errors.Wrapf(xerr.NewErrCode(ErrCodeUnauthorized), "token解析失败: %v", err))
return
}
if claims.UserType == model.UserTypeTemp {
httpx.Error(w, errors.Wrapf(xerr.NewErrCode(xerr.USER_NEED_BIND_MOBILE), "token解析失败: %v", err))
return
}
next(w, r)
}
}

View File

@ -10,6 +10,7 @@ import (
"sync/atomic" "sync/atomic"
"time" "time"
"tydata-server/app/main/api/internal/config" "tydata-server/app/main/api/internal/config"
"tydata-server/app/main/model"
"tydata-server/pkg/lzkit/lzUtils" "tydata-server/pkg/lzkit/lzUtils"
"github.com/smartwalle/alipay/v3" "github.com/smartwalle/alipay/v3"
@ -104,10 +105,10 @@ func (a *AliPayService) CreateAlipayOrder(ctx context.Context, amount float64, s
return "", fmt.Errorf("无的支付平台: %s", platform) return "", fmt.Errorf("无的支付平台: %s", platform)
} }
switch platform { switch platform {
case "app": case model.PlatformApp:
// 调用App支付的创建方法 // 调用App支付的创建方法
return a.CreateAlipayAppOrder(amount, subject, outTradeNo) return a.CreateAlipayAppOrder(amount, subject, outTradeNo)
case "h5": case model.PlatformH5:
// 调用H5支付的创建方法并传入 returnUrl // 调用H5支付的创建方法并传入 returnUrl
return a.CreateAlipayH5Order(amount, subject, outTradeNo) return a.CreateAlipayH5Order(amount, subject, outTradeNo)
default: default:

View File

@ -2,22 +2,34 @@ package service
import ( import (
"context" "context"
"database/sql"
"tydata-server/app/main/api/internal/config"
"tydata-server/app/main/model" "tydata-server/app/main/model"
"tydata-server/common/ctxdata"
jwtx "tydata-server/common/jwt"
"tydata-server/common/xerr"
"github.com/google/uuid" "github.com/google/uuid"
"github.com/pkg/errors"
"github.com/zeromicro/go-zero/core/stores/sqlx" "github.com/zeromicro/go-zero/core/stores/sqlx"
) )
type UserService struct { type UserService struct {
Config *config.Config
userModel model.UserModel userModel model.UserModel
userAuthModel model.UserAuthModel userAuthModel model.UserAuthModel
userTempModel model.UserTempModel
agentModel model.AgentModel
} }
// NewUserService 创建UserService实例 // NewUserService 创建UserService实例
func NewUserService(userModel model.UserModel, userAuthModel model.UserAuthModel) *UserService { func NewUserService(config *config.Config, userModel model.UserModel, userAuthModel model.UserAuthModel, userTempModel model.UserTempModel, agentModel model.AgentModel) *UserService {
return &UserService{ return &UserService{
Config: config,
userModel: userModel, userModel: userModel,
userAuthModel: userAuthModel, userAuthModel: userAuthModel,
userTempModel: userTempModel,
agentModel: agentModel,
} }
} }
@ -63,3 +75,217 @@ func (s *UserService) RegisterUUIDUser(ctx context.Context) (int64, error) {
return userId, nil return userId, nil
} }
// generalUserToken 生成用户token
func (s *UserService) GeneralUserToken(ctx context.Context, userID int64) (string, error) {
platform, err := ctxdata.GetPlatformFromCtx(ctx)
if err != nil {
return "", err
}
var isAgent int64
var agentID int64
var userType int64
user, err := s.userModel.FindOne(ctx, userID)
if err != nil && !errors.Is(err, model.ErrNotFound) {
return "", err
}
if user != nil {
userID = user.Id
userType = model.UserTypeNormal
agent, err := s.agentModel.FindOneByUserId(ctx, userID)
if err != nil && !errors.Is(err, model.ErrNotFound) {
return "", err
}
if agent != nil {
agentID = agent.Id
isAgent = model.AgentStatusYes
}
} else {
userTemp, err := s.userTempModel.FindOne(ctx, userID)
if err != nil {
return "", err
}
if userTemp != nil {
userID = userTemp.Id
userType = model.UserTypeTemp
}
}
token, generaErr := jwtx.GenerateJwtToken(jwtx.JwtClaims{
UserId: userID,
AgentId: agentID,
Platform: platform,
UserType: userType,
IsAgent: isAgent,
}, s.Config.JwtAuth.AccessSecret, s.Config.JwtAuth.AccessExpire)
if generaErr != nil {
return "", errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "更新token, 生成token失败 : %d", userID)
}
return token, nil
}
// RegisterUser 注册用户返回用户ID
// 传入手机号自动注册如果ctx存在临时用户则临时用户转为正式用户
func (s *UserService) RegisterUser(ctx context.Context, mobile string) (int64, error) {
claims, err := ctxdata.GetClaimsFromCtx(ctx)
if err != nil && !errors.Is(err, ctxdata.ErrNoInCtx) {
return 0, err
}
user, err := s.userModel.FindOneByMobile(ctx, sql.NullString{String: mobile, Valid: true})
if err != nil && !errors.Is(err, model.ErrNotFound) {
return 0, err
}
if user != nil {
return 0, errors.New("用户已注册")
}
// 普通注册
if claims == nil {
var userId int64
err = s.userModel.Trans(ctx, func(ctx context.Context, session sqlx.Session) error {
user := &model.User{
Mobile: sql.NullString{String: mobile, Valid: true},
}
result, err := s.userModel.Insert(ctx, session, user)
if err != nil {
return err
}
userId, err = result.LastInsertId()
if err != nil {
return err
}
s.userAuthModel.Insert(ctx, session, &model.UserAuth{
UserId: userId,
AuthType: model.UserAuthTypeMobile,
AuthKey: mobile,
})
return nil
})
if err != nil {
return 0, err
}
return userId, nil
}
// 双重判断是否已经注册
if claims.UserType == model.UserTypeNormal {
return 0, errors.New("用户已注册")
}
var userId int64
// 临时转正式注册
err = s.userModel.Trans(ctx, func(ctx context.Context, session sqlx.Session) error {
user := &model.User{
Mobile: sql.NullString{String: mobile, Valid: true},
}
result, err := s.userModel.Insert(ctx, session, user)
if err != nil {
return err
}
userId, err = result.LastInsertId()
if err != nil {
return err
}
_, err = s.userAuthModel.Insert(ctx, session, &model.UserAuth{
UserId: userId,
AuthType: model.UserAuthTypeMobile,
AuthKey: mobile,
})
if err != nil {
return err
}
err = s.TempUserBindUser(ctx, session, userId)
if err != nil {
return err
}
return nil
})
if err != nil {
return 0, err
}
return userId, nil
}
// TempUserBindUser 临时用户绑定用户
func (s *UserService) TempUserBindUser(ctx context.Context, session sqlx.Session, normalUserID int64) error {
claims, err := ctxdata.GetClaimsFromCtx(ctx)
if err != nil && !errors.Is(err, ctxdata.ErrNoInCtx) {
return err
}
if claims == nil || claims.UserType != model.UserTypeTemp {
return errors.New("无临时用户")
}
userTemp, err := s.userTempModel.FindOne(ctx, claims.UserId)
if err != nil {
return err
}
userAuth, err := s.userAuthModel.FindOneByAuthTypeAuthKey(ctx, userTemp.AuthType, userTemp.AuthKey)
if err != nil && !errors.Is(err, model.ErrNotFound) {
return err
}
if userAuth != nil {
return errors.New("临时用户已注册")
}
if session == nil {
err := s.userAuthModel.Trans(ctx, func(ctx context.Context, session sqlx.Session) error {
_, err = s.userAuthModel.Insert(ctx, session, &model.UserAuth{
UserId: normalUserID,
AuthType: userTemp.AuthType,
AuthKey: userTemp.AuthKey,
})
if err != nil {
return err
}
err = s.userTempModel.DeleteSoft(ctx, session, userTemp)
if err != nil {
return err
}
return nil
})
if err != nil {
return err
}
return nil
} else {
_, err = s.userAuthModel.Insert(ctx, session, &model.UserAuth{
UserId: normalUserID,
AuthType: userTemp.AuthType,
AuthKey: userTemp.AuthKey,
})
if err != nil {
return err
}
err = s.userTempModel.DeleteSoft(ctx, session, userTemp)
if err != nil {
return err
}
return nil
}
}
// _bak_RegisterUUIDUser 注册UUID用户返回用户ID
func (s *UserService) _bak_RegisterUUIDUser(ctx context.Context) error {
// 生成UUID
uuidStr, err := s.GenerateUUIDUserId(ctx)
if err != nil {
return err
}
err = s.userTempModel.Trans(ctx, func(ctx context.Context, session sqlx.Session) error {
// 创建用户临时记录
userTemp := &model.UserTemp{
AuthType: model.UserAuthTypeUUID,
AuthKey: uuidStr,
}
_, err := s.userTempModel.Insert(ctx, session, userTemp)
return err
})
if err != nil {
return err
}
return nil
}

View File

@ -219,12 +219,12 @@ func (w *WechatPayService) CreateWechatOrder(ctx context.Context, amount float64
var err error var err error
switch platform { switch platform {
case "mp-weixin": case model.PlatformWxMini:
userID, getUidErr := ctxdata.GetUidFromCtx(ctx) userID, getUidErr := ctxdata.GetUidFromCtx(ctx)
if getUidErr != nil { if getUidErr != nil {
return "", getUidErr return "", getUidErr
} }
userAuthModel, findAuthModelErr := w.userAuthModel.FindOneByUserIdAuthType(ctx, userID, model.UserAuthTypeWxMini) userAuthModel, findAuthModelErr := w.userAuthModel.FindOneByUserIdAuthType(ctx, userID, model.UserAuthTypeWxMiniOpenID)
if findAuthModelErr != nil { if findAuthModelErr != nil {
return "", findAuthModelErr return "", findAuthModelErr
} }
@ -232,12 +232,12 @@ func (w *WechatPayService) CreateWechatOrder(ctx context.Context, amount float64
if err != nil { if err != nil {
return "", err return "", err
} }
case "h5-weixin": case model.PlatformWxH5:
userID, getUidErr := ctxdata.GetUidFromCtx(ctx) userID, getUidErr := ctxdata.GetUidFromCtx(ctx)
if getUidErr != nil { if getUidErr != nil {
return "", getUidErr return "", getUidErr
} }
userAuthModel, findAuthModelErr := w.userAuthModel.FindOneByUserIdAuthType(ctx, userID, model.UserAuthTypeWxh5) userAuthModel, findAuthModelErr := w.userAuthModel.FindOneByUserIdAuthType(ctx, userID, model.UserAuthTypeWxh5OpenID)
if findAuthModelErr != nil { if findAuthModelErr != nil {
return "", findAuthModelErr return "", findAuthModelErr
} }
@ -245,7 +245,7 @@ func (w *WechatPayService) CreateWechatOrder(ctx context.Context, amount float64
if err != nil { if err != nil {
return "", err return "", err
} }
case "app": case model.PlatformApp:
// 如果是 APP 平台,调用 APP 支付订单创建 // 如果是 APP 平台,调用 APP 支付订单创建
prepayData, err = w.CreateWechatAppOrder(ctx, amount, description, outTradeNo) prepayData, err = w.CreateWechatAppOrder(ctx, amount, description, outTradeNo)
default: default:

View File

@ -8,7 +8,6 @@ import (
"github.com/hibiken/asynq" "github.com/hibiken/asynq"
"github.com/zeromicro/go-zero/core/logx" "github.com/zeromicro/go-zero/core/logx"
"github.com/zeromicro/go-zero/core/stores/cache"
"github.com/zeromicro/go-zero/core/stores/redis" "github.com/zeromicro/go-zero/core/stores/redis"
"github.com/zeromicro/go-zero/core/stores/sqlx" "github.com/zeromicro/go-zero/core/stores/sqlx"
"github.com/zeromicro/go-zero/rest" "github.com/zeromicro/go-zero/rest"
@ -20,12 +19,13 @@ type ServiceContext struct {
Redis *redis.Redis Redis *redis.Redis
// 中间件 // 中间件
SourceInterceptor rest.Middleware
AuthInterceptor rest.Middleware AuthInterceptor rest.Middleware
UserAuthInterceptor rest.Middleware
// 用户相关模型 // 用户相关模型
UserModel model.UserModel UserModel model.UserModel
UserAuthModel model.UserAuthModel UserAuthModel model.UserAuthModel
UserTempModel model.UserTempModel
// 产品相关模型 // 产品相关模型
ProductModel model.ProductModel ProductModel model.ProductModel
@ -94,185 +94,98 @@ type ServiceContext struct {
AdminPromotionLinkStatsService *service.AdminPromotionLinkStatsService AdminPromotionLinkStatsService *service.AdminPromotionLinkStatsService
} }
// 用户相关模型初始化 // NewServiceContext 创建服务上下文
type userModels struct { func NewServiceContext(c config.Config) *ServiceContext {
UserModel model.UserModel // ============================== 基础设施初始化 ==============================
UserAuthModel model.UserAuthModel db := sqlx.NewMysql(c.DataSource)
} cacheConf := c.CacheRedis
func initUserModels(db sqlx.SqlConn, redis cache.CacheConf) userModels { // 初始化Redis客户端
return userModels{ redisConf := redis.RedisConf{
UserModel: model.NewUserModel(db, redis), Host: cacheConf[0].Host,
UserAuthModel: model.NewUserAuthModel(db, redis), Pass: cacheConf[0].Pass,
Type: cacheConf[0].Type,
} }
} redisClient := redis.MustNewRedis(redisConf)
// 产品相关模型初始化 // ============================== 用户相关模型 ==============================
type productModels struct { userModel := model.NewUserModel(db, cacheConf)
ProductModel model.ProductModel userAuthModel := model.NewUserAuthModel(db, cacheConf)
FeatureModel model.FeatureModel userTempModel := model.NewUserTempModel(db, cacheConf)
ProductFeatureModel model.ProductFeatureModel
}
func initProductModels(db sqlx.SqlConn, redis cache.CacheConf) productModels { // ============================== 产品相关模型 ==============================
return productModels{ productModel := model.NewProductModel(db, cacheConf)
ProductModel: model.NewProductModel(db, redis), featureModel := model.NewFeatureModel(db, cacheConf)
FeatureModel: model.NewFeatureModel(db, redis), productFeatureModel := model.NewProductFeatureModel(db, cacheConf)
ProductFeatureModel: model.NewProductFeatureModel(db, redis),
}
}
// 订单相关模型初始化 // ============================== 订单相关模型 ==============================
type orderModels struct { orderModel := model.NewOrderModel(db, cacheConf)
OrderModel model.OrderModel queryModel := model.NewQueryModel(db, cacheConf)
QueryModel model.QueryModel orderRefundModel := model.NewOrderRefundModel(db, cacheConf)
OrderRefundModel model.OrderRefundModel queryCleanupLogModel := model.NewQueryCleanupLogModel(db, cacheConf)
QueryCleanupLogModel model.QueryCleanupLogModel queryCleanupDetailModel := model.NewQueryCleanupDetailModel(db, cacheConf)
QueryCleanupDetailModel model.QueryCleanupDetailModel queryCleanupConfigModel := model.NewQueryCleanupConfigModel(db, cacheConf)
QueryCleanupConfigModel model.QueryCleanupConfigModel
}
func initOrderModels(db sqlx.SqlConn, redis cache.CacheConf) orderModels { // ============================== 代理相关模型 ==============================
return orderModels{ agentModel := model.NewAgentModel(db, cacheConf)
OrderModel: model.NewOrderModel(db, redis), agentAuditModel := model.NewAgentAuditModel(db, cacheConf)
QueryModel: model.NewQueryModel(db, redis), agentClosureModel := model.NewAgentClosureModel(db, cacheConf)
OrderRefundModel: model.NewOrderRefundModel(db, redis), agentCommissionModel := model.NewAgentCommissionModel(db, cacheConf)
QueryCleanupLogModel: model.NewQueryCleanupLogModel(db, redis), agentCommissionDeductionModel := model.NewAgentCommissionDeductionModel(db, cacheConf)
QueryCleanupDetailModel: model.NewQueryCleanupDetailModel(db, redis), agentWalletModel := model.NewAgentWalletModel(db, cacheConf)
QueryCleanupConfigModel: model.NewQueryCleanupConfigModel(db, redis), agentLinkModel := model.NewAgentLinkModel(db, cacheConf)
} agentOrderModel := model.NewAgentOrderModel(db, cacheConf)
} agentRewardsModel := model.NewAgentRewardsModel(db, cacheConf)
agentMembershipConfigModel := model.NewAgentMembershipConfigModel(db, cacheConf)
agentMembershipRechargeOrderModel := model.NewAgentMembershipRechargeOrderModel(db, cacheConf)
agentMembershipUserConfigModel := model.NewAgentMembershipUserConfigModel(db, cacheConf)
agentProductConfigModel := model.NewAgentProductConfigModel(db, cacheConf)
agentPlatformDeductionModel := model.NewAgentPlatformDeductionModel(db, cacheConf)
agentActiveStatModel := model.NewAgentActiveStatModel(db, cacheConf)
agentWithdrawalModel := model.NewAgentWithdrawalModel(db, cacheConf)
agentRealNameModel := model.NewAgentRealNameModel(db, cacheConf)
// 代理相关模型初始化 // ============================== 管理后台相关模型 ==============================
type agentModels struct { adminApiModel := model.NewAdminApiModel(db, cacheConf)
AgentModel model.AgentModel adminMenuModel := model.NewAdminMenuModel(db, cacheConf)
AgentAuditModel model.AgentAuditModel adminRoleModel := model.NewAdminRoleModel(db, cacheConf)
AgentClosureModel model.AgentClosureModel adminRoleApiModel := model.NewAdminRoleApiModel(db, cacheConf)
AgentCommissionModel model.AgentCommissionModel adminRoleMenuModel := model.NewAdminRoleMenuModel(db, cacheConf)
AgentCommissionDeductionModel model.AgentCommissionDeductionModel adminUserModel := model.NewAdminUserModel(db, cacheConf)
AgentWalletModel model.AgentWalletModel adminUserRoleModel := model.NewAdminUserRoleModel(db, cacheConf)
AgentLinkModel model.AgentLinkModel adminDictDataModel := model.NewAdminDictDataModel(db, cacheConf)
AgentOrderModel model.AgentOrderModel adminDictTypeModel := model.NewAdminDictTypeModel(db, cacheConf)
AgentRewardsModel model.AgentRewardsModel adminPromotionLinkModel := model.NewAdminPromotionLinkModel(db, cacheConf)
AgentMembershipConfigModel model.AgentMembershipConfigModel adminPromotionLinkStatsTotalModel := model.NewAdminPromotionLinkStatsTotalModel(db, cacheConf)
AgentMembershipRechargeOrderModel model.AgentMembershipRechargeOrderModel adminPromotionLinkStatsHistoryModel := model.NewAdminPromotionLinkStatsHistoryModel(db, cacheConf)
AgentMembershipUserConfigModel model.AgentMembershipUserConfigModel adminPromotionOrderModel := model.NewAdminPromotionOrderModel(db, cacheConf)
AgentProductConfigModel model.AgentProductConfigModel
AgentPlatformDeductionModel model.AgentPlatformDeductionModel
AgentActiveStatModel model.AgentActiveStatModel
AgentWithdrawalModel model.AgentWithdrawalModel
AgentRealNameModel model.AgentRealNameModel
}
func initAgentModels(db sqlx.SqlConn, redis cache.CacheConf) agentModels { // ============================== 其他模型 ==============================
return agentModels{ exampleModel := model.NewExampleModel(db, cacheConf)
AgentModel: model.NewAgentModel(db, redis), globalNotificationsModel := model.NewGlobalNotificationsModel(db, cacheConf)
AgentAuditModel: model.NewAgentAuditModel(db, redis),
AgentClosureModel: model.NewAgentClosureModel(db, redis),
AgentCommissionModel: model.NewAgentCommissionModel(db, redis),
AgentCommissionDeductionModel: model.NewAgentCommissionDeductionModel(db, redis),
AgentWalletModel: model.NewAgentWalletModel(db, redis),
AgentLinkModel: model.NewAgentLinkModel(db, redis),
AgentOrderModel: model.NewAgentOrderModel(db, redis),
AgentRewardsModel: model.NewAgentRewardsModel(db, redis),
AgentMembershipConfigModel: model.NewAgentMembershipConfigModel(db, redis),
AgentMembershipRechargeOrderModel: model.NewAgentMembershipRechargeOrderModel(db, redis),
AgentMembershipUserConfigModel: model.NewAgentMembershipUserConfigModel(db, redis),
AgentProductConfigModel: model.NewAgentProductConfigModel(db, redis),
AgentPlatformDeductionModel: model.NewAgentPlatformDeductionModel(db, redis),
AgentActiveStatModel: model.NewAgentActiveStatModel(db, redis),
AgentWithdrawalModel: model.NewAgentWithdrawalModel(db, redis),
AgentRealNameModel: model.NewAgentRealNameModel(db, redis),
}
}
// 管理后台相关模型初始化 // ============================== 第三方服务初始化 ==============================
type adminModels struct { westDexService := service.NewWestDexService(c)
AdminApiModel model.AdminApiModel yushanService := service.NewYushanService(c)
AdminMenuModel model.AdminMenuModel
AdminRoleModel model.AdminRoleModel
AdminRoleApiModel model.AdminRoleApiModel
AdminRoleMenuModel model.AdminRoleMenuModel
AdminUserModel model.AdminUserModel
AdminUserRoleModel model.AdminUserRoleModel
AdminDictDataModel model.AdminDictDataModel
AdminDictTypeModel model.AdminDictTypeModel
AdminPromotionLinkModel model.AdminPromotionLinkModel
AdminPromotionLinkStatsTotalModel model.AdminPromotionLinkStatsTotalModel
AdminPromotionLinkStatsHistoryModel model.AdminPromotionLinkStatsHistoryModel
AdminPromotionOrderModel model.AdminPromotionOrderModel
}
func initAdminModels(db sqlx.SqlConn, redis cache.CacheConf) adminModels {
return adminModels{
AdminApiModel: model.NewAdminApiModel(db, redis),
AdminMenuModel: model.NewAdminMenuModel(db, redis),
AdminRoleModel: model.NewAdminRoleModel(db, redis),
AdminRoleApiModel: model.NewAdminRoleApiModel(db, redis),
AdminRoleMenuModel: model.NewAdminRoleMenuModel(db, redis),
AdminUserModel: model.NewAdminUserModel(db, redis),
AdminUserRoleModel: model.NewAdminUserRoleModel(db, redis),
AdminDictDataModel: model.NewAdminDictDataModel(db, redis),
AdminDictTypeModel: model.NewAdminDictTypeModel(db, redis),
AdminPromotionLinkModel: model.NewAdminPromotionLinkModel(db, redis),
AdminPromotionLinkStatsTotalModel: model.NewAdminPromotionLinkStatsTotalModel(db, redis),
AdminPromotionLinkStatsHistoryModel: model.NewAdminPromotionLinkStatsHistoryModel(db, redis),
AdminPromotionOrderModel: model.NewAdminPromotionOrderModel(db, redis),
}
}
// 其他模型初始化
type otherModels struct {
ExampleModel model.ExampleModel
GlobalNotificationsModel model.GlobalNotificationsModel
}
func initOtherModels(db sqlx.SqlConn, redis cache.CacheConf) otherModels {
return otherModels{
ExampleModel: model.NewExampleModel(db, redis),
GlobalNotificationsModel: model.NewGlobalNotificationsModel(db, redis),
}
}
// 服务初始化
type services struct {
AlipayService *service.AliPayService
WechatPayService *service.WechatPayService
ApplePayService *service.ApplePayService
WestDexService *service.WestDexService
YushanService *service.YushanService
ApiRequestService *service.ApiRequestService
AsynqServer *asynq.Server
AsynqService *service.AsynqService
VerificationService *service.VerificationService
AgentService *service.AgentService
UserService *service.UserService
DictService *service.DictService
AdminPromotionLinkStatsService *service.AdminPromotionLinkStatsService
}
func initServices(c config.Config, userAuthModel model.UserAuthModel, westDexService *service.WestDexService,
yushanService *service.YushanService, featureModel model.FeatureModel,
productFeatureModel model.ProductFeatureModel, agentModels agentModels,
userModels userModels, adminModels adminModels) services {
// ============================== 业务服务初始化 ==============================
alipayService := service.NewAliPayService(c) alipayService := service.NewAliPayService(c)
wechatPayService := service.NewWechatPayService(c, userAuthModel, service.InitTypeWxPayPubKey) wechatPayService := service.NewWechatPayService(c, userAuthModel, service.InitTypeWxPayPubKey)
applePayService := service.NewApplePayService(c) applePayService := service.NewApplePayService(c)
apiRequestService := service.NewApiRequestService(c, westDexService, yushanService, featureModel, productFeatureModel) apiRequestService := service.NewApiRequestService(c, westDexService, yushanService, featureModel, productFeatureModel)
verificationService := service.NewVerificationService(c, westDexService, apiRequestService) verificationService := service.NewVerificationService(c, westDexService, apiRequestService)
asynqService := service.NewAsynqService(c) asynqService := service.NewAsynqService(c)
agentService := service.NewAgentService(c, agentModels.AgentModel, agentModels.AgentAuditModel, agentService := service.NewAgentService(c, agentModel, agentAuditModel, agentClosureModel,
agentModels.AgentClosureModel, agentModels.AgentCommissionModel, agentCommissionModel, agentCommissionDeductionModel, agentWalletModel, agentLinkModel,
agentModels.AgentCommissionDeductionModel, agentModels.AgentWalletModel, agentOrderModel, agentRewardsModel, agentMembershipConfigModel, agentMembershipRechargeOrderModel,
agentModels.AgentLinkModel, agentModels.AgentOrderModel, agentModels.AgentRewardsModel, agentMembershipUserConfigModel, agentProductConfigModel, agentPlatformDeductionModel,
agentModels.AgentMembershipConfigModel, agentModels.AgentMembershipRechargeOrderModel, agentActiveStatModel, agentWithdrawalModel)
agentModels.AgentMembershipUserConfigModel, agentModels.AgentProductConfigModel, userService := service.NewUserService(&c, userModel, userAuthModel, userTempModel, agentModel)
agentModels.AgentPlatformDeductionModel, agentModels.AgentActiveStatModel, dictService := service.NewDictService(adminDictTypeModel, adminDictDataModel)
agentModels.AgentWithdrawalModel) adminPromotionLinkStatsService := service.NewAdminPromotionLinkStatsService(adminPromotionLinkModel,
userService := service.NewUserService(userModels.UserModel, userModels.UserAuthModel) adminPromotionLinkStatsTotalModel, adminPromotionLinkStatsHistoryModel)
dictService := service.NewDictService(adminModels.AdminDictTypeModel, adminModels.AdminDictDataModel)
AdminPromotionLinkStatsService := service.NewAdminPromotionLinkStatsService(adminModels.AdminPromotionLinkModel, adminModels.AdminPromotionLinkStatsTotalModel, adminModels.AdminPromotionLinkStatsHistoryModel) // ============================== 异步任务服务 ==============================
asynqServer := asynq.NewServer( asynqServer := asynq.NewServer(
asynq.RedisClientOpt{Addr: c.CacheRedis[0].Host, Password: c.CacheRedis[0].Pass}, asynq.RedisClientOpt{Addr: c.CacheRedis[0].Host, Password: c.CacheRedis[0].Pass},
asynq.Config{ asynq.Config{
@ -284,7 +197,70 @@ wechatPayService := service.NewWechatPayService(c, userAuthModel, service.InitTy
}, },
) )
return services{ // ============================== 返回服务上下文 ==============================
return &ServiceContext{
Config: c,
Redis: redisClient,
AuthInterceptor: middleware.NewAuthInterceptorMiddleware(c).Handle,
UserAuthInterceptor: middleware.NewUserAuthInterceptorMiddleware().Handle,
// 用户相关模型
UserModel: userModel,
UserAuthModel: userAuthModel,
UserTempModel: userTempModel,
// 产品相关模型
ProductModel: productModel,
FeatureModel: featureModel,
ProductFeatureModel: productFeatureModel,
// 订单相关模型
OrderModel: orderModel,
QueryModel: queryModel,
OrderRefundModel: orderRefundModel,
QueryCleanupLogModel: queryCleanupLogModel,
QueryCleanupDetailModel: queryCleanupDetailModel,
QueryCleanupConfigModel: queryCleanupConfigModel,
// 代理相关模型
AgentModel: agentModel,
AgentAuditModel: agentAuditModel,
AgentClosureModel: agentClosureModel,
AgentCommissionModel: agentCommissionModel,
AgentCommissionDeductionModel: agentCommissionDeductionModel,
AgentWalletModel: agentWalletModel,
AgentLinkModel: agentLinkModel,
AgentOrderModel: agentOrderModel,
AgentRewardsModel: agentRewardsModel,
AgentMembershipConfigModel: agentMembershipConfigModel,
AgentMembershipRechargeOrderModel: agentMembershipRechargeOrderModel,
AgentMembershipUserConfigModel: agentMembershipUserConfigModel,
AgentProductConfigModel: agentProductConfigModel,
AgentPlatformDeductionModel: agentPlatformDeductionModel,
AgentActiveStatModel: agentActiveStatModel,
AgentWithdrawalModel: agentWithdrawalModel,
AgentRealNameModel: agentRealNameModel,
// 管理后台相关模型
AdminApiModel: adminApiModel,
AdminMenuModel: adminMenuModel,
AdminRoleModel: adminRoleModel,
AdminRoleApiModel: adminRoleApiModel,
AdminRoleMenuModel: adminRoleMenuModel,
AdminUserModel: adminUserModel,
AdminUserRoleModel: adminUserRoleModel,
AdminDictDataModel: adminDictDataModel,
AdminDictTypeModel: adminDictTypeModel,
AdminPromotionLinkModel: adminPromotionLinkModel,
AdminPromotionLinkStatsTotalModel: adminPromotionLinkStatsTotalModel,
AdminPromotionLinkStatsHistoryModel: adminPromotionLinkStatsHistoryModel,
AdminPromotionOrderModel: adminPromotionOrderModel,
// 其他模型
ExampleModel: exampleModel,
GlobalNotificationsModel: globalNotificationsModel,
// 服务
AlipayService: alipayService, AlipayService: alipayService,
WechatPayService: wechatPayService, WechatPayService: wechatPayService,
ApplePayService: applePayService, ApplePayService: applePayService,
@ -297,115 +273,7 @@ wechatPayService := service.NewWechatPayService(c, userAuthModel, service.InitTy
AgentService: agentService, AgentService: agentService,
UserService: userService, UserService: userService,
DictService: dictService, DictService: dictService,
AdminPromotionLinkStatsService: AdminPromotionLinkStatsService, AdminPromotionLinkStatsService: adminPromotionLinkStatsService,
}
}
// NewServiceContext 创建服务上下文
func NewServiceContext(c config.Config) *ServiceContext {
db := sqlx.NewMysql(c.DataSource)
// 使用配置中的CacheRedis配置
cacheConf := c.CacheRedis
// 初始化Redis客户端用于异步任务等
redisConf := redis.RedisConf{
Host: cacheConf[0].Host,
Pass: cacheConf[0].Pass,
Type: cacheConf[0].Type,
}
redisClient := redis.MustNewRedis(redisConf)
// 初始化各个模块的模型
userModels := initUserModels(db, cacheConf)
productModels := initProductModels(db, cacheConf)
orderModels := initOrderModels(db, cacheConf)
agentModels := initAgentModels(db, cacheConf)
adminModels := initAdminModels(db, cacheConf)
otherModels := initOtherModels(db, cacheConf)
// 初始化第三方服务
westDexService := service.NewWestDexService(c)
yushanService := service.NewYushanService(c)
// 初始化所有服务
services := initServices(c, userModels.UserAuthModel, westDexService, yushanService,
productModels.FeatureModel, productModels.ProductFeatureModel, agentModels, userModels, adminModels)
return &ServiceContext{
Config: c,
Redis: redisClient,
SourceInterceptor: middleware.NewSourceInterceptorMiddleware().Handle,
AuthInterceptor: middleware.NewAuthInterceptorMiddleware(c).Handle,
// 用户相关模型
UserModel: userModels.UserModel,
UserAuthModel: userModels.UserAuthModel,
// 产品相关模型
ProductModel: productModels.ProductModel,
FeatureModel: productModels.FeatureModel,
ProductFeatureModel: productModels.ProductFeatureModel,
// 订单相关模型
OrderModel: orderModels.OrderModel,
QueryModel: orderModels.QueryModel,
OrderRefundModel: orderModels.OrderRefundModel,
QueryCleanupLogModel: orderModels.QueryCleanupLogModel,
QueryCleanupDetailModel: orderModels.QueryCleanupDetailModel,
QueryCleanupConfigModel: orderModels.QueryCleanupConfigModel,
// 代理相关模型
AgentModel: agentModels.AgentModel,
AgentAuditModel: agentModels.AgentAuditModel,
AgentClosureModel: agentModels.AgentClosureModel,
AgentCommissionModel: agentModels.AgentCommissionModel,
AgentCommissionDeductionModel: agentModels.AgentCommissionDeductionModel,
AgentWalletModel: agentModels.AgentWalletModel,
AgentLinkModel: agentModels.AgentLinkModel,
AgentOrderModel: agentModels.AgentOrderModel,
AgentRewardsModel: agentModels.AgentRewardsModel,
AgentMembershipConfigModel: agentModels.AgentMembershipConfigModel,
AgentMembershipRechargeOrderModel: agentModels.AgentMembershipRechargeOrderModel,
AgentMembershipUserConfigModel: agentModels.AgentMembershipUserConfigModel,
AgentProductConfigModel: agentModels.AgentProductConfigModel,
AgentPlatformDeductionModel: agentModels.AgentPlatformDeductionModel,
AgentActiveStatModel: agentModels.AgentActiveStatModel,
AgentWithdrawalModel: agentModels.AgentWithdrawalModel,
AgentRealNameModel: agentModels.AgentRealNameModel,
// 管理后台相关模型
AdminApiModel: adminModels.AdminApiModel,
AdminMenuModel: adminModels.AdminMenuModel,
AdminRoleModel: adminModels.AdminRoleModel,
AdminRoleApiModel: adminModels.AdminRoleApiModel,
AdminRoleMenuModel: adminModels.AdminRoleMenuModel,
AdminUserModel: adminModels.AdminUserModel,
AdminUserRoleModel: adminModels.AdminUserRoleModel,
AdminDictDataModel: adminModels.AdminDictDataModel,
AdminDictTypeModel: adminModels.AdminDictTypeModel,
AdminPromotionLinkModel: adminModels.AdminPromotionLinkModel,
AdminPromotionLinkStatsTotalModel: adminModels.AdminPromotionLinkStatsTotalModel,
AdminPromotionLinkStatsHistoryModel: adminModels.AdminPromotionLinkStatsHistoryModel,
AdminPromotionOrderModel: adminModels.AdminPromotionOrderModel,
// 其他模型
ExampleModel: otherModels.ExampleModel,
GlobalNotificationsModel: otherModels.GlobalNotificationsModel,
// 服务
AlipayService: services.AlipayService,
WechatPayService: services.WechatPayService,
ApplePayService: services.ApplePayService,
WestDexService: services.WestDexService,
YushanService: services.YushanService,
ApiRequestService: services.ApiRequestService,
AsynqServer: services.AsynqServer,
AsynqService: services.AsynqService,
VerificationService: services.VerificationService,
AgentService: services.AgentService,
UserService: services.UserService,
DictService: services.DictService,
AdminPromotionLinkStatsService: services.AdminPromotionLinkStatsService,
} }
} }

View File

@ -962,6 +962,9 @@ type BindMobileReq struct {
} }
type BindMobileResp struct { type BindMobileResp struct {
AccessToken string `json:"accessToken"`
AccessExpire int64 `json:"accessExpire"`
RefreshAfter int64 `json:"refreshAfter"`
} }
type Commission struct { type Commission struct {
@ -1293,17 +1296,6 @@ type MobileCodeLoginResp struct {
RefreshAfter int64 `json:"refreshAfter"` RefreshAfter int64 `json:"refreshAfter"`
} }
type MobileLoginReq struct {
Mobile string `json:"mobile" validate:"required,mobile"`
Password string `json:"password" validate:"required"`
}
type MobileLoginResp struct {
AccessToken string `json:"accessToken"`
AccessExpire int64 `json:"accessExpire"`
RefreshAfter int64 `json:"refreshAfter"`
}
type Notification struct { type Notification struct {
Title string `json:"title"` // 通知标题 Title string `json:"title"` // 通知标题
Content string `json:"content"` // 通知内容 (富文本) Content string `json:"content"` // 通知内容 (富文本)
@ -1596,18 +1588,6 @@ type RecordLinkClickResp struct {
Success bool `json:"success"` // 是否成功 Success bool `json:"success"` // 是否成功
} }
type RegisterReq struct {
Mobile string `json:"mobile" validate:"required,mobile"`
Password string `json:"password" validate:"required,min=11,max=11,password"`
Code string `json:"code" validate:"required"`
}
type RegisterResp struct {
AccessToken string `json:"accessToken"`
AccessExpire int64 `json:"accessExpire"`
RefreshAfter int64 `json:"refreshAfter"`
}
type Rewards struct { type Rewards struct {
Type string `json:"type"` Type string `json:"type"`
Amount float64 `json:"amount"` Amount float64 `json:"amount"`
@ -1692,6 +1672,7 @@ type User struct {
Id int64 `json:"id"` Id int64 `json:"id"`
Mobile string `json:"mobile"` Mobile string `json:"mobile"`
NickName string `json:"nickName"` NickName string `json:"nickName"`
UserType int64 `json:"userType"`
} }
type UserInfoResp struct { type UserInfoResp struct {

View File

@ -7,6 +7,7 @@ import (
"os" "os"
"tydata-server/app/main/api/internal/config" "tydata-server/app/main/api/internal/config"
"tydata-server/app/main/api/internal/handler" "tydata-server/app/main/api/internal/handler"
"tydata-server/app/main/api/internal/middleware"
"tydata-server/app/main/api/internal/queue" "tydata-server/app/main/api/internal/queue"
"tydata-server/app/main/api/internal/svc" "tydata-server/app/main/api/internal/svc"
@ -55,6 +56,7 @@ func main() {
}() }()
server := rest.MustNewServer(c.RestConf) server := rest.MustNewServer(c.RestConf)
server.Use(middleware.GlobalSourceInterceptor)
defer server.Stop() defer server.Stop()
handler.RegisterHandlers(server, svcContext) handler.RegisterHandlers(server, svcContext)

View File

@ -0,0 +1,27 @@
package model
import (
"github.com/zeromicro/go-zero/core/stores/cache"
"github.com/zeromicro/go-zero/core/stores/sqlx"
)
var _ UserTempModel = (*customUserTempModel)(nil)
type (
// UserTempModel is an interface to be customized, add more methods here,
// and implement the added methods in customUserTempModel.
UserTempModel interface {
userTempModel
}
customUserTempModel struct {
*defaultUserTempModel
}
)
// NewUserTempModel returns a model for the database table.
func NewUserTempModel(conn sqlx.SqlConn, c cache.CacheConf) UserTempModel {
return &customUserTempModel{
defaultUserTempModel: newUserTempModel(conn, c),
}
}

View File

@ -0,0 +1,407 @@
// Code generated by goctl. DO NOT EDIT!
package model
import (
"context"
"database/sql"
"fmt"
"strings"
"time"
"github.com/Masterminds/squirrel"
"github.com/pkg/errors"
"github.com/zeromicro/go-zero/core/stores/builder"
"github.com/zeromicro/go-zero/core/stores/cache"
"github.com/zeromicro/go-zero/core/stores/sqlc"
"github.com/zeromicro/go-zero/core/stores/sqlx"
"github.com/zeromicro/go-zero/core/stringx"
"tydata-server/common/globalkey"
)
var (
userTempFieldNames = builder.RawFieldNames(&UserTemp{})
userTempRows = strings.Join(userTempFieldNames, ",")
userTempRowsExpectAutoSet = strings.Join(stringx.Remove(userTempFieldNames, "`id`", "`create_time`", "`update_time`"), ",")
userTempRowsWithPlaceHolder = strings.Join(stringx.Remove(userTempFieldNames, "`id`", "`create_time`", "`update_time`"), "=?,") + "=?"
cacheTydataUserTempIdPrefix = "cache:tydata:userTemp:id:"
cacheTydataUserTempAuthTypeAuthKeyPrefix = "cache:tydata:userTemp:authType:authKey:"
)
type (
userTempModel interface {
Insert(ctx context.Context, session sqlx.Session, data *UserTemp) (sql.Result, error)
FindOne(ctx context.Context, id int64) (*UserTemp, error)
FindOneByAuthTypeAuthKey(ctx context.Context, authType string, authKey string) (*UserTemp, error)
Update(ctx context.Context, session sqlx.Session, data *UserTemp) (sql.Result, error)
UpdateWithVersion(ctx context.Context, session sqlx.Session, data *UserTemp) error
Trans(ctx context.Context, fn func(context context.Context, session sqlx.Session) error) error
SelectBuilder() squirrel.SelectBuilder
DeleteSoft(ctx context.Context, session sqlx.Session, data *UserTemp) error
FindSum(ctx context.Context, sumBuilder squirrel.SelectBuilder, field string) (float64, error)
FindCount(ctx context.Context, countBuilder squirrel.SelectBuilder, field string) (int64, error)
FindAll(ctx context.Context, rowBuilder squirrel.SelectBuilder, orderBy string) ([]*UserTemp, error)
FindPageListByPage(ctx context.Context, rowBuilder squirrel.SelectBuilder, page, pageSize int64, orderBy string) ([]*UserTemp, error)
FindPageListByPageWithTotal(ctx context.Context, rowBuilder squirrel.SelectBuilder, page, pageSize int64, orderBy string) ([]*UserTemp, int64, error)
FindPageListByIdDESC(ctx context.Context, rowBuilder squirrel.SelectBuilder, preMinId, pageSize int64) ([]*UserTemp, error)
FindPageListByIdASC(ctx context.Context, rowBuilder squirrel.SelectBuilder, preMaxId, pageSize int64) ([]*UserTemp, error)
Delete(ctx context.Context, session sqlx.Session, id int64) error
}
defaultUserTempModel struct {
sqlc.CachedConn
table string
}
UserTemp struct {
Id int64 `db:"id"`
AuthKey string `db:"auth_key"` // 平台唯一id
AuthType string `db:"auth_type"` // 平台类型
CreateTime time.Time `db:"create_time"`
UpdateTime time.Time `db:"update_time"`
DeleteTime sql.NullTime `db:"delete_time"` // 删除时间
DelState int64 `db:"del_state"`
Version int64 `db:"version"` // 版本号
}
)
func newUserTempModel(conn sqlx.SqlConn, c cache.CacheConf) *defaultUserTempModel {
return &defaultUserTempModel{
CachedConn: sqlc.NewConn(conn, c),
table: "`user_temp`",
}
}
func (m *defaultUserTempModel) Insert(ctx context.Context, session sqlx.Session, data *UserTemp) (sql.Result, error) {
data.DelState = globalkey.DelStateNo
tydataUserTempAuthTypeAuthKeyKey := fmt.Sprintf("%s%v:%v", cacheTydataUserTempAuthTypeAuthKeyPrefix, data.AuthType, data.AuthKey)
tydataUserTempIdKey := fmt.Sprintf("%s%v", cacheTydataUserTempIdPrefix, data.Id)
return m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) {
query := fmt.Sprintf("insert into %s (%s) values (?, ?, ?, ?, ?)", m.table, userTempRowsExpectAutoSet)
if session != nil {
return session.ExecCtx(ctx, query, data.AuthKey, data.AuthType, data.DeleteTime, data.DelState, data.Version)
}
return conn.ExecCtx(ctx, query, data.AuthKey, data.AuthType, data.DeleteTime, data.DelState, data.Version)
}, tydataUserTempAuthTypeAuthKeyKey, tydataUserTempIdKey)
}
func (m *defaultUserTempModel) FindOne(ctx context.Context, id int64) (*UserTemp, error) {
tydataUserTempIdKey := fmt.Sprintf("%s%v", cacheTydataUserTempIdPrefix, id)
var resp UserTemp
err := m.QueryRowCtx(ctx, &resp, tydataUserTempIdKey, func(ctx context.Context, conn sqlx.SqlConn, v interface{}) error {
query := fmt.Sprintf("select %s from %s where `id` = ? and del_state = ? limit 1", userTempRows, m.table)
return conn.QueryRowCtx(ctx, v, query, id, globalkey.DelStateNo)
})
switch err {
case nil:
return &resp, nil
case sqlc.ErrNotFound:
return nil, ErrNotFound
default:
return nil, err
}
}
func (m *defaultUserTempModel) FindOneByAuthTypeAuthKey(ctx context.Context, authType string, authKey string) (*UserTemp, error) {
tydataUserTempAuthTypeAuthKeyKey := fmt.Sprintf("%s%v:%v", cacheTydataUserTempAuthTypeAuthKeyPrefix, authType, authKey)
var resp UserTemp
err := m.QueryRowIndexCtx(ctx, &resp, tydataUserTempAuthTypeAuthKeyKey, m.formatPrimary, func(ctx context.Context, conn sqlx.SqlConn, v interface{}) (i interface{}, e error) {
query := fmt.Sprintf("select %s from %s where `auth_type` = ? and `auth_key` = ? and del_state = ? limit 1", userTempRows, m.table)
if err := conn.QueryRowCtx(ctx, &resp, query, authType, authKey, globalkey.DelStateNo); err != nil {
return nil, err
}
return resp.Id, nil
}, m.queryPrimary)
switch err {
case nil:
return &resp, nil
case sqlc.ErrNotFound:
return nil, ErrNotFound
default:
return nil, err
}
}
func (m *defaultUserTempModel) Update(ctx context.Context, session sqlx.Session, newData *UserTemp) (sql.Result, error) {
data, err := m.FindOne(ctx, newData.Id)
if err != nil {
return nil, err
}
tydataUserTempAuthTypeAuthKeyKey := fmt.Sprintf("%s%v:%v", cacheTydataUserTempAuthTypeAuthKeyPrefix, data.AuthType, data.AuthKey)
tydataUserTempIdKey := fmt.Sprintf("%s%v", cacheTydataUserTempIdPrefix, data.Id)
return m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) {
query := fmt.Sprintf("update %s set %s where `id` = ?", m.table, userTempRowsWithPlaceHolder)
if session != nil {
return session.ExecCtx(ctx, query, newData.AuthKey, newData.AuthType, newData.DeleteTime, newData.DelState, newData.Version, newData.Id)
}
return conn.ExecCtx(ctx, query, newData.AuthKey, newData.AuthType, newData.DeleteTime, newData.DelState, newData.Version, newData.Id)
}, tydataUserTempAuthTypeAuthKeyKey, tydataUserTempIdKey)
}
func (m *defaultUserTempModel) UpdateWithVersion(ctx context.Context, session sqlx.Session, newData *UserTemp) error {
oldVersion := newData.Version
newData.Version += 1
var sqlResult sql.Result
var err error
data, err := m.FindOne(ctx, newData.Id)
if err != nil {
return err
}
tydataUserTempAuthTypeAuthKeyKey := fmt.Sprintf("%s%v:%v", cacheTydataUserTempAuthTypeAuthKeyPrefix, data.AuthType, data.AuthKey)
tydataUserTempIdKey := fmt.Sprintf("%s%v", cacheTydataUserTempIdPrefix, data.Id)
sqlResult, err = m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) {
query := fmt.Sprintf("update %s set %s where `id` = ? and version = ? ", m.table, userTempRowsWithPlaceHolder)
if session != nil {
return session.ExecCtx(ctx, query, newData.AuthKey, newData.AuthType, newData.DeleteTime, newData.DelState, newData.Version, newData.Id, oldVersion)
}
return conn.ExecCtx(ctx, query, newData.AuthKey, newData.AuthType, newData.DeleteTime, newData.DelState, newData.Version, newData.Id, oldVersion)
}, tydataUserTempAuthTypeAuthKeyKey, tydataUserTempIdKey)
if err != nil {
return err
}
updateCount, err := sqlResult.RowsAffected()
if err != nil {
return err
}
if updateCount == 0 {
return ErrNoRowsUpdate
}
return nil
}
func (m *defaultUserTempModel) DeleteSoft(ctx context.Context, session sqlx.Session, data *UserTemp) error {
data.DelState = globalkey.DelStateYes
data.DeleteTime = sql.NullTime{Time: time.Now(), Valid: true}
if err := m.UpdateWithVersion(ctx, session, data); err != nil {
return errors.Wrapf(errors.New("delete soft failed "), "UserTempModel delete err : %+v", err)
}
return nil
}
func (m *defaultUserTempModel) FindSum(ctx context.Context, builder squirrel.SelectBuilder, field string) (float64, error) {
if len(field) == 0 {
return 0, errors.Wrapf(errors.New("FindSum Least One Field"), "FindSum Least One Field")
}
builder = builder.Columns("IFNULL(SUM(" + field + "),0)")
query, values, err := builder.Where("del_state = ?", globalkey.DelStateNo).ToSql()
if err != nil {
return 0, err
}
var resp float64
err = m.QueryRowNoCacheCtx(ctx, &resp, query, values...)
switch err {
case nil:
return resp, nil
default:
return 0, err
}
}
func (m *defaultUserTempModel) FindCount(ctx context.Context, builder squirrel.SelectBuilder, field string) (int64, error) {
if len(field) == 0 {
return 0, errors.Wrapf(errors.New("FindCount Least One Field"), "FindCount Least One Field")
}
builder = builder.Columns("COUNT(" + field + ")")
query, values, err := builder.Where("del_state = ?", globalkey.DelStateNo).ToSql()
if err != nil {
return 0, err
}
var resp int64
err = m.QueryRowNoCacheCtx(ctx, &resp, query, values...)
switch err {
case nil:
return resp, nil
default:
return 0, err
}
}
func (m *defaultUserTempModel) FindAll(ctx context.Context, builder squirrel.SelectBuilder, orderBy string) ([]*UserTemp, error) {
builder = builder.Columns(userTempRows)
if orderBy == "" {
builder = builder.OrderBy("id DESC")
} else {
builder = builder.OrderBy(orderBy)
}
query, values, err := builder.Where("del_state = ?", globalkey.DelStateNo).ToSql()
if err != nil {
return nil, err
}
var resp []*UserTemp
err = m.QueryRowsNoCacheCtx(ctx, &resp, query, values...)
switch err {
case nil:
return resp, nil
default:
return nil, err
}
}
func (m *defaultUserTempModel) FindPageListByPage(ctx context.Context, builder squirrel.SelectBuilder, page, pageSize int64, orderBy string) ([]*UserTemp, error) {
builder = builder.Columns(userTempRows)
if orderBy == "" {
builder = builder.OrderBy("id DESC")
} else {
builder = builder.OrderBy(orderBy)
}
if page < 1 {
page = 1
}
offset := (page - 1) * pageSize
query, values, err := builder.Where("del_state = ?", globalkey.DelStateNo).Offset(uint64(offset)).Limit(uint64(pageSize)).ToSql()
if err != nil {
return nil, err
}
var resp []*UserTemp
err = m.QueryRowsNoCacheCtx(ctx, &resp, query, values...)
switch err {
case nil:
return resp, nil
default:
return nil, err
}
}
func (m *defaultUserTempModel) FindPageListByPageWithTotal(ctx context.Context, builder squirrel.SelectBuilder, page, pageSize int64, orderBy string) ([]*UserTemp, int64, error) {
total, err := m.FindCount(ctx, builder, "id")
if err != nil {
return nil, 0, err
}
builder = builder.Columns(userTempRows)
if orderBy == "" {
builder = builder.OrderBy("id DESC")
} else {
builder = builder.OrderBy(orderBy)
}
if page < 1 {
page = 1
}
offset := (page - 1) * pageSize
query, values, err := builder.Where("del_state = ?", globalkey.DelStateNo).Offset(uint64(offset)).Limit(uint64(pageSize)).ToSql()
if err != nil {
return nil, total, err
}
var resp []*UserTemp
err = m.QueryRowsNoCacheCtx(ctx, &resp, query, values...)
switch err {
case nil:
return resp, total, nil
default:
return nil, total, err
}
}
func (m *defaultUserTempModel) FindPageListByIdDESC(ctx context.Context, builder squirrel.SelectBuilder, preMinId, pageSize int64) ([]*UserTemp, error) {
builder = builder.Columns(userTempRows)
if preMinId > 0 {
builder = builder.Where(" id < ? ", preMinId)
}
query, values, err := builder.Where("del_state = ?", globalkey.DelStateNo).OrderBy("id DESC").Limit(uint64(pageSize)).ToSql()
if err != nil {
return nil, err
}
var resp []*UserTemp
err = m.QueryRowsNoCacheCtx(ctx, &resp, query, values...)
switch err {
case nil:
return resp, nil
default:
return nil, err
}
}
func (m *defaultUserTempModel) FindPageListByIdASC(ctx context.Context, builder squirrel.SelectBuilder, preMaxId, pageSize int64) ([]*UserTemp, error) {
builder = builder.Columns(userTempRows)
if preMaxId > 0 {
builder = builder.Where(" id > ? ", preMaxId)
}
query, values, err := builder.Where("del_state = ?", globalkey.DelStateNo).OrderBy("id ASC").Limit(uint64(pageSize)).ToSql()
if err != nil {
return nil, err
}
var resp []*UserTemp
err = m.QueryRowsNoCacheCtx(ctx, &resp, query, values...)
switch err {
case nil:
return resp, nil
default:
return nil, err
}
}
func (m *defaultUserTempModel) Trans(ctx context.Context, fn func(ctx context.Context, session sqlx.Session) error) error {
return m.TransactCtx(ctx, func(ctx context.Context, session sqlx.Session) error {
return fn(ctx, session)
})
}
func (m *defaultUserTempModel) SelectBuilder() squirrel.SelectBuilder {
return squirrel.Select().From(m.table)
}
func (m *defaultUserTempModel) Delete(ctx context.Context, session sqlx.Session, id int64) error {
data, err := m.FindOne(ctx, id)
if err != nil {
return err
}
tydataUserTempAuthTypeAuthKeyKey := fmt.Sprintf("%s%v:%v", cacheTydataUserTempAuthTypeAuthKeyPrefix, data.AuthType, data.AuthKey)
tydataUserTempIdKey := fmt.Sprintf("%s%v", cacheTydataUserTempIdPrefix, id)
_, err = m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) {
query := fmt.Sprintf("delete from %s where `id` = ?", m.table)
if session != nil {
return session.ExecCtx(ctx, query, id)
}
return conn.ExecCtx(ctx, query, id)
}, tydataUserTempAuthTypeAuthKeyKey, tydataUserTempIdKey)
return err
}
func (m *defaultUserTempModel) formatPrimary(primary interface{}) string {
return fmt.Sprintf("%s%v", cacheTydataUserTempIdPrefix, primary)
}
func (m *defaultUserTempModel) queryPrimary(ctx context.Context, conn sqlx.SqlConn, v, primary interface{}) error {
query := fmt.Sprintf("select %s from %s where `id` = ? and del_state = ? limit 1", userTempRows, m.table)
return conn.QueryRowCtx(ctx, v, query, primary, globalkey.DelStateNo)
}
func (m *defaultUserTempModel) tableName() string {
return m.table
}

View File

@ -9,15 +9,20 @@ import (
var ErrNotFound = sqlx.ErrNotFound var ErrNotFound = sqlx.ErrNotFound
var ErrNoRowsUpdate = errors.New("update db no rows change") var ErrNoRowsUpdate = errors.New("update db no rows change")
var UserAuthTypeAppMobile string = "app_mobile" //平台内部 // 平台
var UserAuthTypeAppWechat string = "app_wechat" //微信小程序 var PlatformWxMini string = "wxmini"
var UserAuthTypeH5Mobile string = "h5_mobile" var PlatformWxH5 string = "wxh5"
var UserAuthTypeWxMini string = "wx_mini" var PlatformApp string = "app"
var UserAuthTypeWxh5 string = "wx_h5" var PlatformH5 string = "h5"
var UserAuthTypeAgentDirect string = "agent_direct" var PlatformAdmin string = "admin"
var UserAuthTypeAgentPromote string = "agent_promote"
// 用户授权类型
var UserAuthTypeMobile string = "mobile"
var UserAuthTypeWxMiniOpenID string = "wxmini_openid"
var UserAuthTypeWxh5OpenID string = "wxh5_openid"
var UserAuthTypeUUID string = "uuid" var UserAuthTypeUUID string = "uuid"
// 代理扣除类型
var AgentDeductionTypeCost string = "cost" var AgentDeductionTypeCost string = "cost"
var AgentDeductionTypePricing string = "pricing" var AgentDeductionTypePricing string = "pricing"
@ -78,3 +83,16 @@ const (
AgentRealNameStatusApproved = "approved" AgentRealNameStatusApproved = "approved"
AgentRealNameStatusRejected = "rejected" AgentRealNameStatusRejected = "rejected"
) )
// 用户身份类型
const (
UserTypeTemp = 0 // 临时用户
UserTypeNormal = 1 // 正式用户
UserTypeAdmin = 2 // 管理员
)
// 代理状态
const (
AgentStatusNo = 0 // 非代理
AgentStatusYes = 1 // 是代理
)

View File

@ -5,13 +5,15 @@ import (
"encoding/json" "encoding/json"
"errors" "errors"
"fmt" "fmt"
"tydata-server/app/main/model"
jwtx "tydata-server/common/jwt"
) )
const CtxKeyJwtUserId = "userId" const CtxKeyJwtUserId = "userId"
// 定义错误类型 // 定义错误类型
var ( var (
ErrNoUserIdInCtx = errors.New("上下文中没有用户ID") // 未登录 ErrNoInCtx = errors.New("上下文中没有相关数据")
ErrInvalidUserId = errors.New("用户ID格式无效") // 数据异常 ErrInvalidUserId = errors.New("用户ID格式无效") // 数据异常
) )
@ -20,7 +22,11 @@ func GetUidFromCtx(ctx context.Context) (int64, error) {
// 尝试从上下文中获取 jwtUserId // 尝试从上下文中获取 jwtUserId
value := ctx.Value(CtxKeyJwtUserId) value := ctx.Value(CtxKeyJwtUserId)
if value == nil { if value == nil {
return 0, ErrNoUserIdInCtx claims, err := GetClaimsFromCtx(ctx)
if err != nil {
return 0, err
}
return claims.UserId, nil
} }
// 根据值的类型进行不同处理 // 根据值的类型进行不同处理
@ -47,12 +53,52 @@ func GetUidFromCtx(ctx context.Context) (int64, error) {
} }
} }
func GetClaimsFromCtx(ctx context.Context) (*jwtx.JwtClaims, error) {
value := ctx.Value(jwtx.ExtraKey)
if value == nil {
return nil, ErrNoInCtx
}
// 首先尝试直接断言为 *jwtx.JwtClaims
if claims, ok := value.(*jwtx.JwtClaims); ok {
return claims, nil
}
// 如果直接断言失败,尝试从 map[string]interface{} 中解析
if claimsMap, ok := value.(map[string]interface{}); ok {
return jwtx.MapToJwtClaims(claimsMap)
}
return nil, ErrNoInCtx
}
// IsNoUserIdError 判断是否是未登录错误 // IsNoUserIdError 判断是否是未登录错误
func IsNoUserIdError(err error) bool { func IsNoUserIdError(err error) bool {
return errors.Is(err, ErrNoUserIdInCtx) return errors.Is(err, ErrNoInCtx)
} }
// IsInvalidUserIdError 判断是否是用户ID格式错误 // IsInvalidUserIdError 判断是否是用户ID格式错误
func IsInvalidUserIdError(err error) bool { func IsInvalidUserIdError(err error) bool {
return errors.Is(err, ErrInvalidUserId) return errors.Is(err, ErrInvalidUserId)
} }
// GetPlatformFromCtx 从 context 中获取平台
func GetPlatformFromCtx(ctx context.Context) (string, error) {
platform, platformOk := ctx.Value("platform").(string)
if !platformOk {
return "", fmt.Errorf("平台不存在: %s", platform)
}
switch platform {
case model.PlatformWxMini:
return model.PlatformWxMini, nil
case model.PlatformWxH5:
return model.PlatformWxH5, nil
case model.PlatformApp:
return model.PlatformApp, nil
case model.PlatformH5:
return model.PlatformH5, nil
default:
return "", fmt.Errorf("不支持的支付平台: %s", platform)
}
}

View File

@ -1,179 +0,0 @@
package ctxdata
import (
"context"
"encoding/json"
"errors"
"testing"
)
func TestGetUidFromCtx(t *testing.T) {
tests := []struct {
name string
ctxSetup func() context.Context
wantUid int64
wantError error
}{
{
name: "正常情况_有效用户ID_json.Number",
ctxSetup: func() context.Context {
return context.WithValue(context.Background(), CtxKeyJwtUserId, json.Number("12345"))
},
wantUid: 12345,
wantError: nil,
},
{
name: "正常情况_有效用户ID_int64",
ctxSetup: func() context.Context {
return context.WithValue(context.Background(), CtxKeyJwtUserId, int64(12345))
},
wantUid: 12345,
wantError: nil,
},
{
name: "正常情况_有效用户ID_int",
ctxSetup: func() context.Context {
return context.WithValue(context.Background(), CtxKeyJwtUserId, 12345)
},
wantUid: 12345,
wantError: nil,
},
{
name: "正常情况_有效用户ID_float64",
ctxSetup: func() context.Context {
return context.WithValue(context.Background(), CtxKeyJwtUserId, float64(12345))
},
wantUid: 12345,
wantError: nil,
},
{
name: "异常情况_上下文中无用户ID",
ctxSetup: func() context.Context {
return context.Background()
},
wantUid: 0,
wantError: ErrNoUserIdInCtx,
},
{
name: "异常情况_用户ID类型错误",
ctxSetup: func() context.Context {
return context.WithValue(context.Background(), CtxKeyJwtUserId, "非数字类型")
},
wantUid: 0,
wantError: ErrInvalidUserId,
},
{
name: "异常情况_用户ID无法转换为int64",
ctxSetup: func() context.Context {
return context.WithValue(context.Background(), CtxKeyJwtUserId, json.Number("非数字内容"))
},
wantUid: 0,
wantError: ErrInvalidUserId,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
ctx := tt.ctxSetup()
gotUid, gotErr := GetUidFromCtx(ctx)
// 检查返回的用户ID
if gotUid != tt.wantUid {
t.Errorf("GetUidFromCtx() 返回用户ID = %v, 期望值 %v", gotUid, tt.wantUid)
}
// 检查错误类型
if tt.wantError == nil && gotErr != nil {
t.Errorf("GetUidFromCtx() 返回意外错误 = %v", gotErr)
}
if tt.wantError != nil && !errors.Is(gotErr, tt.wantError) {
t.Errorf("GetUidFromCtx() 错误类型 = %v, 期望错误类型 %v", gotErr, tt.wantError)
}
})
}
}
func TestIsNoUserIdError(t *testing.T) {
tests := []struct {
name string
err error
expected bool
}{
{
name: "是未登录错误",
err: ErrNoUserIdInCtx,
expected: true,
},
{
name: "包装的未登录错误",
err: errors.New("外层错误: " + ErrNoUserIdInCtx.Error()),
expected: false, // 直接字符串拼接不会保留错误链
},
{
name: "使用fmt.Errorf包装的未登录错误",
err: errors.New("外层错误"),
expected: false,
},
{
name: "非未登录错误",
err: ErrInvalidUserId,
expected: false,
},
{
name: "nil错误",
err: nil,
expected: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := IsNoUserIdError(tt.err); got != tt.expected {
t.Errorf("IsNoUserIdError() = %v, 期望值 %v", got, tt.expected)
}
})
}
}
func TestIsInvalidUserIdError(t *testing.T) {
tests := []struct {
name string
err error
expected bool
}{
{
name: "是无效用户ID错误",
err: ErrInvalidUserId,
expected: true,
},
{
name: "包装的无效用户ID错误",
err: errors.New("外层错误: " + ErrInvalidUserId.Error()),
expected: false, // 直接字符串拼接不会保留错误链
},
{
name: "使用fmt.Errorf包装的无效用户ID错误",
err: errors.New("外层错误"),
expected: false,
},
{
name: "非无效用户ID错误",
err: ErrNoUserIdInCtx,
expected: false,
},
{
name: "nil错误",
err: nil,
expected: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := IsInvalidUserIdError(tt.err); got != tt.expected {
t.Errorf("IsInvalidUserIdError() = %v, 期望值 %v", got, tt.expected)
}
})
}
}

View File

@ -1,68 +1,94 @@
package jwtx package jwtx
import ( import (
"encoding/json"
"errors" "errors"
"github.com/golang-jwt/jwt/v4"
"strconv"
"time" "time"
"github.com/golang-jwt/jwt/v4"
) )
// Token 生成逻辑的函数,接收 userId、过期时间和密钥返回生成的 token const ExtraKey = "extra"
func GenerateJwtToken(userId int64, secret string, expireTime int64) (string, error) {
// 获取当前时间戳 type JwtClaims struct {
now := time.Now().Unix() UserId int64 `json:"userId"`
// 定义 JWT Claims AgentId int64 `json:"agentId"`
claims := jwt.MapClaims{ Platform string `json:"platform"`
"exp": now + expireTime, // token 过期时间 // 用户身份类型0-临时用户1-正式用户
"iat": now, // 签发时间 UserType int64 `json:"userType"`
"userId": userId, // 用户ID // 是否代理0-否1-是
IsAgent int64 `json:"isAgent"`
}
// MapToJwtClaims 将 map[string]interface{} 转换为 JwtClaims 结构体
func MapToJwtClaims(claimsMap map[string]interface{}) (*JwtClaims, error) {
// 使用JSON序列化/反序列化的方式自动转换
jsonData, err := json.Marshal(claimsMap)
if err != nil {
return nil, errors.New("序列化claims失败")
} }
// 创建新的 JWT token var claims JwtClaims
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims) if err := json.Unmarshal(jsonData, &claims); err != nil {
return nil, errors.New("反序列化claims失败")
}
// 使用密钥对 token 签名 return &claims, nil
signedToken, err := token.SignedString([]byte(secret)) }
// GenerateJwtToken 生成JWT token
func GenerateJwtToken(claims JwtClaims, secret string, expire int64) (string, error) {
now := time.Now().Unix()
// 将 claims 结构体转换为 map[string]interface{}
claimsBytes, err := json.Marshal(claims)
if err != nil { if err != nil {
return "", err return "", err
} }
return signedToken, nil var claimsMap map[string]interface{}
if err := json.Unmarshal(claimsBytes, &claimsMap); err != nil {
return "", err
}
jwtClaims := jwt.MapClaims{
"exp": now + expire,
"iat": now,
"userId": claims.UserId,
ExtraKey: claimsMap,
}
token := jwt.NewWithClaims(jwt.SigningMethodHS256, jwtClaims)
return token.SignedString([]byte(secret))
} }
func ParseJwtToken(tokenStr string, secret string) (int64, error) {
func ParseJwtToken(tokenStr string, secret string) (*JwtClaims, error) {
token, err := jwt.Parse(tokenStr, func(token *jwt.Token) (interface{}, error) { token, err := jwt.Parse(tokenStr, func(token *jwt.Token) (interface{}, error) {
return []byte(secret), nil return []byte(secret), nil
}) })
if err != nil || !token.Valid { if err != nil || !token.Valid {
return 0, errors.New("invalid JWT") return nil, errors.New("invalid JWT")
} }
claims, ok := token.Claims.(jwt.MapClaims) claims, ok := token.Claims.(jwt.MapClaims)
if !ok || !token.Valid { if !ok || !token.Valid {
return 0, errors.New("invalid JWT claims") return nil, errors.New("invalid JWT claims")
} }
// 从 claims 中提取 userId extraInfo, exists := claims[ExtraKey]
userIdRaw, ok := claims["userId"] if !exists {
if !ok { return nil, errors.New("extra not found in JWT")
return 0, errors.New("userId not found in JWT")
} }
// 处理不同类型的 userId确保它被转换为 int64 // 尝试直接断言为 JwtClaims 结构体
switch userId := userIdRaw.(type) { if jwtClaims, ok := extraInfo.(JwtClaims); ok {
case float64: return &jwtClaims, nil
return int64(userId), nil
case int64:
return userId, nil
case string:
// 如果 userId 是字符串,可以尝试将其转换为 int64
parsedId, err := strconv.ParseInt(userId, 10, 64)
if err != nil {
return 0, errors.New("invalid userId in JWT")
} }
return parsedId, nil
default: // 尝试从 map[string]interface{} 中解析
return 0, errors.New("unsupported userId type in JWT") if claimsMap, ok := extraInfo.(map[string]interface{}); ok {
return MapToJwtClaims(claimsMap)
} }
return nil, errors.New("unsupported extra type in JWT")
} }

View File

@ -15,6 +15,7 @@ const DB_UPDATE_AFFECTED_ZERO_ERROR uint32 = 100006
const PARAM_VERIFICATION_ERROR uint32 = 100007 const PARAM_VERIFICATION_ERROR uint32 = 100007
const CUSTOM_ERROR uint32 = 100008 const CUSTOM_ERROR uint32 = 100008
const USER_NOT_FOUND uint32 = 100009 const USER_NOT_FOUND uint32 = 100009
const USER_NEED_BIND_MOBILE uint32 = 100010
const LOGIN_FAILED uint32 = 200001 const LOGIN_FAILED uint32 = 200001
const LOGIC_QUERY_WAIT uint32 = 200002 const LOGIC_QUERY_WAIT uint32 = 200002

View File

@ -33,9 +33,10 @@ $tables = @(
# "query", # "query",
# "query_cleanup_log" # "query_cleanup_log"
# "query_cleanup_detail" # "query_cleanup_detail"
"query_cleanup_config" # "query_cleanup_config"
# "user" # "user"
# "user_auth" # "user_auth"
"user_temp"
# "example" # "example"
# "admin_user" # "admin_user"
# "admin_user_role" # "admin_user_role"

View File

@ -9,7 +9,7 @@ import (
func TestAesEcbMobileEncryption(t *testing.T) { func TestAesEcbMobileEncryption(t *testing.T) {
// 测试手机号加密 // 测试手机号加密
mobile := "13280082033 " mobile := "17776203797 "
key := []byte("ff83609b2b24fc73196aac3d3dfb874f") // 16字节AES-128密钥 key := []byte("ff83609b2b24fc73196aac3d3dfb874f") // 16字节AES-128密钥
keyStr := hex.EncodeToString(key) keyStr := hex.EncodeToString(key)
@ -19,7 +19,7 @@ func TestAesEcbMobileEncryption(t *testing.T) {
t.Fatalf("手机号加密失败: %v", err) t.Fatalf("手机号加密失败: %v", err)
} }
fmt.Printf("encrypted: %s\n", encrypted) fmt.Printf("encrypted: %s\n", encrypted)
jmStr := "oEpLcrIpDPN63rOlESXTDg==" jmStr := "m9EEeW9ZBBJmi1hx1k1uIQ=="
// 测试解密 // 测试解密
decrypted, err := DecryptMobile(jmStr, keyStr) decrypted, err := DecryptMobile(jmStr, keyStr)
if err != nil { if err != nil {