1、示例报告改未登录可访问

2、增加代理推广报告查询注册UUID账户
This commit is contained in:
liangzai 2025-05-11 20:45:48 +08:00
parent 213f1de2c6
commit 176ad00e35
8 changed files with 223 additions and 85 deletions

View File

@ -31,6 +31,7 @@ type QueryItem {
@server ( @server (
prefix: api/v1 prefix: api/v1
group: query group: query
middleware: AuthInterceptor
) )
service main { service main {
@doc "query service agent" @doc "query service agent"
@ -86,10 +87,6 @@ service main {
@handler queryProvisionalOrder @handler queryProvisionalOrder
get /query/provisional_order/:id (QueryProvisionalOrderReq) returns (QueryProvisionalOrderResp) get /query/provisional_order/:id (QueryProvisionalOrderReq) returns (QueryProvisionalOrderResp)
@doc "查询示例"
@handler queryExample
get /query/example (QueryExampleReq) returns (QueryExampleResp)
@doc "查询列表" @doc "查询列表"
@handler queryList @handler queryList
get /query/list (QueryListReq) returns (QueryListResp) get /query/list (QueryListReq) returns (QueryListResp)
@ -204,6 +201,10 @@ service main {
@handler queryDetail @handler queryDetail
get /query/:id (QueryDetailReq) returns (QueryDetailResp) get /query/:id (QueryDetailReq) returns (QueryDetailResp)
@doc "查询示例"
@handler queryExample
get /query/example (QueryExampleReq) returns (QueryExampleResp)
} }
type QuerySingleTestReq { type QuerySingleTestReq {

View File

@ -241,6 +241,8 @@ func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
) )
server.AddRoutes( server.AddRoutes(
rest.WithMiddlewares(
[]rest.Middleware{serverCtx.AuthInterceptor},
[]rest.Route{ []rest.Route{
{ {
// query service agent // query service agent
@ -253,7 +255,8 @@ func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
Path: "/query/service_app/:product", Path: "/query/service_app/:product",
Handler: query.QueryServiceAppHandler(serverCtx), Handler: query.QueryServiceAppHandler(serverCtx),
}, },
}, }...,
),
rest.WithPrefix("/api/v1"), rest.WithPrefix("/api/v1"),
) )
@ -272,12 +275,6 @@ func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
server.AddRoutes( server.AddRoutes(
[]rest.Route{ []rest.Route{
{
// 查询示例
Method: http.MethodGet,
Path: "/query/example",
Handler: query.QueryExampleHandler(serverCtx),
},
{ {
// 查询列表 // 查询列表
Method: http.MethodGet, Method: http.MethodGet,
@ -327,6 +324,12 @@ func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
Path: "/query/:id", Path: "/query/:id",
Handler: query.QueryDetailHandler(serverCtx), Handler: query.QueryDetailHandler(serverCtx),
}, },
{
// 查询示例
Method: http.MethodGet,
Path: "/query/example",
Handler: query.QueryExampleHandler(serverCtx),
},
{ {
Method: http.MethodPost, Method: http.MethodPost,
Path: "/query/single/test", Path: "/query/single/test",

View File

@ -2,13 +2,11 @@ package query
import ( import (
"context" "context"
"database/sql"
"encoding/hex" "encoding/hex"
"encoding/json" "encoding/json"
"fmt" "fmt"
"time" "time"
"tydata-server/app/user/cmd/api/internal/service" "tydata-server/app/user/cmd/api/internal/service"
"tydata-server/app/user/model"
"tydata-server/common/ctxdata" "tydata-server/common/ctxdata"
jwtx "tydata-server/common/jwt" jwtx "tydata-server/common/jwt"
"tydata-server/common/xerr" "tydata-server/common/xerr"
@ -17,7 +15,6 @@ import (
"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"
"tydata-server/app/user/cmd/api/internal/svc" "tydata-server/app/user/cmd/api/internal/svc"
"tydata-server/app/user/cmd/api/internal/types" "tydata-server/app/user/cmd/api/internal/types"
@ -120,9 +117,9 @@ func (l *QueryServiceLogic) ProcessMarriageLogic(req *types.QueryServiceReq) (*t
"id_card": data.IDCard, "id_card": data.IDCard,
"mobile": data.Mobile, "mobile": data.Mobile,
} }
userID, err := l.GetOrCreateUser(data.Mobile) userID, err := l.GetOrCreateUser()
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)
} }
cacheNo, cacheDataErr := l.CacheData(params, "marriage", userID) cacheNo, cacheDataErr := l.CacheData(params, "marriage", userID)
if cacheDataErr != nil { if cacheDataErr != nil {
@ -180,9 +177,9 @@ func (l *QueryServiceLogic) ProcessHomeServiceLogic(req *types.QueryServiceReq)
"id_card": data.IDCard, "id_card": data.IDCard,
"mobile": data.Mobile, "mobile": data.Mobile,
} }
userID, err := l.GetOrCreateUser(data.Mobile) userID, err := l.GetOrCreateUser()
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)
} }
cacheNo, cacheDataErr := l.CacheData(params, "homeservice", userID) cacheNo, cacheDataErr := l.CacheData(params, "homeservice", userID)
if cacheDataErr != nil { if cacheDataErr != nil {
@ -241,9 +238,9 @@ func (l *QueryServiceLogic) ProcessRiskAssessmentLogic(req *types.QueryServiceRe
"id_card": data.IDCard, "id_card": data.IDCard,
"mobile": data.Mobile, "mobile": data.Mobile,
} }
userID, err := l.GetOrCreateUser(data.Mobile) userID, err := l.GetOrCreateUser()
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)
} }
cacheNo, cacheDataErr := l.CacheData(params, "riskassessment", userID) cacheNo, cacheDataErr := l.CacheData(params, "riskassessment", userID)
if cacheDataErr != nil { if cacheDataErr != nil {
@ -301,9 +298,9 @@ func (l *QueryServiceLogic) ProcessCompanyInfoLogic(req *types.QueryServiceReq)
"id_card": data.IDCard, "id_card": data.IDCard,
"mobile": data.Mobile, "mobile": data.Mobile,
} }
userID, err := l.GetOrCreateUser(data.Mobile) userID, err := l.GetOrCreateUser()
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)
} }
cacheNo, cacheDataErr := l.CacheData(params, "companyinfo", userID) cacheNo, cacheDataErr := l.CacheData(params, "companyinfo", userID)
if cacheDataErr != nil { if cacheDataErr != nil {
@ -362,9 +359,9 @@ func (l *QueryServiceLogic) ProcessRentalInfoLogic(req *types.QueryServiceReq) (
"id_card": data.IDCard, "id_card": data.IDCard,
"mobile": data.Mobile, "mobile": data.Mobile,
} }
userID, err := l.GetOrCreateUser(data.Mobile) userID, err := l.GetOrCreateUser()
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)
} }
cacheNo, cacheDataErr := l.CacheData(params, "rentalinfo", userID) cacheNo, cacheDataErr := l.CacheData(params, "rentalinfo", userID)
if cacheDataErr != nil { if cacheDataErr != nil {
@ -423,9 +420,9 @@ func (l *QueryServiceLogic) ProcessPreLoanBackgroundCheckLogic(req *types.QueryS
"id_card": data.IDCard, "id_card": data.IDCard,
"mobile": data.Mobile, "mobile": data.Mobile,
} }
userID, err := l.GetOrCreateUser(data.Mobile) userID, err := l.GetOrCreateUser()
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)
} }
cacheNo, cacheDataErr := l.CacheData(params, "preloanbackgroundcheck", userID) cacheNo, cacheDataErr := l.CacheData(params, "preloanbackgroundcheck", userID)
if cacheDataErr != nil { if cacheDataErr != nil {
@ -483,9 +480,9 @@ func (l *QueryServiceLogic) ProcessBackgroundCheckLogic(req *types.QueryServiceR
"id_card": data.IDCard, "id_card": data.IDCard,
"mobile": data.Mobile, "mobile": data.Mobile,
} }
userID, err := l.GetOrCreateUser(data.Mobile) userID, err := l.GetOrCreateUser()
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)
} }
cacheNo, cacheDataErr := l.CacheData(params, "backgroundcheck", userID) cacheNo, cacheDataErr := l.CacheData(params, "backgroundcheck", userID)
if cacheDataErr != nil { if cacheDataErr != nil {
@ -1390,51 +1387,36 @@ func (l *QueryServiceLogic) CacheData(params map[string]interface{}, Product str
return outTradeNo, nil return outTradeNo, nil
} }
func (l *QueryServiceLogic) GetOrCreateUser(mobile string) (int64, error) { // GetOrCreateUser 获取或创建用户
agentIdentifier, ok := l.ctx.Value("agentIdentifier").(string) // 1. 如果上下文中已有用户ID直接返回
app, appOk := l.ctx.Value("app").(bool) // 2. 如果是代理查询或APP请求创建新用户
if (!ok || agentIdentifier == "") && (!appOk || app == false) { // 3. 其他情况返回未登录错误
// 不是代理查询 func (l *QueryServiceLogic) GetOrCreateUser() (int64, error) {
userID, getUidErr := ctxdata.GetUidFromCtx(l.ctx) // 尝试获取用户ID
if getUidErr != nil { userID, err := ctxdata.GetUidFromCtx(l.ctx)
return 0, getUidErr if err == nil {
} return userID, nil // 已有用户ID直接返回
return userID, nil
} }
userModel, err := l.svcCtx.UserModel.FindOneByMobile(l.ctx, sql.NullString{String: mobile, Valid: true}) // 如果不是未登录错误,说明是其他错误,直接返回
if err != nil && !errors.Is(err, model.ErrNotFound) { if !ctxdata.IsNoUserIdError(err) {
return 0, err return 0, err
} }
// 没有则创建账号
if userModel == nil {
userModel = &model.User{Mobile: sql.NullString{String: mobile, Valid: true}}
// if len(userModel.Nickname) == 0 {
// userModel.Nickname = mobile
// }
if transErr := l.svcCtx.UserModel.Trans(l.ctx, func(ctx context.Context, session sqlx.Session) error {
insertResult, userInsertErr := l.svcCtx.UserModel.Insert(ctx, session, userModel)
if userInsertErr != nil {
return userInsertErr
}
lastId, lastInsertIdErr := insertResult.LastInsertId()
if lastInsertIdErr != nil {
return lastInsertIdErr
}
userModel.Id = lastId
userAuth := new(model.UserAuth) // 检查是否是代理查询或APP请求
userAuth.UserId = lastId isAgentQuery := false
userAuth.AuthKey = mobile if agentID, ok := l.ctx.Value("agentIdentifier").(string); ok && agentID != "" {
userAuth.AuthType = model.UserAuthTypeAgentPromote isAgentQuery = true
if _, userAuthInsertErr := l.svcCtx.UserAuthModel.Insert(ctx, session, userAuth); userAuthInsertErr != nil { }
return userAuthInsertErr if app, ok := l.ctx.Value("app").(bool); ok && app {
isAgentQuery = true
} }
return nil // 如果不是代理查询或APP请求返回未登录错误
}); transErr != nil { if !isAgentQuery {
return 0, transErr return 0, ctxdata.ErrNoUserIdInCtx
} }
}
return userModel.Id, nil // 创建新用户
return l.svcCtx.UserService.RegisterUUIDUser(l.ctx)
} }

View File

@ -0,0 +1,56 @@
package middleware
import (
"context"
"net/http"
"tydata-server/app/user/cmd/api/internal/config"
"tydata-server/common/ctxdata"
jwtx "tydata-server/common/jwt"
"tydata-server/common/xerr"
"github.com/pkg/errors"
"github.com/zeromicro/go-zero/rest/httpx"
)
const (
// 定义错误码
ErrCodeUnauthorized = 401
)
type AuthInterceptorMiddleware struct {
Config config.Config
}
func NewAuthInterceptorMiddleware(c config.Config) *AuthInterceptorMiddleware {
return &AuthInterceptorMiddleware{
Config: c,
}
}
func (m *AuthInterceptorMiddleware) Handle(next http.HandlerFunc) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
// 从请求头中获取Authorization字段
authHeader := r.Header.Get("Authorization")
// 如果没有Authorization头直接放行
if authHeader == "" {
next(w, r)
return
}
// 解析JWT令牌
userId, err := jwtx.ParseJwtToken(authHeader, m.Config.JwtAuth.AccessSecret)
if err != nil {
// JWT解析失败返回401错误
httpx.Error(w, errors.Wrapf(xerr.NewErrCode(ErrCodeUnauthorized), "token解析失败: %v", err))
return
}
// 将用户ID添加到请求上下文
ctx := context.WithValue(r.Context(), ctxdata.CtxKeyJwtUserId, userId)
// 使用新的上下文继续处理请求
next(w, r.WithContext(ctx))
}
}

View File

@ -0,0 +1,65 @@
package service
import (
"context"
"tydata-server/app/user/model"
"github.com/google/uuid"
"github.com/zeromicro/go-zero/core/stores/sqlx"
)
type UserService struct {
userModel model.UserModel
userAuthModel model.UserAuthModel
}
// NewUserService 创建UserService实例
func NewUserService(userModel model.UserModel, userAuthModel model.UserAuthModel) *UserService {
return &UserService{
userModel: userModel,
userAuthModel: userAuthModel,
}
}
// GenerateUUIDUserId 生成UUID用户ID
func (s *UserService) GenerateUUIDUserId(ctx context.Context) (string, error) {
id := uuid.NewString()
return id, nil
}
// RegisterUUIDUser 注册UUID用户返回用户ID
func (s *UserService) RegisterUUIDUser(ctx context.Context) (int64, error) {
// 生成UUID
uuidStr, err := s.GenerateUUIDUserId(ctx)
if err != nil {
return 0, err
}
var userId int64
err = s.userModel.Trans(ctx, func(ctx context.Context, session sqlx.Session) error {
// 创建用户记录
user := &model.User{}
result, err := s.userModel.Insert(ctx, session, user)
if err != nil {
return err
}
userId, err = result.LastInsertId()
if err != nil {
return err
}
// 创建用户认证记录
userAuth := &model.UserAuth{
UserId: userId,
AuthType: model.UserAuthTypeUUID,
AuthKey: uuidStr,
}
_, err = s.userAuthModel.Insert(ctx, session, userAuth)
return err
})
if err != nil {
return 0, err
}
return userId, nil
}

View File

@ -17,6 +17,7 @@ type ServiceContext struct {
Config config.Config Config config.Config
Redis *redis.Redis Redis *redis.Redis
SourceInterceptor rest.Middleware SourceInterceptor rest.Middleware
AuthInterceptor rest.Middleware
UserModel model.UserModel UserModel model.UserModel
UserAuthModel model.UserAuthModel UserAuthModel model.UserAuthModel
ProductModel model.ProductModel ProductModel model.ProductModel
@ -52,6 +53,7 @@ type ServiceContext struct {
AsynqService *service.AsynqService // 客户端 AsynqService *service.AsynqService // 客户端
VerificationService *service.VerificationService VerificationService *service.VerificationService
AgentService *service.AgentService AgentService *service.AgentService
UserService *service.UserService
} }
func NewServiceContext(c config.Config) *ServiceContext { func NewServiceContext(c config.Config) *ServiceContext {
@ -114,10 +116,12 @@ func NewServiceContext(c config.Config) *ServiceContext {
agentCommissionDeductionModel, agentWalletModel, agentLinkModel, agentOrderModel, agentRewardsModel, agentCommissionDeductionModel, agentWalletModel, agentLinkModel, agentOrderModel, agentRewardsModel,
agentMembershipConfigModel, agentMembershipRechargeOrderModel, agentMembershipUserConfigModel, agentMembershipConfigModel, agentMembershipRechargeOrderModel, agentMembershipUserConfigModel,
agentProductConfigModel, agentPlatformDeductionModel, agentActiveStatModel, agentWithdrawalModel) agentProductConfigModel, agentPlatformDeductionModel, agentActiveStatModel, agentWithdrawalModel)
userService := service.NewUserService(userModel, userAuthModel)
return &ServiceContext{ return &ServiceContext{
Config: c, Config: c,
Redis: redis.MustNewRedis(redisConf), Redis: redis.MustNewRedis(redisConf),
SourceInterceptor: middleware.NewSourceInterceptorMiddleware().Handle, SourceInterceptor: middleware.NewSourceInterceptorMiddleware().Handle,
AuthInterceptor: middleware.NewAuthInterceptorMiddleware(c).Handle,
AlipayService: alipayService, AlipayService: alipayService,
WechatPayService: wechatPayService, WechatPayService: wechatPayService,
ApplePayService: applePayService, ApplePayService: applePayService,
@ -153,6 +157,7 @@ func NewServiceContext(c config.Config) *ServiceContext {
AgentActiveStatModel: agentActiveStatModel, AgentActiveStatModel: agentActiveStatModel,
AgentWithdrawalModel: agentWithdrawalModel, AgentWithdrawalModel: agentWithdrawalModel,
ExampleModel: exampleModel, ExampleModel: exampleModel,
UserService: userService,
} }
} }

View File

@ -2,6 +2,7 @@ package model
import ( import (
"errors" "errors"
"github.com/zeromicro/go-zero/core/stores/sqlx" "github.com/zeromicro/go-zero/core/stores/sqlx"
) )
@ -15,6 +16,7 @@ var UserAuthTypeWxMini string = "wx_mini"
var UserAuthTypeWxh5 string = "wx_h5" var UserAuthTypeWxh5 string = "wx_h5"
var UserAuthTypeAgentDirect string = "agent_direct" var UserAuthTypeAgentDirect string = "agent_direct"
var UserAuthTypeAgentPromote string = "agent_promote" var UserAuthTypeAgentPromote string = "agent_promote"
var UserAuthTypeUUID string = "uuid"
var AgentDeductionTypeCost string = "cost" var AgentDeductionTypeCost string = "cost"
var AgentDeductionTypePricing string = "pricing" var AgentDeductionTypePricing string = "pricing"

View File

@ -3,23 +3,47 @@ package ctxdata
import ( import (
"context" "context"
"encoding/json" "encoding/json"
"errors"
"fmt" "fmt"
) )
const CtxKeyJwtUserId = "userId" const CtxKeyJwtUserId = "userId"
// 定义错误类型
var (
ErrNoUserIdInCtx = errors.New("上下文中没有用户ID") // 未登录
ErrInvalidUserId = errors.New("用户ID格式无效") // 数据异常
)
// GetUidFromCtx 从 context 中获取用户 ID // GetUidFromCtx 从 context 中获取用户 ID
func GetUidFromCtx(ctx context.Context) (int64, error) { func GetUidFromCtx(ctx context.Context) (int64, error) {
// 尝试从上下文中获取 jwtUserId // 尝试从上下文中获取 jwtUserId
jsonUid, ok := ctx.Value(CtxKeyJwtUserId).(json.Number) value := ctx.Value(CtxKeyJwtUserId)
if !ok { if value == nil {
return 0, fmt.Errorf("无法获取用户 ID, CtxKeyJwtUserId = %v", CtxKeyJwtUserId) return 0, ErrNoUserIdInCtx
} }
// 尝试转换为 json.Number
jsonUid, ok := value.(json.Number)
if !ok {
return 0, fmt.Errorf("%w: 期望类型 json.Number, 实际类型 %T", ErrInvalidUserId, value)
}
// 转换为 int64 // 转换为 int64
uid, err := jsonUid.Int64() uid, err := jsonUid.Int64()
if err != nil { if err != nil {
return 0, fmt.Errorf("用户 ID 转换失败: %v", err) return 0, fmt.Errorf("%w: %v", ErrInvalidUserId, err)
} }
return uid, nil return uid, nil
} }
// IsNoUserIdError 判断是否是未登录错误
func IsNoUserIdError(err error) bool {
return errors.Is(err, ErrNoUserIdInCtx)
}
// IsInvalidUserIdError 判断是否是用户ID格式错误
func IsInvalidUserIdError(err error) bool {
return errors.Is(err, ErrInvalidUserId)
}