Compare commits

..

No commits in common. "972b10eeaee68f831c63530e19d9c6f0965ffc5a" and "87321ed65ae95fecbc791fbd790c78d8130e4f2a" have entirely different histories.

12 changed files with 87 additions and 235 deletions

View File

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

View File

@ -61,6 +61,3 @@ Ali:
Code: "d55b58829efb41c8aa8e86769cba4844"
SystemConfig:
ThreeVerify: false
WechatH5:
AppID: "wx442ee1ac1ee75917"
AppSecret: "c80474909db42f63913b7a307b3bee17"

View File

@ -62,6 +62,3 @@ Ali:
Code: "d55b58829efb41c8aa8e86769cba4844"
SystemConfig:
ThreeVerify: true
WechatH5:
AppID: "wx442ee1ac1ee75917"
AppSecret: "c80474909db42f63913b7a307b3bee17"

View File

@ -19,7 +19,6 @@ type Config struct {
WestConfig WestConfig
YushanConfig YushanConfig
SystemConfig SystemConfig
WechatH5 WechatH5Config
}
// JwtAuth 用于 JWT 鉴权配置
@ -88,7 +87,3 @@ type YushanConfig struct {
type SystemConfig struct {
ThreeVerify bool
}
type WechatH5Config struct {
AppID string
AppSecret string
}

View File

@ -241,22 +241,19 @@ func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
)
server.AddRoutes(
rest.WithMiddlewares(
[]rest.Middleware{serverCtx.AuthInterceptor},
[]rest.Route{
{
// query service agent
Method: http.MethodPost,
Path: "/query/service_agent/:product",
Handler: query.QueryServiceAgentHandler(serverCtx),
},
{
Method: http.MethodPost,
Path: "/query/service_app/:product",
Handler: query.QueryServiceAppHandler(serverCtx),
},
}...,
),
[]rest.Route{
{
// query service agent
Method: http.MethodPost,
Path: "/query/service_agent/:product",
Handler: query.QueryServiceAgentHandler(serverCtx),
},
{
Method: http.MethodPost,
Path: "/query/service_app/:product",
Handler: query.QueryServiceAppHandler(serverCtx),
},
},
rest.WithPrefix("/api/v1"),
)
@ -275,6 +272,12 @@ 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,
@ -324,12 +327,6 @@ 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,10 +2,12 @@ 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"
@ -15,6 +17,7 @@ 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"
@ -117,9 +120,9 @@ func (l *QueryServiceLogic) ProcessMarriageLogic(req *types.QueryServiceReq) (*t
"id_card": data.IDCard,
"mobile": data.Mobile,
}
userID, err := l.GetOrCreateUser()
userID, err := l.GetOrCreateUser(data.Mobile)
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 {
@ -177,9 +180,9 @@ func (l *QueryServiceLogic) ProcessHomeServiceLogic(req *types.QueryServiceReq)
"id_card": data.IDCard,
"mobile": data.Mobile,
}
userID, err := l.GetOrCreateUser()
userID, err := l.GetOrCreateUser(data.Mobile)
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 {
@ -238,9 +241,9 @@ func (l *QueryServiceLogic) ProcessRiskAssessmentLogic(req *types.QueryServiceRe
"id_card": data.IDCard,
"mobile": data.Mobile,
}
userID, err := l.GetOrCreateUser()
userID, err := l.GetOrCreateUser(data.Mobile)
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 {
@ -298,9 +301,9 @@ func (l *QueryServiceLogic) ProcessCompanyInfoLogic(req *types.QueryServiceReq)
"id_card": data.IDCard,
"mobile": data.Mobile,
}
userID, err := l.GetOrCreateUser()
userID, err := l.GetOrCreateUser(data.Mobile)
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 {
@ -359,9 +362,9 @@ func (l *QueryServiceLogic) ProcessRentalInfoLogic(req *types.QueryServiceReq) (
"id_card": data.IDCard,
"mobile": data.Mobile,
}
userID, err := l.GetOrCreateUser()
userID, err := l.GetOrCreateUser(data.Mobile)
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 {
@ -420,9 +423,9 @@ func (l *QueryServiceLogic) ProcessPreLoanBackgroundCheckLogic(req *types.QueryS
"id_card": data.IDCard,
"mobile": data.Mobile,
}
userID, err := l.GetOrCreateUser()
userID, err := l.GetOrCreateUser(data.Mobile)
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 {
@ -480,9 +483,9 @@ func (l *QueryServiceLogic) ProcessBackgroundCheckLogic(req *types.QueryServiceR
"id_card": data.IDCard,
"mobile": data.Mobile,
}
userID, err := l.GetOrCreateUser()
userID, err := l.GetOrCreateUser(data.Mobile)
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 {
@ -770,7 +773,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, getUidErr
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "查询服务, 获取用户信息失败, %+v", getUidErr)
}
// AES解密
@ -1387,36 +1390,51 @@ func (l *QueryServiceLogic) CacheData(params map[string]interface{}, Product str
return outTradeNo, 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直接返回
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
}
// 如果不是未登录错误,说明是其他错误,直接返回
if !ctxdata.IsNoUserIdError(err) {
userModel, err := l.svcCtx.UserModel.FindOneByMobile(l.ctx, sql.NullString{String: mobile, Valid: true})
if err != nil && !errors.Is(err, model.ErrNotFound) {
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
// 检查是否是代理查询或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
}
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请求返回未登录错误
if !isAgentQuery {
return 0, ctxdata.ErrNoUserIdInCtx
return nil
}); transErr != nil {
return 0, transErr
}
}
// 创建新用户
return l.svcCtx.UserService.RegisterUUIDUser(l.ctx)
return userModel.Id, nil
}

View File

@ -36,7 +36,7 @@ func NewWxH5AuthLogic(ctx context.Context, svcCtx *svc.ServiceContext) *WxH5Auth
func (l *WxH5AuthLogic) WxH5Auth(req *types.WXH5AuthReq) (resp *types.WXH5AuthResp, err error) {
// Step 1: 使用code获取access_token
accessTokenResp, err := l.GetAccessToken(req.Code)
accessTokenResp, err := GetAccessToken(req.Code)
if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "获取access_token失败: %v", err)
}
@ -108,9 +108,9 @@ type AccessTokenResp struct {
}
// GetAccessToken 通过code获取access_token
func (l *WxH5AuthLogic) GetAccessToken(code string) (*AccessTokenResp, error) {
appID := l.svcCtx.Config.WechatH5.AppID
appSecret := l.svcCtx.Config.WechatH5.AppSecret
func GetAccessToken(code string) (*AccessTokenResp, error) {
appID := "wx442ee1ac1ee75917"
appSecret := "c80474909db42f63913b7a307b3bee17"
url := fmt.Sprintf("https://api.weixin.qq.com/sns/oauth2/access_token?appid=%s&secret=%s&code=%s&grant_type=authorization_code", appID, appSecret, code)

View File

@ -1,55 +0,0 @@
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

@ -1,65 +0,0 @@
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,7 +17,6 @@ type ServiceContext struct {
Config config.Config
Redis *redis.Redis
SourceInterceptor rest.Middleware
AuthInterceptor rest.Middleware
UserModel model.UserModel
UserAuthModel model.UserAuthModel
ProductModel model.ProductModel
@ -53,7 +52,6 @@ type ServiceContext struct {
AsynqService *service.AsynqService // 客户端
VerificationService *service.VerificationService
AgentService *service.AgentService
UserService *service.UserService
}
func NewServiceContext(c config.Config) *ServiceContext {
@ -116,12 +114,10 @@ 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,
@ -157,7 +153,6 @@ func NewServiceContext(c config.Config) *ServiceContext {
AgentActiveStatModel: agentActiveStatModel,
AgentWithdrawalModel: agentWithdrawalModel,
ExampleModel: exampleModel,
UserService: userService,
}
}

View File

@ -16,7 +16,6 @@ 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,47 +3,23 @@ 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
value := ctx.Value(CtxKeyJwtUserId)
if value == nil {
return 0, ErrNoUserIdInCtx
}
// 尝试转换为 json.Number
jsonUid, ok := value.(json.Number)
jsonUid, ok := ctx.Value(CtxKeyJwtUserId).(json.Number)
if !ok {
return 0, fmt.Errorf("%w: 期望类型 json.Number, 实际类型 %T", ErrInvalidUserId, value)
return 0, fmt.Errorf("无法获取用户 ID, CtxKeyJwtUserId = %v", CtxKeyJwtUserId)
}
// 转换为 int64
uid, err := jsonUid.Int64()
if err != nil {
return 0, fmt.Errorf("%w: %v", ErrInvalidUserId, err)
return 0, fmt.Errorf("用户 ID 转换失败: %v", 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)
}