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

2、增加代理推广报告查询注册UUID账户
This commit is contained in:
liangzai 2025-05-11 19:39:56 +08:00
parent 9ec2e6c104
commit 972b10eeae
8 changed files with 222 additions and 85 deletions

View File

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

View File

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

View File

@ -2,12 +2,10 @@ package query
import (
"context"
"database/sql"
"encoding/hex"
"encoding/json"
"fmt"
"qnc-server/app/user/cmd/api/internal/service"
"qnc-server/app/user/model"
"qnc-server/common/ctxdata"
jwtx "qnc-server/common/jwt"
"qnc-server/common/xerr"
@ -17,7 +15,6 @@ import (
"github.com/pkg/errors"
"github.com/zeromicro/go-zero/core/stores/redis"
"github.com/zeromicro/go-zero/core/stores/sqlx"
"qnc-server/app/user/cmd/api/internal/svc"
"qnc-server/app/user/cmd/api/internal/types"
@ -120,9 +117,9 @@ func (l *QueryServiceLogic) ProcessMarriageLogic(req *types.QueryServiceReq) (*t
"id_card": data.IDCard,
"mobile": data.Mobile,
}
userID, err := l.GetOrCreateUser(data.Mobile)
userID, err := l.GetOrCreateUser()
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)
if cacheDataErr != nil {
@ -180,9 +177,9 @@ func (l *QueryServiceLogic) ProcessHomeServiceLogic(req *types.QueryServiceReq)
"id_card": data.IDCard,
"mobile": data.Mobile,
}
userID, err := l.GetOrCreateUser(data.Mobile)
userID, err := l.GetOrCreateUser()
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)
if cacheDataErr != nil {
@ -241,9 +238,9 @@ func (l *QueryServiceLogic) ProcessRiskAssessmentLogic(req *types.QueryServiceRe
"id_card": data.IDCard,
"mobile": data.Mobile,
}
userID, err := l.GetOrCreateUser(data.Mobile)
userID, err := l.GetOrCreateUser()
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)
if cacheDataErr != nil {
@ -301,9 +298,9 @@ func (l *QueryServiceLogic) ProcessCompanyInfoLogic(req *types.QueryServiceReq)
"id_card": data.IDCard,
"mobile": data.Mobile,
}
userID, err := l.GetOrCreateUser(data.Mobile)
userID, err := l.GetOrCreateUser()
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)
if cacheDataErr != nil {
@ -362,9 +359,9 @@ func (l *QueryServiceLogic) ProcessRentalInfoLogic(req *types.QueryServiceReq) (
"id_card": data.IDCard,
"mobile": data.Mobile,
}
userID, err := l.GetOrCreateUser(data.Mobile)
userID, err := l.GetOrCreateUser()
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)
if cacheDataErr != nil {
@ -423,9 +420,9 @@ func (l *QueryServiceLogic) ProcessPreLoanBackgroundCheckLogic(req *types.QueryS
"id_card": data.IDCard,
"mobile": data.Mobile,
}
userID, err := l.GetOrCreateUser(data.Mobile)
userID, err := l.GetOrCreateUser()
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)
if cacheDataErr != nil {
@ -483,9 +480,9 @@ func (l *QueryServiceLogic) ProcessBackgroundCheckLogic(req *types.QueryServiceR
"id_card": data.IDCard,
"mobile": data.Mobile,
}
userID, err := l.GetOrCreateUser(data.Mobile)
userID, err := l.GetOrCreateUser()
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)
if cacheDataErr != nil {
@ -773,7 +770,7 @@ func (l *QueryServiceLogic) ProcessTocPhoneThreeElementsLogic(req *types.QuerySe
func (l *QueryServiceLogic) ProcessTocPhoneTwoElementsLogic(req *types.QueryServiceReq) (*types.QueryServiceResp, error) {
userID, getUidErr := ctxdata.GetUidFromCtx(l.ctx)
if getUidErr != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "查询服务, 获取用户信息失败, %+v", getUidErr)
return nil, getUidErr
}
// AES解密
@ -1390,51 +1387,36 @@ func (l *QueryServiceLogic) CacheData(params map[string]interface{}, Product str
return outTradeNo, nil
}
func (l *QueryServiceLogic) GetOrCreateUser(mobile string) (int64, error) {
agentIdentifier, ok := l.ctx.Value("agentIdentifier").(string)
app, appOk := l.ctx.Value("app").(bool)
if (!ok || agentIdentifier == "") && (!appOk || app == false) {
// 不是代理查询
userID, getUidErr := ctxdata.GetUidFromCtx(l.ctx)
if getUidErr != nil {
return 0, getUidErr
}
return userID, nil
// GetOrCreateUser 获取或创建用户
// 1. 如果上下文中已有用户ID直接返回
// 2. 如果是代理查询或APP请求创建新用户
// 3. 其他情况返回未登录错误
func (l *QueryServiceLogic) GetOrCreateUser() (int64, error) {
// 尝试获取用户ID
userID, err := ctxdata.GetUidFromCtx(l.ctx)
if err == nil {
return userID, nil // 已有用户ID直接返回
}
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
}
// 没有则创建账号
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)
userAuth.UserId = lastId
userAuth.AuthKey = mobile
userAuth.AuthType = model.UserAuthTypeAgentPromote
if _, userAuthInsertErr := l.svcCtx.UserAuthModel.Insert(ctx, session, userAuth); userAuthInsertErr != nil {
return userAuthInsertErr
// 检查是否是代理查询或APP请求
isAgentQuery := false
if agentID, ok := l.ctx.Value("agentIdentifier").(string); ok && agentID != "" {
isAgentQuery = true
}
if app, ok := l.ctx.Value("app").(bool); ok && app {
isAgentQuery = true
}
return nil
}); transErr != nil {
return 0, transErr
// 如果不是代理查询或APP请求返回未登录错误
if !isAgentQuery {
return 0, ctxdata.ErrNoUserIdInCtx
}
}
return userModel.Id, nil
// 创建新用户
return l.svcCtx.UserService.RegisterUUIDUser(l.ctx)
}

View File

@ -0,0 +1,55 @@
package middleware
import (
"context"
"net/http"
"qnc-server/app/user/cmd/api/internal/config"
"qnc-server/common/ctxdata"
jwtx "qnc-server/common/jwt"
"qnc-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"
"qnc-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
Redis *redis.Redis
SourceInterceptor rest.Middleware
AuthInterceptor rest.Middleware
UserModel model.UserModel
UserAuthModel model.UserAuthModel
ProductModel model.ProductModel
@ -52,6 +53,7 @@ type ServiceContext struct {
AsynqService *service.AsynqService // 客户端
VerificationService *service.VerificationService
AgentService *service.AgentService
UserService *service.UserService
}
func NewServiceContext(c config.Config) *ServiceContext {
@ -114,10 +116,12 @@ func NewServiceContext(c config.Config) *ServiceContext {
agentCommissionDeductionModel, agentWalletModel, agentLinkModel, agentOrderModel, agentRewardsModel,
agentMembershipConfigModel, agentMembershipRechargeOrderModel, agentMembershipUserConfigModel,
agentProductConfigModel, agentPlatformDeductionModel, agentActiveStatModel, agentWithdrawalModel)
userService := service.NewUserService(userModel, userAuthModel)
return &ServiceContext{
Config: c,
Redis: redis.MustNewRedis(redisConf),
SourceInterceptor: middleware.NewSourceInterceptorMiddleware().Handle,
AuthInterceptor: middleware.NewAuthInterceptorMiddleware(c).Handle,
AlipayService: alipayService,
WechatPayService: wechatPayService,
ApplePayService: applePayService,
@ -153,6 +157,7 @@ func NewServiceContext(c config.Config) *ServiceContext {
AgentActiveStatModel: agentActiveStatModel,
AgentWithdrawalModel: agentWithdrawalModel,
ExampleModel: exampleModel,
UserService: userService,
}
}

View File

@ -16,6 +16,7 @@ var UserAuthTypeWxMini string = "wx_mini"
var UserAuthTypeWxh5 string = "wx_h5"
var UserAuthTypeAgentDirect string = "agent_direct"
var UserAuthTypeAgentPromote string = "agent_promote"
var UserAuthTypeUUID string = "uuid"
var AgentDeductionTypeCost string = "cost"
var AgentDeductionTypePricing string = "pricing"

View File

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