feat(user): temp

This commit is contained in:
liangzai 2024-12-24 11:37:25 +08:00
parent 4748bb0cfb
commit 97e14bbe37
36 changed files with 1980 additions and 656 deletions

View File

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

View File

@ -19,6 +19,10 @@ import (
jwt: JwtAuth jwt: JwtAuth
) )
service main { service main {
@doc "query service"
@handler queryService
post /query/service/:product (QueryServiceReq) returns (QueryServiceResp)
@doc "query marriage" @doc "query marriage"
@handler marriage @handler marriage
post /query/marriage (QueryReq) returns (QueryResp) post /query/marriage (QueryReq) returns (QueryResp)
@ -76,6 +80,10 @@ service main {
@handler queryDetailByOrderId @handler queryDetailByOrderId
get /query/orderId/:order_id (QueryDetailByOrderIdReq) returns (QueryDetailByOrderIdResp) get /query/orderId/:order_id (QueryDetailByOrderIdReq) returns (QueryDetailByOrderIdResp)
@doc "查询详情 按订单号"
@handler queryDetailByOrderNo
get /query/orderNo/:order_no (QueryDetailByOrderNoReq) returns (QueryDetailByOrderNoResp)
@doc "查询详情" @doc "查询详情"
@handler queryDetail @handler queryDetail
get /query/:id (QueryDetailReq) returns (QueryDetailResp) get /query/:id (QueryDetailReq) returns (QueryDetailResp)

View File

@ -16,15 +16,25 @@ type (
} }
) )
type (
QueryServiceReq {
Product string `path:"product"`
Data string `json:"data" validate:"required"`
}
QueryServiceResp {
id string `json:"id"`
}
)
type Query { type Query {
Id int64 `json:"id"` // 主键ID Id int64 `json:"id"` // 主键ID
OrderId int64 `json:"order_id"` // 订单ID OrderId int64 `json:"order_id"` // 订单ID
UserId int64 `json:"user_id"` // 用户ID UserId int64 `json:"user_id"` // 用户ID
ProductId int64 `json:"product_id"` // 产品ID ProductName string `json:"product_name"` // 产品ID
QueryData []map[string]interface{} `json:"query_data"` QueryData []map[string]interface{} `json:"query_data"`
CreateTime string `json:"create_time"` // 创建时间 CreateTime string `json:"create_time"` // 创建时间
UpdateTime string `json:"update_time"` // 更新时间 UpdateTime string `json:"update_time"` // 更新时间
QueryState string `json:"query_state"` // 查询状态 QueryState string `json:"query_state"` // 查询状态
} }
// 获取查询临时订单 // 获取查询临时订单
@ -78,6 +88,15 @@ type (
} }
) )
type (
QueryDetailByOrderNoReq {
OrderNo string `path:"order_no"`
}
QueryDetailByOrderNoResp {
Query
}
)
type ( type (
QueryRetryReq { QueryRetryReq {
Id int64 `path:"id"` Id int64 `path:"id"`

View File

@ -31,6 +31,15 @@ service main {
@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 "wechat mini auth"
@handler wxMiniAuth
post /user/wxMiniAuth (WXMiniAuthReq) returns (WXMiniAuthResp)
@doc "wechat h5 auth"
@handler wxH5Auth
post /user/wxh5Auth (WXH5AuthReq) returns (WXH5AuthResp)
} }
//need login //need login
@ -43,10 +52,6 @@ service main {
@doc "get user info" @doc "get user info"
@handler detail @handler detail
get /user/detail returns (UserInfoResp) get /user/detail returns (UserInfoResp)
@doc "wechat mini auth"
@handler wxMiniAuth
post /user/wxMiniAuth (WXMiniAuthReq) returns (WXMiniAuthResp)
} }
//============================> auth v1 <============================ //============================> auth v1 <============================

View File

@ -62,7 +62,16 @@ type (
RefreshAfter int64 `json:"refreshAfter"` RefreshAfter int64 `json:"refreshAfter"`
} }
) )
type (
WXH5AuthReq {
Code string `json:"code"`
}
WXH5AuthResp {
AccessToken string `json:"accessToken"`
AccessExpire int64 `json:"accessExpire"`
RefreshAfter int64 `json:"refreshAfter"`
}
)
type ( type (
UserInfoResp { UserInfoResp {
UserInfo User `json:"userInfo"` UserInfo User `json:"userInfo"`

View File

@ -14,8 +14,8 @@ VerifyCode:
AccessKeyID: "LTAI5tKGB3TVJbMHSoZN3yr9" AccessKeyID: "LTAI5tKGB3TVJbMHSoZN3yr9"
AccessKeySecret: "OCQ30GWp4yENMjmfOAaagksE18bp65" AccessKeySecret: "OCQ30GWp4yENMjmfOAaagksE18bp65"
EndpointURL: "dysmsapi.aliyuncs.com" EndpointURL: "dysmsapi.aliyuncs.com"
SignName: "天远数据" SignName: "全能查"
TemplateCode: "SMS_474525324" TemplateCode: "SMS_473780047"
ValidTime: 300 ValidTime: 300
Encrypt: Encrypt:
SecretKey: "ff83609b2b24fc73196aac3d3dfb874f" SecretKey: "ff83609b2b24fc73196aac3d3dfb874f"
@ -47,4 +47,6 @@ Applepay:
KeyID: "LAY65829DQ" KeyID: "LAY65829DQ"
LoadPrivateKeyPath: "etc/merchant/AuthKey_LAY65829DQ.p8" LoadPrivateKeyPath: "etc/merchant/AuthKey_LAY65829DQ.p8"
Ali: Ali:
Code: "d55b58829efb41c8aa8e86769cba4844" Code: "d55b58829efb41c8aa8e86769cba4844"
SystemConfig:
ThreeVerify: false

View File

@ -4,7 +4,7 @@ Port: 8888
DataSource: "qnc:5vg67b3UNHu8@tcp(qnc_mysql:3306)/qnc?charset=utf8mb4&parseTime=True&loc=Local" DataSource: "qnc:5vg67b3UNHu8@tcp(qnc_mysql:3306)/qnc?charset=utf8mb4&parseTime=True&loc=Local"
CacheRedis: CacheRedis:
- Host: "qnc_redis:6379" - Host: "qnc_redis:6379"
Pass: "3m3WsgyCKWqz" # Redis 密码,如果未设置则留空 Pass: " " # Redis 密码,如果未设置则留空
Type: "node" # 单节点模式 Type: "node" # 单节点模式
JwtAuth: JwtAuth:
@ -48,4 +48,6 @@ Applepay:
KeyID: "LAY65829DQ" KeyID: "LAY65829DQ"
LoadPrivateKeyPath: "etc/merchant/AuthKey_LAY65829DQ.p8" LoadPrivateKeyPath: "etc/merchant/AuthKey_LAY65829DQ.p8"
Ali: Ali:
Code: "d55b58829efb41c8aa8e86769cba4844" Code: "d55b58829efb41c8aa8e86769cba4844"
SystemConfig:
ThreeVerify: false

View File

@ -7,16 +7,17 @@ import (
type Config struct { type Config struct {
rest.RestConf rest.RestConf
DataSource string DataSource string
CacheRedis cache.CacheConf CacheRedis cache.CacheConf
JwtAuth JwtAuth // JWT 鉴权相关配置 JwtAuth JwtAuth // JWT 鉴权相关配置
VerifyCode VerifyCode VerifyCode VerifyCode
Encrypt Encrypt Encrypt Encrypt
Alipay AlipayConfig Alipay AlipayConfig
Wxpay WxpayConfig Wxpay WxpayConfig
Applepay ApplepayConfig Applepay ApplepayConfig
Ali AliConfig Ali AliConfig
WestConfig WestConfig WestConfig WestConfig
SystemConfig SystemConfig
} }
// JwtAuth 用于 JWT 鉴权配置 // JwtAuth 用于 JWT 鉴权配置
@ -71,3 +72,7 @@ type WestConfig struct {
SecretId string SecretId string
SecretSecondId string SecretSecondId string
} }
type SystemConfig struct {
ThreeVerify bool
}

View File

@ -0,0 +1,29 @@
package query
import (
"net/http"
"github.com/zeromicro/go-zero/rest/httpx"
"qnc-server/app/user/cmd/api/internal/logic/query"
"qnc-server/app/user/cmd/api/internal/svc"
"qnc-server/app/user/cmd/api/internal/types"
"qnc-server/common/result"
"qnc-server/pkg/lzkit/validator"
)
func QueryDetailByOrderNoHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
var req types.QueryDetailByOrderNoReq
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 := query.NewQueryDetailByOrderNoLogic(r.Context(), svcCtx)
resp, err := l.QueryDetailByOrderNo(&req)
result.HttpResult(r, w, resp, err)
}
}

View File

@ -0,0 +1,24 @@
package query
import (
"net/http"
"github.com/zeromicro/go-zero/rest/httpx"
"qnc-server/app/user/cmd/api/internal/logic/query"
"qnc-server/app/user/cmd/api/internal/svc"
"qnc-server/app/user/cmd/api/internal/types"
"qnc-server/common/result"
)
func QueryServiceHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
var req types.QueryServiceReq
if err := httpx.Parse(r, &req); err != nil {
result.ParamErrorResult(r, w, err)
return
}
l := query.NewQueryServiceLogic(r.Context(), svcCtx)
resp, err := l.QueryService(&req)
result.HttpResult(r, w, resp, err)
}
}

View File

@ -49,18 +49,21 @@ func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
) )
server.AddRoutes( server.AddRoutes(
[]rest.Route{ rest.WithMiddlewares(
{ []rest.Middleware{serverCtx.SourceInterceptor},
Method: http.MethodPost, []rest.Route{
Path: "/pay/iap_callback", {
Handler: pay.IapCallbackHandler(serverCtx), Method: http.MethodPost,
}, Path: "/pay/iap_callback",
{ Handler: pay.IapCallbackHandler(serverCtx),
Method: http.MethodPost, },
Path: "/pay/payment", {
Handler: pay.PaymentHandler(serverCtx), Method: http.MethodPost,
}, Path: "/pay/payment",
}, Handler: pay.PaymentHandler(serverCtx),
},
}...,
),
rest.WithJwt(serverCtx.Config.JwtAuth.AccessSecret), rest.WithJwt(serverCtx.Config.JwtAuth.AccessSecret),
rest.WithPrefix("/api/v1"), rest.WithPrefix("/api/v1"),
) )
@ -126,6 +129,12 @@ func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
Path: "/query/riskAssessment", Path: "/query/riskAssessment",
Handler: query.RiskAssessmentHandler(serverCtx), Handler: query.RiskAssessmentHandler(serverCtx),
}, },
{
// query service
Method: http.MethodPost,
Path: "/query/service/:product",
Handler: query.QueryServiceHandler(serverCtx),
},
}, },
rest.WithJwt(serverCtx.Config.JwtAuth.AccessSecret), rest.WithJwt(serverCtx.Config.JwtAuth.AccessSecret),
rest.WithPrefix("/api/v1"), rest.WithPrefix("/api/v1"),
@ -157,6 +166,12 @@ func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
Path: "/query/orderId/:order_id", Path: "/query/orderId/:order_id",
Handler: query.QueryDetailByOrderIdHandler(serverCtx), Handler: query.QueryDetailByOrderIdHandler(serverCtx),
}, },
{
// 查询详情 按订单号
Method: http.MethodGet,
Path: "/query/orderNo/:order_no",
Handler: query.QueryDetailByOrderNoHandler(serverCtx),
},
{ {
// 获取查询临时订单 // 获取查询临时订单
Method: http.MethodGet, Method: http.MethodGet,
@ -194,6 +209,18 @@ func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
Path: "/user/register", Path: "/user/register",
Handler: user.RegisterHandler(serverCtx), Handler: user.RegisterHandler(serverCtx),
}, },
{
// wechat mini auth
Method: http.MethodPost,
Path: "/user/wxMiniAuth",
Handler: user.WxMiniAuthHandler(serverCtx),
},
{
// wechat h5 auth
Method: http.MethodPost,
Path: "/user/wxh5Auth",
Handler: user.WxH5AuthHandler(serverCtx),
},
}, },
rest.WithPrefix("/api/v1"), rest.WithPrefix("/api/v1"),
) )
@ -206,12 +233,6 @@ func RegisterHandlers(server *rest.Server, serverCtx *svc.ServiceContext) {
Path: "/user/detail", Path: "/user/detail",
Handler: user.DetailHandler(serverCtx), Handler: user.DetailHandler(serverCtx),
}, },
{
// wechat mini auth
Method: http.MethodPost,
Path: "/user/wxMiniAuth",
Handler: user.WxMiniAuthHandler(serverCtx),
},
}, },
rest.WithJwt(serverCtx.Config.JwtAuth.AccessSecret), rest.WithJwt(serverCtx.Config.JwtAuth.AccessSecret),
rest.WithPrefix("/api/v1"), rest.WithPrefix("/api/v1"),

View File

@ -0,0 +1,29 @@
package user
import (
"net/http"
"github.com/zeromicro/go-zero/rest/httpx"
"qnc-server/app/user/cmd/api/internal/logic/user"
"qnc-server/app/user/cmd/api/internal/svc"
"qnc-server/app/user/cmd/api/internal/types"
"qnc-server/common/result"
"qnc-server/pkg/lzkit/validator"
)
func WxH5AuthHandler(svcCtx *svc.ServiceContext) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
var req types.WXH5AuthReq
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.NewWxH5AuthLogic(r.Context(), svcCtx)
resp, err := l.WxH5Auth(&req)
result.HttpResult(r, w, resp, err)
}
}

View File

@ -40,7 +40,7 @@ func (l *PaymentLogic) Payment(req *types.PaymentReq) (resp *types.PaymentResp,
if cacheErr != nil { if cacheErr != nil {
return nil, cacheErr return nil, cacheErr
} }
var data types.QueryCache var data types.QueryCacheLoad
err = json.Unmarshal([]byte(cache), &data) err = json.Unmarshal([]byte(cache), &data)
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)
@ -55,7 +55,11 @@ func (l *PaymentLogic) Payment(req *types.PaymentReq) (resp *types.PaymentResp,
if decodeErr != nil { if decodeErr != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "生成订单, 获取AES密钥失败: %+v", decodeErr) return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "生成订单, 获取AES密钥失败: %+v", decodeErr)
} }
encryptParams, aesEncryptErr := crypto.AesEncrypt([]byte(cache), key) params, marshalErr := json.Marshal(data.Params)
if marshalErr != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "生成订单, 序列化参数失败: %+v", marshalErr)
}
encryptParams, aesEncryptErr := crypto.AesEncrypt(params, key)
if aesEncryptErr != nil { if aesEncryptErr != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "生成订单, 加密参数失败: %+v", aesEncryptErr) return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "生成订单, 加密参数失败: %+v", aesEncryptErr)
} }
@ -65,10 +69,10 @@ func (l *PaymentLogic) Payment(req *types.PaymentReq) (resp *types.PaymentResp,
var createOrderErr error var createOrderErr error
if req.PayMethod == "wechatpay" { if req.PayMethod == "wechatpay" {
outTradeNo = l.svcCtx.WechatPayService.GenerateOutTradeNo() outTradeNo = l.svcCtx.WechatPayService.GenerateOutTradeNo()
prepayID, createOrderErr = l.svcCtx.WechatPayService.CreateWechatAppOrder(l.ctx, product.SellPrice, product.Description, outTradeNo) prepayID, createOrderErr = l.svcCtx.WechatPayService.CreateWechatOrder(l.ctx, product.SellPrice, product.Description, outTradeNo)
} else if req.PayMethod == "alipay" { } else if req.PayMethod == "alipay" {
outTradeNo = l.svcCtx.AlipayService.GenerateOutTradeNo() outTradeNo = l.svcCtx.AlipayService.GenerateOutTradeNo()
prepayID, createOrderErr = l.svcCtx.AlipayService.CreateAlipayAppOrder(product.SellPrice, product.Description, outTradeNo) prepayID, createOrderErr = l.svcCtx.AlipayService.CreateAlipayOrder(l.ctx, product.SellPrice, product.Description, outTradeNo)
} else if req.PayMethod == "appleiap" { } else if req.PayMethod == "appleiap" {
outTradeNo = l.svcCtx.ApplePayService.GenerateOutTradeNo() outTradeNo = l.svcCtx.ApplePayService.GenerateOutTradeNo()
prepayID = l.svcCtx.ApplePayService.GetIappayAppID(product.ProductEn) prepayID = l.svcCtx.ApplePayService.GetIappayAppID(product.ProductEn)

View File

@ -94,7 +94,7 @@ func (l *MarriageLogic) Marriage(req *types.QueryReq) (resp *types.QueryResp, er
return nil, errors.Wrapf(xerr.NewErrMsg("验证码不正确"), "婚恋评估, 验证码不正确: %s", data.Mobile) return nil, errors.Wrapf(xerr.NewErrMsg("验证码不正确"), "婚恋评估, 验证码不正确: %s", data.Mobile)
} }
//// 3、二要素三要素核验 //// 3、二要素核验
//twoVerification := service.TwoFactorVerificationRequest{ //twoVerification := service.TwoFactorVerificationRequest{
// Name: data.Name, // Name: data.Name,
// IDCard: data.IDCard, // IDCard: data.IDCard,
@ -106,7 +106,7 @@ func (l *MarriageLogic) Marriage(req *types.QueryReq) (resp *types.QueryResp, er
//if !verification.Passed { //if !verification.Passed {
// return nil, errors.Wrapf(xerr.NewErrCodeMsg(xerr.SERVER_COMMON_ERROR, verification.Err.Error()), "婚恋评估, 二要素验证不通过: %+v", err) // return nil, errors.Wrapf(xerr.NewErrCodeMsg(xerr.SERVER_COMMON_ERROR, verification.Err.Error()), "婚恋评估, 二要素验证不通过: %+v", err)
//} //}
// 3、二要素三要素核验 // 3、三要素核验
threeVerification := service.ThreeFactorVerificationRequest{ threeVerification := service.ThreeFactorVerificationRequest{
Name: data.Name, Name: data.Name,
IDCard: data.IDCard, IDCard: data.IDCard,

View File

@ -65,8 +65,8 @@ func (l *QueryDetailByOrderIdLogic) QueryDetailByOrderId(req *types.QueryDetailB
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "报告查询, 查找订单错误: %+v", err) return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "报告查询, 查找订单错误: %+v", err)
} }
} }
if order.Status != "paid" { if order.Status == "failed" {
return nil, errors.Wrapf(xerr.NewErrCodeMsg(xerr.LOGIC_QUERY_WAIT, ""), "") return nil, errors.Wrapf(xerr.NewErrCodeMsg(xerr.LOGIC_QUERY_ERROR, ""), "")
} }
// 获取报告信息 // 获取报告信息
queryModel, err := l.svcCtx.QueryModel.FindOneByOrderId(l.ctx, req.OrderId) queryModel, err := l.svcCtx.QueryModel.FindOneByOrderId(l.ctx, req.OrderId)
@ -125,7 +125,11 @@ func (l *QueryDetailByOrderIdLogic) QueryDetailByOrderId(req *types.QueryDetailB
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)
} }
product, err := l.svcCtx.ProductModel.FindOne(l.ctx, queryModel.ProductId)
if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "报告查询, 获取商品信息失败, %+v", err)
}
query.ProductName = product.ProductName
return &types.QueryDetailByOrderIdResp{ return &types.QueryDetailByOrderIdResp{
Query: query, Query: query,
}, nil }, nil

View File

@ -0,0 +1,132 @@
package query
import (
"context"
"encoding/hex"
"github.com/jinzhu/copier"
"github.com/pkg/errors"
"qnc-server/common/xerr"
"qnc-server/pkg/lzkit/delay"
"time"
"qnc-server/app/user/cmd/api/internal/svc"
"qnc-server/app/user/cmd/api/internal/types"
"github.com/zeromicro/go-zero/core/logx"
)
type QueryDetailByOrderNoLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
func NewQueryDetailByOrderNoLogic(ctx context.Context, svcCtx *svc.ServiceContext) *QueryDetailByOrderNoLogic {
return &QueryDetailByOrderNoLogic{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
func (l *QueryDetailByOrderNoLogic) QueryDetailByOrderNo(req *types.QueryDetailByOrderNoReq) (resp *types.QueryDetailByOrderNoResp, err error) {
// 获取订单信息
order, err := l.svcCtx.OrderModel.FindOneByOrderNo(l.ctx, req.OrderNo)
if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "报告查询, 查找报告错误: %+v", err)
}
// 创建渐进式延迟策略实例
progressiveDelayOrder, err := delay.New(200*time.Millisecond, 3*time.Second, 10*time.Second, 1.5)
if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "初始化渐进式延迟策略失败: %+v", err)
}
// 等待订单状态变为 "paid"
startTime := time.Now()
for order.Status == "pending" {
if time.Since(startTime) > 10*time.Second {
return nil, errors.Wrapf(xerr.NewErrCodeMsg(xerr.LOGIC_QUERY_WAIT, ""), "")
}
// 使用渐进式延迟,获取下次延迟时间
nextDelay, _ := progressiveDelayOrder.NextDelay()
// 等待一段时间后再查一次订单状态
time.Sleep(nextDelay)
// 再次查找订单
order, err = l.svcCtx.OrderModel.FindOneByOrderNo(l.ctx, req.OrderNo)
if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "报告查询, 查找订单错误: %+v", err)
}
}
if order.Status != "paid" {
return nil, errors.Wrapf(xerr.NewErrCodeMsg(xerr.LOGIC_QUERY_WAIT, ""), "")
}
// 获取报告信息
queryModel, err := l.svcCtx.QueryModel.FindOneByOrderId(l.ctx, order.Id)
if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "报告查询, 查找报告错误: %+v", err)
}
// 创建渐进式延迟实例
progressiveDelayQuery, err := delay.New(200*time.Millisecond, 3*time.Second, 10*time.Second, 1.5)
if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "初始化渐进式延迟策略失败: %+v", err)
}
// 等待 queryModel.QueryState 不再是 "pending"
startTime = time.Now()
for queryModel.QueryState == "pending" {
if time.Since(startTime) > 10*time.Second {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "报告查询超时,查询状态长时间为 'pending'")
}
// 使用渐进式延迟,获取下次延迟时间
nextDelay, _ := progressiveDelayQuery.NextDelay()
// 每隔一段时间检查一次查询状态
time.Sleep(nextDelay)
// 再次查询 report 状态
queryModel, err = l.svcCtx.QueryModel.FindOneByOrderId(l.ctx, order.Id)
if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "报告查询, 查找报告错误: %+v", err)
}
}
// 根据 QueryState 做后续处理
if queryModel.QueryState == "failed" {
return nil, errors.Wrapf(xerr.NewErrCodeMsg(xerr.LOGIC_QUERY_ERROR, ""), "")
}
var query types.Query
query.CreateTime = queryModel.CreateTime.Format("2006-01-02 15:04:05")
query.UpdateTime = queryModel.UpdateTime.Format("2006-01-02 15:04:05")
// 解密查询数据
secretKey := l.svcCtx.Config.Encrypt.SecretKey
key, decodeErr := hex.DecodeString(secretKey)
if decodeErr != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "报告查询, 获取AES解密解药失败, %+v", err)
}
processErr := ProcessQueryData(queryModel.QueryData, &query.QueryData, key)
if processErr != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "报告查询, 报告结果处理失败: %v", processErr)
}
// 复制报告数据
err = copier.Copy(&query, queryModel)
if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "报告查询, 报告结构体复制失败, %+v", err)
}
product, err := l.svcCtx.ProductModel.FindOne(l.ctx, queryModel.ProductId)
if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "报告查询, 获取商品信息失败, %+v", err)
}
query.ProductName = product.ProductName
return &types.QueryDetailByOrderNoResp{
Query: query,
}, nil
}

View File

@ -58,6 +58,11 @@ func (l *QueryDetailLogic) QueryDetail(req *types.QueryDetailReq) (resp *types.Q
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)
} }
product, err := l.svcCtx.ProductModel.FindOne(l.ctx, queryModel.ProductId)
if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "报告查询, 获取商品信息失败, %+v", err)
}
query.ProductName = product.ProductName
return &types.QueryDetailResp{ return &types.QueryDetailResp{
Query: query, Query: query,
}, nil }, nil

View File

@ -51,6 +51,11 @@ func (l *QueryExampleLogic) QueryExample(req *types.QueryExampleReq) (resp *type
if copyErr != nil { if copyErr != 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)
} }
product, err := l.svcCtx.ProductModel.FindOne(l.ctx, queryModel.ProductId)
if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "示例报告, 获取商品信息失败, %+v", err)
}
query.ProductName = product.ProductName
return &types.QueryExampleResp{ return &types.QueryExampleResp{
Query: query, Query: query,
}, nil }, nil

View File

@ -50,6 +50,11 @@ func (l *QueryListLogic) QueryList(req *types.QueryListReq) (resp *types.QueryLi
if copyErr != nil { if copyErr != 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)
} }
product, findProductErr := l.svcCtx.ProductModel.FindOne(l.ctx, queryModel.ProductId)
if findProductErr != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "报告列表查询, 获取商品信息失败, %+v", err)
}
query.ProductName = product.ProductName
list = append(list, query) list = append(list, query)
} }
} }

View File

@ -0,0 +1,717 @@
package query
import (
"context"
"encoding/hex"
"encoding/json"
"fmt"
"github.com/pkg/errors"
"github.com/zeromicro/go-zero/core/stores/redis"
"qnc-server/app/user/cmd/api/internal/service"
"qnc-server/common/ctxdata"
"qnc-server/common/xerr"
"qnc-server/pkg/lzkit/crypto"
"qnc-server/pkg/lzkit/validator"
"time"
"qnc-server/app/user/cmd/api/internal/svc"
"qnc-server/app/user/cmd/api/internal/types"
"github.com/zeromicro/go-zero/core/logx"
)
type QueryServiceLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
func NewQueryServiceLogic(ctx context.Context, svcCtx *svc.ServiceContext) *QueryServiceLogic {
return &QueryServiceLogic{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
func (l *QueryServiceLogic) QueryService(req *types.QueryServiceReq) (resp *types.QueryServiceResp, err error) {
return l.PreprocessLogic(req, req.Product)
}
var productProcessors = map[string]func(*QueryServiceLogic, *types.QueryServiceReq) (*types.QueryServiceResp, error){
"marriage": (*QueryServiceLogic).ProcessMarriageLogic,
"homeservice": (*QueryServiceLogic).ProcessHomeServiceLogic,
"riskassessment": (*QueryServiceLogic).ProcessRiskAssessmentLogic,
"companyinfo": (*QueryServiceLogic).ProcessCompanyInfoLogic,
"rentalinfo": (*QueryServiceLogic).ProcessRentalInfoLogic,
"preloanbackgroundcheck": (*QueryServiceLogic).ProcessPreLoanBackgroundCheckLogic,
"backgroundcheck": (*QueryServiceLogic).ProcessBackgroundCheckLogic,
"toc_marriage": (*QueryServiceLogic).ProcessTocMarriageLogic,
"toc_PersonalBadRecord": (*QueryServiceLogic).ProcessTocPersonalBadRecordLogic,
"toc_ShareholderBusinessRelation": (*QueryServiceLogic).ProcessTocShareholderBusinessRelationLogic,
"toc_PersonalLawsuit": (*QueryServiceLogic).ProcessTocPersonalLawsuitLogic,
"toc_EnterpriseLawsuit": (*QueryServiceLogic).ProcessTocEnterpriseLawsuitLogic,
}
func (l *QueryServiceLogic) PreprocessLogic(req *types.QueryServiceReq, product string) (*types.QueryServiceResp, error) {
if processor, exists := productProcessors[product]; exists {
return processor(l, req) // 调用对应的处理函数
}
return nil, errors.New("未找到相应的处理程序")
}
func (l *QueryServiceLogic) ProcessMarriageLogic(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)
}
// AES解密
decryptData, DecryptDataErr := l.DecryptData(req.Data)
if DecryptDataErr != nil {
return nil, DecryptDataErr
}
// 校验参数
var data types.MarriageReq
if unmarshalErr := json.Unmarshal(decryptData, &data); unmarshalErr != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "查询服务, 解密后的数据格式不正确: %+v", unmarshalErr)
}
if validatorErr := validator.Validate(data); validatorErr != nil {
return nil, errors.Wrapf(xerr.NewErrCodeMsg(xerr.PARAM_VERIFICATION_ERROR, validatorErr.Error()), "查询服务, 参数不正确: %+v", validatorErr)
}
// 校验验证码
verifyCodeErr := l.VerifyCode(data.Mobile, data.Code)
if verifyCodeErr != nil {
return nil, verifyCodeErr
}
// 校验三要素
verifyErr := l.Verify(data.Name, data.IDCard, data.Mobile)
if verifyErr != nil {
return nil, verifyErr
}
// 缓存
params := map[string]interface{}{
"name": data.Name,
"id_card": data.IDCard,
"mobile": data.Mobile,
}
cacheNo, cacheDataErr := l.CacheData(params, "marriage", userID)
if cacheDataErr != nil {
return nil, cacheDataErr
}
return &types.QueryServiceResp{Id: cacheNo}, nil
}
// 处理家政服务相关逻辑
func (l *QueryServiceLogic) ProcessHomeServiceLogic(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)
}
// AES解密
decryptData, DecryptDataErr := l.DecryptData(req.Data)
if DecryptDataErr != nil {
return nil, DecryptDataErr
}
// 校验参数
var data types.HomeServiceReq
if unmarshalErr := json.Unmarshal(decryptData, &data); unmarshalErr != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "查询服务, 解密后的数据格式不正确: %+v", unmarshalErr)
}
if validatorErr := validator.Validate(data); validatorErr != nil {
return nil, errors.Wrapf(xerr.NewErrCodeMsg(xerr.PARAM_VERIFICATION_ERROR, validatorErr.Error()), "查询服务, 参数不正确: %+v", validatorErr)
}
// 校验验证码
verifyCodeErr := l.VerifyCode(data.Mobile, data.Code)
if verifyCodeErr != nil {
return nil, verifyCodeErr
}
// 校验三要素
verifyErr := l.Verify(data.Name, data.IDCard, data.Mobile)
if verifyErr != nil {
return nil, verifyErr
}
// 缓存
params := map[string]interface{}{
"name": data.Name,
"id_card": data.IDCard,
"mobile": data.Mobile,
}
cacheNo, cacheDataErr := l.CacheData(params, "homeservice", userID)
if cacheDataErr != nil {
return nil, cacheDataErr
}
return &types.QueryServiceResp{Id: cacheNo}, nil
}
// 处理风险评估相关逻辑
func (l *QueryServiceLogic) ProcessRiskAssessmentLogic(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)
}
// AES解密
decryptData, DecryptDataErr := l.DecryptData(req.Data)
if DecryptDataErr != nil {
return nil, DecryptDataErr
}
// 校验参数
var data types.RiskAssessmentReq
if unmarshalErr := json.Unmarshal(decryptData, &data); unmarshalErr != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "查询服务, 解密后的数据格式不正确: %+v", unmarshalErr)
}
if validatorErr := validator.Validate(data); validatorErr != nil {
return nil, errors.Wrapf(xerr.NewErrCodeMsg(xerr.PARAM_VERIFICATION_ERROR, validatorErr.Error()), "查询服务, 参数不正确: %+v", validatorErr)
}
// 校验验证码
verifyCodeErr := l.VerifyCode(data.Mobile, data.Code)
if verifyCodeErr != nil {
return nil, verifyCodeErr
}
// 校验三要素
verifyErr := l.Verify(data.Name, data.IDCard, data.Mobile)
if verifyErr != nil {
return nil, verifyErr
}
// 缓存
params := map[string]interface{}{
"name": data.Name,
"id_card": data.IDCard,
"mobile": data.Mobile,
}
cacheNo, cacheDataErr := l.CacheData(params, "riskassessment", userID)
if cacheDataErr != nil {
return nil, cacheDataErr
}
return &types.QueryServiceResp{Id: cacheNo}, nil
}
// 处理公司信息查询相关逻辑
func (l *QueryServiceLogic) ProcessCompanyInfoLogic(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)
}
// AES解密
decryptData, DecryptDataErr := l.DecryptData(req.Data)
if DecryptDataErr != nil {
return nil, DecryptDataErr
}
// 校验参数
var data types.CompanyInfoReq
if unmarshalErr := json.Unmarshal(decryptData, &data); unmarshalErr != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "查询服务, 解密后的数据格式不正确: %+v", unmarshalErr)
}
if validatorErr := validator.Validate(data); validatorErr != nil {
return nil, errors.Wrapf(xerr.NewErrCodeMsg(xerr.PARAM_VERIFICATION_ERROR, validatorErr.Error()), "查询服务, 参数不正确: %+v", validatorErr)
}
// 校验验证码
verifyCodeErr := l.VerifyCode(data.Mobile, data.Code)
if verifyCodeErr != nil {
return nil, verifyCodeErr
}
// 校验三要素
verifyErr := l.Verify(data.Name, data.IDCard, data.Mobile)
if verifyErr != nil {
return nil, verifyErr
}
// 缓存
params := map[string]interface{}{
"name": data.Name,
"id_card": data.IDCard,
"mobile": data.Mobile,
}
cacheNo, cacheDataErr := l.CacheData(params, "companyinfo", userID)
if cacheDataErr != nil {
return nil, cacheDataErr
}
return &types.QueryServiceResp{Id: cacheNo}, nil
}
// 处理租赁信息查询相关逻辑
func (l *QueryServiceLogic) ProcessRentalInfoLogic(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)
}
// AES解密
decryptData, DecryptDataErr := l.DecryptData(req.Data)
if DecryptDataErr != nil {
return nil, DecryptDataErr
}
// 校验参数
var data types.RentalInfoReq
if unmarshalErr := json.Unmarshal(decryptData, &data); unmarshalErr != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "查询服务, 解密后的数据格式不正确: %+v", unmarshalErr)
}
if validatorErr := validator.Validate(data); validatorErr != nil {
return nil, errors.Wrapf(xerr.NewErrCodeMsg(xerr.PARAM_VERIFICATION_ERROR, validatorErr.Error()), "查询服务, 参数不正确: %+v", validatorErr)
}
// 校验验证码
verifyCodeErr := l.VerifyCode(data.Mobile, data.Code)
if verifyCodeErr != nil {
return nil, verifyCodeErr
}
// 校验三要素
verifyErr := l.Verify(data.Name, data.IDCard, data.Mobile)
if verifyErr != nil {
return nil, verifyErr
}
// 缓存
params := map[string]interface{}{
"name": data.Name,
"id_card": data.IDCard,
"mobile": data.Mobile,
}
cacheNo, cacheDataErr := l.CacheData(params, "rentalinfo", userID)
if cacheDataErr != nil {
return nil, cacheDataErr
}
return &types.QueryServiceResp{Id: cacheNo}, nil
}
// 处理贷前背景检查相关逻辑
func (l *QueryServiceLogic) ProcessPreLoanBackgroundCheckLogic(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)
}
// AES解密
decryptData, DecryptDataErr := l.DecryptData(req.Data)
if DecryptDataErr != nil {
return nil, DecryptDataErr
}
// 校验参数
var data types.PreLoanBackgroundCheckReq
if unmarshalErr := json.Unmarshal(decryptData, &data); unmarshalErr != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "查询服务, 解密后的数据格式不正确: %+v", unmarshalErr)
}
if validatorErr := validator.Validate(data); validatorErr != nil {
return nil, errors.Wrapf(xerr.NewErrCodeMsg(xerr.PARAM_VERIFICATION_ERROR, validatorErr.Error()), "查询服务, 参数不正确: %+v", validatorErr)
}
// 校验验证码
verifyCodeErr := l.VerifyCode(data.Mobile, data.Code)
if verifyCodeErr != nil {
return nil, verifyCodeErr
}
// 校验三要素
verifyErr := l.Verify(data.Name, data.IDCard, data.Mobile)
if verifyErr != nil {
return nil, verifyErr
}
// 缓存
params := map[string]interface{}{
"name": data.Name,
"id_card": data.IDCard,
"mobile": data.Mobile,
}
cacheNo, cacheDataErr := l.CacheData(params, "preloanbackgroundcheck", userID)
if cacheDataErr != nil {
return nil, cacheDataErr
}
return &types.QueryServiceResp{Id: cacheNo}, nil
}
// 处理人事背调相关逻辑
func (l *QueryServiceLogic) ProcessBackgroundCheckLogic(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)
}
// AES解密
decryptData, DecryptDataErr := l.DecryptData(req.Data)
if DecryptDataErr != nil {
return nil, DecryptDataErr
}
// 校验参数
var data types.BackgroundCheckReq
if unmarshalErr := json.Unmarshal(decryptData, &data); unmarshalErr != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "查询服务, 解密后的数据格式不正确: %+v", unmarshalErr)
}
if validatorErr := validator.Validate(data); validatorErr != nil {
return nil, errors.Wrapf(xerr.NewErrCodeMsg(xerr.PARAM_VERIFICATION_ERROR, validatorErr.Error()), "查询服务, 参数不正确: %+v", validatorErr)
}
// 校验验证码
verifyCodeErr := l.VerifyCode(data.Mobile, data.Code)
if verifyCodeErr != nil {
return nil, verifyCodeErr
}
// 校验三要素
verifyErr := l.Verify(data.Name, data.IDCard, data.Mobile)
if verifyErr != nil {
return nil, verifyErr
}
// 缓存
params := map[string]interface{}{
"name": data.Name,
"id_card": data.IDCard,
"mobile": data.Mobile,
}
cacheNo, cacheDataErr := l.CacheData(params, "backgroundcheck", userID)
if cacheDataErr != nil {
return nil, cacheDataErr
}
return &types.QueryServiceResp{Id: cacheNo}, nil
}
func (l *QueryServiceLogic) ProcessTocMarriageLogic(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)
}
// AES解密
decryptData, DecryptDataErr := l.DecryptData(req.Data)
if DecryptDataErr != nil {
return nil, DecryptDataErr
}
// 校验参数
var data types.MarriageReq
if unmarshalErr := json.Unmarshal(decryptData, &data); unmarshalErr != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "查询服务, 解密后的数据格式不正确: %+v", unmarshalErr)
}
if validatorErr := validator.Validate(data); validatorErr != nil {
return nil, errors.Wrapf(xerr.NewErrCodeMsg(xerr.PARAM_VERIFICATION_ERROR, validatorErr.Error()), "查询服务, 参数不正确: %+v", validatorErr)
}
// 校验验证码
verifyCodeErr := l.VerifyCode(data.Mobile, data.Code)
if verifyCodeErr != nil {
return nil, verifyCodeErr
}
// 校验三要素
verifyErr := l.Verify(data.Name, data.IDCard, data.Mobile)
if verifyErr != nil {
return nil, verifyErr
}
// 缓存
params := map[string]interface{}{
"name": data.Name,
"id_card": data.IDCard,
"mobile": data.Mobile,
}
cacheNo, cacheDataErr := l.CacheData(params, "toc_marriage", userID)
if cacheDataErr != nil {
return nil, cacheDataErr
}
return &types.QueryServiceResp{Id: cacheNo}, nil
}
func (l *QueryServiceLogic) ProcessTocPersonalBadRecordLogic(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)
}
// AES解密
decryptData, DecryptDataErr := l.DecryptData(req.Data)
if DecryptDataErr != nil {
return nil, DecryptDataErr
}
// 校验参数
var data types.MarriageReq
if unmarshalErr := json.Unmarshal(decryptData, &data); unmarshalErr != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "查询服务, 解密后的数据格式不正确: %+v", unmarshalErr)
}
if validatorErr := validator.Validate(data); validatorErr != nil {
return nil, errors.Wrapf(xerr.NewErrCodeMsg(xerr.PARAM_VERIFICATION_ERROR, validatorErr.Error()), "查询服务, 参数不正确: %+v", validatorErr)
}
// 校验验证码
verifyCodeErr := l.VerifyCode(data.Mobile, data.Code)
if verifyCodeErr != nil {
return nil, verifyCodeErr
}
// 校验三要素
verifyErr := l.Verify(data.Name, data.IDCard, data.Mobile)
if verifyErr != nil {
return nil, verifyErr
}
// 缓存
params := map[string]interface{}{
"name": data.Name,
"id_card": data.IDCard,
"mobile": data.Mobile,
}
cacheNo, cacheDataErr := l.CacheData(params, "toc_PersonalBadRecord", userID)
if cacheDataErr != nil {
return nil, cacheDataErr
}
return &types.QueryServiceResp{Id: cacheNo}, nil
}
func (l *QueryServiceLogic) ProcessTocShareholderBusinessRelationLogic(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)
}
// AES解密
decryptData, DecryptDataErr := l.DecryptData(req.Data)
if DecryptDataErr != nil {
return nil, DecryptDataErr
}
// 校验参数
var data types.MarriageReq
if unmarshalErr := json.Unmarshal(decryptData, &data); unmarshalErr != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "查询服务, 解密后的数据格式不正确: %+v", unmarshalErr)
}
if validatorErr := validator.Validate(data); validatorErr != nil {
return nil, errors.Wrapf(xerr.NewErrCodeMsg(xerr.PARAM_VERIFICATION_ERROR, validatorErr.Error()), "查询服务, 参数不正确: %+v", validatorErr)
}
// 校验验证码
verifyCodeErr := l.VerifyCode(data.Mobile, data.Code)
if verifyCodeErr != nil {
return nil, verifyCodeErr
}
// 校验三要素
verifyErr := l.Verify(data.Name, data.IDCard, data.Mobile)
if verifyErr != nil {
return nil, verifyErr
}
// 缓存
params := map[string]interface{}{
"name": data.Name,
"id_card": data.IDCard,
"mobile": data.Mobile,
}
cacheNo, cacheDataErr := l.CacheData(params, "toc_ShareholderBusinessRelation", userID)
if cacheDataErr != nil {
return nil, cacheDataErr
}
return &types.QueryServiceResp{Id: cacheNo}, nil
}
func (l *QueryServiceLogic) ProcessTocPersonalLawsuitLogic(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)
}
// AES解密
decryptData, DecryptDataErr := l.DecryptData(req.Data)
if DecryptDataErr != nil {
return nil, DecryptDataErr
}
// 校验参数
var data types.MarriageReq
if unmarshalErr := json.Unmarshal(decryptData, &data); unmarshalErr != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "查询服务, 解密后的数据格式不正确: %+v", unmarshalErr)
}
if validatorErr := validator.Validate(data); validatorErr != nil {
return nil, errors.Wrapf(xerr.NewErrCodeMsg(xerr.PARAM_VERIFICATION_ERROR, validatorErr.Error()), "查询服务, 参数不正确: %+v", validatorErr)
}
// 校验验证码
verifyCodeErr := l.VerifyCode(data.Mobile, data.Code)
if verifyCodeErr != nil {
return nil, verifyCodeErr
}
// 校验三要素
verifyErr := l.Verify(data.Name, data.IDCard, data.Mobile)
if verifyErr != nil {
return nil, verifyErr
}
// 缓存
params := map[string]interface{}{
"name": data.Name,
"id_card": data.IDCard,
"mobile": data.Mobile,
}
cacheNo, cacheDataErr := l.CacheData(params, "toc_PersonalLawsuit", userID)
if cacheDataErr != nil {
return nil, cacheDataErr
}
return &types.QueryServiceResp{Id: cacheNo}, nil
}
func (l *QueryServiceLogic) ProcessTocEnterpriseLawsuitLogic(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)
}
// AES解密
decryptData, DecryptDataErr := l.DecryptData(req.Data)
if DecryptDataErr != nil {
return nil, DecryptDataErr
}
// 校验参数
var data types.EntLawsuitReq
if unmarshalErr := json.Unmarshal(decryptData, &data); unmarshalErr != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "查询服务, 解密后的数据格式不正确: %+v", unmarshalErr)
}
if validatorErr := validator.Validate(data); validatorErr != nil {
return nil, errors.Wrapf(xerr.NewErrCodeMsg(xerr.PARAM_VERIFICATION_ERROR, validatorErr.Error()), "查询服务, 参数不正确: %+v", validatorErr)
}
// 校验验证码
verifyCodeErr := l.VerifyCode(data.Mobile, data.Code)
if verifyCodeErr != nil {
return nil, verifyCodeErr
}
// 校验三要素 后期应改为企业二要素
//verifyErr := l.Verify(data, data.IDCard, data.Mobile)
//if verifyErr != nil {
// return nil, verifyErr
//}
// 缓存
params := map[string]interface{}{
"ent_name": data.EntName,
"ent_code": data.EntCode,
}
cacheNo, cacheDataErr := l.CacheData(params, "toc_EnterpriseLawsuit", userID)
if cacheDataErr != nil {
return nil, cacheDataErr
}
return &types.QueryServiceResp{Id: cacheNo}, nil
}
func (l *QueryServiceLogic) DecryptData(data string) ([]byte, error) {
secretKey := l.svcCtx.Config.Encrypt.SecretKey
key, decodeErr := hex.DecodeString(secretKey)
if decodeErr != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "密钥获取失败: %+v", decodeErr)
}
decryptData, aesDecryptErr := crypto.AesDecrypt(data, key)
if aesDecryptErr != nil || len(decryptData) == 0 {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "解密失败: %+v", aesDecryptErr)
}
return decryptData, nil
}
// 校验验证码
func (l *QueryServiceLogic) VerifyCode(mobile string, code string) error {
codeRedisKey := fmt.Sprintf("%s:%s", "query", mobile)
cacheCode, err := l.svcCtx.Redis.Get(codeRedisKey)
if err != nil {
if errors.Is(err, redis.Nil) {
return errors.Wrapf(xerr.NewErrMsg("验证码已过期"), "验证码过期: %s", mobile)
}
return errors.Wrapf(xerr.NewErrCode(xerr.DB_ERROR), "读取验证码redis缓存失败, mobile: %s, err: %+v", mobile, err)
}
if cacheCode != code {
return errors.Wrapf(xerr.NewErrMsg("验证码不正确"), "验证码不正确: %s", mobile)
}
return nil
}
// 二、三要素验证
func (l *QueryServiceLogic) Verify(Name string, IDCard string, Mobile string) error {
if l.svcCtx.Config.SystemConfig.ThreeVerify {
// 三要素验证
threeVerification := service.ThreeFactorVerificationRequest{
Name,
IDCard,
Mobile,
}
verification, err := l.svcCtx.VerificationService.ThreeFactorVerification(threeVerification)
if err != nil {
return errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "三要素验证失败: %+v", err)
}
if !verification.Passed {
return errors.Wrapf(xerr.NewErrCodeMsg(xerr.SERVER_COMMON_ERROR, verification.Err.Error()), "三要素验证不通过: %+v", err)
}
} else {
twoVerification := service.TwoFactorVerificationRequest{
Name,
IDCard,
}
verification, err := l.svcCtx.VerificationService.TwoFactorVerification(twoVerification)
if err != nil {
return errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "二要素验证失败: %+v", err)
}
if !verification.Passed {
return errors.Wrapf(xerr.NewErrCodeMsg(xerr.SERVER_COMMON_ERROR, verification.Err.Error()), "二要素验证不通过: %+v", err)
}
}
return nil
}
// 缓存
func (l *QueryServiceLogic) CacheData(params map[string]interface{}, Product string, userID int64) (string, error) {
queryCache := types.QueryCacheLoad{
Params: params,
Product: Product,
}
jsonData, marshalErr := json.Marshal(queryCache)
if marshalErr != nil {
return "", errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "查询服务, 序列化参数失败: %+v", marshalErr)
}
outTradeNo := l.svcCtx.WechatPayService.GenerateOutTradeNo()
redisKey := fmt.Sprintf("%d:%s", userID, outTradeNo)
cacheErr := l.svcCtx.Redis.SetexCtx(l.ctx, redisKey, string(jsonData), int(2*time.Hour))
if cacheErr != nil {
return "", cacheErr
}
return outTradeNo, nil
}

View File

@ -0,0 +1,134 @@
package user
import (
"context"
"encoding/json"
"fmt"
"github.com/pkg/errors"
"github.com/zeromicro/go-zero/core/stores/sqlx"
"io"
"net/http"
"qnc-server/app/user/model"
jwtx "qnc-server/common/jwt"
"qnc-server/app/user/cmd/api/internal/svc"
"qnc-server/app/user/cmd/api/internal/types"
"github.com/zeromicro/go-zero/core/logx"
)
type WxH5AuthLogic struct {
logx.Logger
ctx context.Context
svcCtx *svc.ServiceContext
}
func NewWxH5AuthLogic(ctx context.Context, svcCtx *svc.ServiceContext) *WxH5AuthLogic {
return &WxH5AuthLogic{
Logger: logx.WithContext(ctx),
ctx: ctx,
svcCtx: svcCtx,
}
}
func (l *WxH5AuthLogic) WxH5Auth(req *types.WXH5AuthReq) (resp *types.WXH5AuthResp, err error) {
// Step 1: 使用code获取access_token
accessTokenResp, err := GetAccessToken(req.Code)
if err != nil {
return nil, errors.Wrap(err, "获取access_token失败")
}
// Step 2: 查找用户授权信息
userAuth, findErr := l.svcCtx.UserAuthModel.FindOneByAuthTypeAuthKey(l.ctx, accessTokenResp.Openid, "h5-weixin")
if findErr != nil && !errors.Is(findErr, model.ErrNotFound) {
return nil, errors.Wrapf(findErr, "查询用户授权失败openid: %s", accessTokenResp.Openid)
}
// Step 3: 查找或创建用户
var user *model.User
if userAuth != nil {
// 授权信息存在,查找用户
userModel, findUserErr := l.svcCtx.UserModel.FindOne(l.ctx, userAuth.UserId)
if findUserErr != nil {
return nil, errors.Wrapf(findUserErr, "查询用户失败userId: %d", userAuth.UserId)
}
user = userModel
} else {
// 授权信息不存在,创建新用户
user = &model.User{}
if transErr := l.svcCtx.UserModel.Trans(l.ctx, func(context context.Context, session sqlx.Session) error {
// 插入数据库
insertResult, insertErr := l.svcCtx.UserModel.Insert(l.ctx, session, user)
if insertErr != nil {
return errors.Wrapf(insertErr, "创建新用户失败openid: %s", accessTokenResp.Openid)
}
// 获取插入后生成的 user.Id
lastInsertId, lastInsertIdErr := insertResult.LastInsertId()
if lastInsertIdErr != nil {
return errors.Wrapf(lastInsertIdErr, "获取新用户ID失败openid: %s", accessTokenResp.Openid)
}
user.Id = lastInsertId
// 创建用户授权信息
userAuth = &model.UserAuth{
UserId: user.Id,
AuthKey: accessTokenResp.Openid,
AuthType: "mp-weixin", // 微信小程序
}
if _, insertUserAuthErr := l.svcCtx.UserAuthModel.Insert(l.ctx, session, userAuth); insertUserAuthErr != nil {
return errors.Wrapf(insertUserAuthErr, "创建用户授权失败openid: %s", accessTokenResp.Openid)
}
return nil
}); transErr != nil {
return nil, transErr
}
}
// Step 4: 生成JWT Token
token, genErr := jwtx.GenerateJwtToken(user.Id, l.svcCtx.Config.JwtAuth.AccessSecret, l.svcCtx.Config.JwtAuth.AccessExpire)
if genErr != nil {
return nil, errors.Wrap(genErr, "生成JWT token失败")
}
// 返回登录信息
return &types.WXH5AuthResp{
AccessToken: token,
AccessExpire: l.svcCtx.Config.JwtAuth.AccessExpire,
RefreshAfter: l.svcCtx.Config.JwtAuth.RefreshAfter,
}, nil
}
type AccessTokenResp struct {
AccessToken string `json:"access_token"`
Openid string `json:"openid"`
}
// GetAccessToken 通过code获取access_token
func GetAccessToken(code string) (*AccessTokenResp, error) {
appID := "wxd1554b7a57cecc9e"
appSecret := "fb8026c0bc66625b580453300d4b43db"
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)
resp, err := http.Get(url)
if err != nil {
return nil, errors.Wrap(err, "获取access_token失败")
}
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
if err != nil {
return nil, errors.Wrap(err, "读取access_token响应失败")
}
var accessTokenResp AccessTokenResp
if err := json.Unmarshal(body, &accessTokenResp); err != nil {
return nil, errors.Wrap(err, "解析access_token响应失败")
}
if accessTokenResp.AccessToken == "" {
return nil, errors.New("获取access_token失败")
}
return &accessTokenResp, nil
}

View File

@ -0,0 +1,41 @@
package middleware
import (
"context"
"net/http"
)
const (
BrandKey = "X-Brand"
PlatformKey = "X-Platform"
)
type SourceInterceptorMiddleware struct {
}
func NewSourceInterceptorMiddleware() *SourceInterceptorMiddleware {
return &SourceInterceptorMiddleware{}
}
func (m *SourceInterceptorMiddleware) Handle(next http.HandlerFunc) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
// 获取请求头 X-Brand 和 X-Platform 的值
brand := r.Header.Get(BrandKey)
platform := r.Header.Get(PlatformKey)
// 将值放入新的 context 中
ctx := r.Context()
if brand != "" {
ctx = context.WithValue(ctx, "brand", brand)
}
if platform != "" {
ctx = context.WithValue(ctx, "platform", platform)
}
// 通过 r.WithContext 将更新后的 ctx 传递给后续的处理函数
r = r.WithContext(ctx)
// 传递给下一个处理器
next(w, r)
}
}

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"
"qnc-server/app/user/cmd/api/internal/svc" "qnc-server/app/user/cmd/api/internal/svc"
"qnc-server/app/user/cmd/api/internal/types"
"qnc-server/app/user/model" "qnc-server/app/user/model"
"qnc-server/pkg/lzkit/crypto" "qnc-server/pkg/lzkit/crypto"
"qnc-server/pkg/lzkit/lzUtils" "qnc-server/pkg/lzkit/lzUtils"
@ -68,42 +67,11 @@ func (l *PaySuccessNotifyUserHandler) ProcessTask(ctx context.Context, t *asynq.
decryptData, aesdecryptErr := crypto.AesDecrypt(query.QueryParams, key) decryptData, aesdecryptErr := crypto.AesDecrypt(query.QueryParams, key)
if aesdecryptErr != nil { if aesdecryptErr != nil {
aesdecryptErr = fmt.Errorf("密响应信息失败: %v", aesdecryptErr) aesdecryptErr = fmt.Errorf("密响应信息失败: %v", aesdecryptErr)
return l.handleError(ctx, aesdecryptErr, order, query) return l.handleError(ctx, aesdecryptErr, order, query)
} }
requests, exists := types.WestDexParams[product.ProductEn]
if !exists {
err = fmt.Errorf("未找到有效的参数配置: productEn: %s", product.ProductEn)
return l.handleError(ctx, err, order, query)
}
// 根据产品类型选择结构体类型
var requestData interface{}
switch product.ProductEn {
case "marriage":
requestData = &types.MarriageReq{}
case "homeservice":
requestData = &types.HomeServiceReq{}
case "riskassessment":
requestData = &types.RiskAssessmentReq{}
case "companyinfo":
requestData = &types.CompanyInfoReq{}
case "rentalinfo":
requestData = &types.RentalInfoReq{}
case "preloanbackgroundcheck":
requestData = &types.PreLoanBackgroundCheckReq{}
case "backgroundcheck":
requestData = &types.BackgroundCheckReq{}
default:
err = fmt.Errorf("未支持的产品类型: productEn: %s", product.ProductEn)
return l.handleError(ctx, err, order, query)
}
unmarshalErr := json.Unmarshal(decryptData, &requestData)
if unmarshalErr != nil {
unmarshalErr = fmt.Errorf("解析参数失败: %v", unmarshalErr)
return l.handleError(ctx, unmarshalErr, order, query)
}
combinedResponse, err := l.svcCtx.WestDexService.ProcessRequests(requestData, requests) combinedResponse, err := l.svcCtx.ApiRequestService.ProcessRequests(decryptData, product.Id)
if err != nil { if err != nil {
return l.handleError(ctx, err, order, query) return l.handleError(ctx, err, order, query)
} }

View File

@ -58,6 +58,51 @@ func (a *AliPayService) CreateAlipayAppOrder(amount float64, subject string, out
return payStr, nil return payStr, nil
} }
// CreateAlipayH5Order 创建支付宝H5支付订单
func (a *AliPayService) CreateAlipayH5Order(amount float64, subject string, outTradeNo string) (string, error) {
amount = 0.01
client := a.AlipayClient
totalAmount := lzUtils.ToAlipayAmount(amount)
// 构造H5支付请求
p := alipay.TradeWapPay{
Trade: alipay.Trade{
Subject: subject,
OutTradeNo: outTradeNo,
TotalAmount: totalAmount,
ProductCode: "QUICK_WAP_WAY", // H5支付专用产品码
NotifyURL: a.config.NotifyUrl, // 异步回调通知地址
ReturnURL: "http://192.168.1.124:5173/#/pages/report",
},
}
// 获取H5支付请求字符串这里会签名
payUrl, err := client.TradeWapPay(p)
if err != nil {
return "", fmt.Errorf("创建支付宝H5订单失败: %v", err)
}
return payUrl.String(), nil
}
// CreateAlipayOrder 根据平台类型创建支付宝支付订单
func (a *AliPayService) CreateAlipayOrder(ctx context.Context, amount float64, subject string, outTradeNo string) (string, error) {
// 根据 ctx 中的 platform 判断平台
platform, platformOk := ctx.Value("platform").(string)
if !platformOk {
return "", fmt.Errorf("无的支付平台: %s", platform)
}
switch platform {
case "app":
// 调用App支付的创建方法
return a.CreateAlipayAppOrder(amount, subject, outTradeNo)
case "h5":
// 调用H5支付的创建方法并传入 returnUrl
return a.CreateAlipayH5Order(amount, subject, outTradeNo)
default:
return "", fmt.Errorf("不支持的支付平台: %s", platform)
}
}
// AliRefund 发起支付宝退款 // AliRefund 发起支付宝退款
func (a *AliPayService) AliRefund(ctx context.Context, outTradeNo string, refundAmount float64) (*alipay.TradeRefundRsp, error) { func (a *AliPayService) AliRefund(ctx context.Context, outTradeNo string, refundAmount float64) (*alipay.TradeRefundRsp, error) {
refund := alipay.TradeRefund{ refund := alipay.TradeRefund{

View File

@ -0,0 +1,526 @@
package service
import (
"context"
"encoding/json"
"errors"
"fmt"
"github.com/Masterminds/squirrel"
"github.com/tidwall/gjson"
"github.com/zeromicro/go-zero/core/logx"
"qnc-server/app/user/cmd/api/internal/config"
"qnc-server/app/user/model"
"qnc-server/pkg/lzkit/crypto"
"sync"
"sync/atomic"
"time"
)
type ApiRequestService struct {
config config.Config
westDexService *WestDexService
featureModel model.FeatureModel
productFeatureModel model.ProductFeatureModel
}
// NewApiRequestService 是一个构造函数,用于初始化 ApiRequestService
func NewApiRequestService(c config.Config, westDexService *WestDexService, featureModel model.FeatureModel, productFeatureModel model.ProductFeatureModel) *ApiRequestService {
return &ApiRequestService{
config: c,
featureModel: featureModel,
productFeatureModel: productFeatureModel,
westDexService: westDexService,
}
}
type APIResponseData struct {
ApiID string `json:"apiID"`
Data json.RawMessage `json:"data"` // 这里用 RawMessage 来存储原始的 data
Success bool `json:"success"`
Timestamp string `json:"timestamp"`
Error string `json:"error,omitempty"`
}
// ProcessRequests 处理请求
func (a *ApiRequestService) ProcessRequests(params []byte, productID int64) ([]byte, error) {
var ctx, cancel = context.WithCancel(context.Background())
defer cancel()
build := a.productFeatureModel.SelectBuilder().Where(squirrel.Eq{
"product_id": productID,
})
productFeatureList, findProductFeatureErr := a.productFeatureModel.FindAll(ctx, build, "")
if findProductFeatureErr != nil {
return nil, findProductFeatureErr
}
var featureIDs []int64
for _, pf := range productFeatureList {
featureIDs = append(featureIDs, pf.FeatureId)
}
if len(featureIDs) == 0 {
return nil, errors.New("featureIDs 是空的")
}
builder := a.featureModel.SelectBuilder().Where(squirrel.Eq{"id": featureIDs})
featureList, findFeatureErr := a.featureModel.FindAll(ctx, builder, "")
if findFeatureErr != nil {
return nil, findFeatureErr
}
if len(featureList) == 0 {
return nil, errors.New("处理请求错误,产品无对应接口功能")
}
var (
wg sync.WaitGroup
resultsCh = make(chan APIResponseData, len(featureList))
errorsCh = make(chan error, len(featureList))
errorCount int32
errorLimit = len(featureList)
)
for i, feature := range featureList {
wg.Add(1)
go func(i int, feature *model.Feature) {
defer wg.Done()
select {
case <-ctx.Done():
return
default:
}
result := APIResponseData{
ApiID: feature.ApiId,
Success: false,
}
// 请求参数预处理
resp, preprocessErr := a.PreprocessRequestApi(params, feature.ApiId)
timestamp := time.Now().Format("2006-01-02 15:04:05")
if preprocessErr != nil {
result.Timestamp = timestamp
result.Error = preprocessErr.Error()
result.Data = resp
resultsCh <- result
errorsCh <- fmt.Errorf("请求预处理失败: %v", preprocessErr)
atomic.AddInt32(&errorCount, 1)
if atomic.LoadInt32(&errorCount) >= int32(errorLimit) {
cancel()
}
return
}
result.Data = resp
result.Success = true
result.Timestamp = timestamp
resultsCh <- result
}(i, feature)
}
go func() {
wg.Wait()
close(resultsCh)
close(errorsCh)
}()
// 收集所有结果并合并
var responseData []APIResponseData
for result := range resultsCh {
responseData = append(responseData, result)
}
if atomic.LoadInt32(&errorCount) >= int32(errorLimit) {
var allErrors []error
for err := range errorsCh {
allErrors = append(allErrors, err)
}
return nil, fmt.Errorf("请求失败次数超过 %d 次: %v", errorLimit, allErrors)
}
combinedResponse, err := json.Marshal(responseData)
if err != nil {
return nil, fmt.Errorf("响应数据转 JSON 失败: %+v", err)
}
return combinedResponse, nil
}
// ------------------------------------请求处理器--------------------------
var requestProcessors = map[string]func(*ApiRequestService, []byte) ([]byte, error){
"G09SC02": (*ApiRequestService).ProcessG09SC02Request,
"G27BJ05": (*ApiRequestService).ProcessG27BJ05Request,
"G26BJ05": (*ApiRequestService).ProcessG26BJ05Request,
"G34BJ03": (*ApiRequestService).ProcessG34BJ03Request,
"G35SC01": (*ApiRequestService).ProcessG35SC01Request,
"G28BJ05": (*ApiRequestService).ProcessG28BJ05Request,
"G05HZ01": (*ApiRequestService).ProcessG05HZ01Request,
"Q23SC01": (*ApiRequestService).ProcessQ23SC01Request,
}
// PreprocessRequestApi 调用指定的请求处理函数
func (a *ApiRequestService) PreprocessRequestApi(params []byte, apiID string) ([]byte, error) {
if processor, exists := requestProcessors[apiID]; exists {
return processor(a, params) // 调用 ApiRequestService 方法
}
return nil, errors.New("api请求, 未找到相应的处理程序")
}
func (a *ApiRequestService) ProcessG09SC02Request(params []byte) ([]byte, error) {
name := gjson.GetBytes(params, "name")
idCard := gjson.GetBytes(params, "id_card")
if !name.Exists() || !idCard.Exists() {
return nil, errors.New("api请求, G09SC02, 获取相关参数失败")
}
request := map[string]interface{}{
"data": map[string]interface{}{
"certNumMan": a.westDexService.Encrypt(idCard.String()),
"nameMan": a.westDexService.Encrypt(name.String()),
},
}
resp, callApiErr := a.westDexService.CallAPI("G09SC02", request)
if callApiErr != nil {
return nil, callApiErr
}
result := gjson.GetBytes(resp, "data.0.maritalStatus")
if result.Exists() {
responseMap := map[string]string{"status": result.String()}
jsonResponse, err := json.Marshal(responseMap)
if err != nil {
return nil, err
}
return jsonResponse, nil
} else {
return nil, errors.New("查询为空")
}
}
func (a *ApiRequestService) ProcessG27BJ05Request(params []byte) ([]byte, error) {
name := gjson.GetBytes(params, "name")
idCard := gjson.GetBytes(params, "id_card")
mobile := gjson.GetBytes(params, "mobile")
if !name.Exists() || !idCard.Exists() || !mobile.Exists() {
return nil, errors.New("api请求, G27BJ05, 获取相关参数失败")
}
request := map[string]interface{}{
"data": map[string]interface{}{
"id": a.westDexService.Encrypt(idCard.String()),
"name": a.westDexService.Encrypt(name.String()),
"cell": a.westDexService.Encrypt(mobile.String()),
},
}
resp, callApiErr := a.westDexService.CallAPI("G27BJ05", request)
if callApiErr != nil {
return nil, callApiErr
}
// 获取 code 字段
codeResult := gjson.GetBytes(resp, "code")
if !codeResult.Exists() {
return nil, fmt.Errorf("code 字段不存在")
}
if codeResult.String() != "00" {
return nil, fmt.Errorf("未匹配到相关结果")
}
// 获取 data 字段
dataResult := gjson.GetBytes(resp, "data")
if !dataResult.Exists() {
return nil, fmt.Errorf("data 字段不存在")
}
// 将 data 字段解析为 map
var dataMap map[string]interface{}
if err := json.Unmarshal([]byte(dataResult.Raw), &dataMap); err != nil {
return nil, fmt.Errorf("解析 data 字段失败: %v", err)
}
// 删除指定字段
delete(dataMap, "swift_number")
delete(dataMap, "DataStrategy")
// 重新编码为 JSON
modifiedData, err := json.Marshal(dataMap)
if err != nil {
return nil, fmt.Errorf("编码修改后的 data 失败: %v", err)
}
return modifiedData, nil
}
func (a *ApiRequestService) ProcessG26BJ05Request(params []byte) ([]byte, error) {
name := gjson.GetBytes(params, "name")
idCard := gjson.GetBytes(params, "id_card")
mobile := gjson.GetBytes(params, "mobile")
if !name.Exists() || !idCard.Exists() || !mobile.Exists() {
return nil, errors.New("api请求, G26BJ05, 获取相关参数失败")
}
request := map[string]interface{}{
"data": map[string]interface{}{
"id": a.westDexService.Encrypt(idCard.String()),
"name": a.westDexService.Encrypt(name.String()),
"cell": a.westDexService.Encrypt(mobile.String()),
"time_range": 5,
},
}
resp, callApiErr := a.westDexService.CallAPI("G26BJ05", request)
if callApiErr != nil {
return nil, callApiErr
}
codeResult := gjson.GetBytes(resp, "code")
if !codeResult.Exists() {
return nil, fmt.Errorf("code 字段不存在")
}
if codeResult.String() != "00" {
return nil, fmt.Errorf("未匹配到相关结果")
}
// 获取 data 字段
dataResult := gjson.GetBytes(resp, "data")
if !dataResult.Exists() {
return nil, fmt.Errorf("data 字段不存在")
}
// 将 data 字段解析为 map
var dataMap map[string]interface{}
if err := json.Unmarshal([]byte(dataResult.Raw), &dataMap); err != nil {
return nil, fmt.Errorf("解析 data 字段失败: %v", err)
}
// 删除指定字段
delete(dataMap, "swift_number")
delete(dataMap, "DataStrategy")
// 重新编码为 JSON
modifiedData, err := json.Marshal(dataMap)
if err != nil {
return nil, fmt.Errorf("编码修改后的 data 失败: %v", err)
}
return modifiedData, nil
}
func (a *ApiRequestService) ProcessG34BJ03Request(params []byte) ([]byte, error) {
name := gjson.GetBytes(params, "name")
idCard := gjson.GetBytes(params, "id_card")
if !name.Exists() || !idCard.Exists() {
return nil, errors.New("api请求, G34BJ03, 获取相关参数失败")
}
request := map[string]interface{}{
"data": map[string]interface{}{
"id_card": a.westDexService.Encrypt(idCard.String()),
"name": a.westDexService.Encrypt(name.String()),
},
}
resp, callApiErr := a.westDexService.CallAPI("G34BJ03", request)
if callApiErr != nil {
return nil, callApiErr
}
dataResult := gjson.GetBytes(resp, "negative_info.data.risk_level")
if dataResult.Exists() {
// 如果字段存在,构造包含 "status" 的 JSON 响应
responseMap := map[string]string{"risk_level": dataResult.String()}
jsonResponse, err := json.Marshal(responseMap)
if err != nil {
return nil, err
}
return jsonResponse, nil
} else {
return nil, errors.New("查询为空")
}
}
func (a *ApiRequestService) ProcessG35SC01Request(params []byte) ([]byte, error) {
name := gjson.GetBytes(params, "name")
idCard := gjson.GetBytes(params, "id_card")
if !name.Exists() || !idCard.Exists() {
return nil, errors.New("api请求, G35SC01, 获取相关参数失败")
}
request := map[string]interface{}{
"data": map[string]interface{}{
"idcard": a.westDexService.Encrypt(idCard.String()),
"name": a.westDexService.Encrypt(name.String()),
"inquired_auth": a.westDexService.GetDateRange(),
},
}
resp, callApiErr := a.westDexService.CallAPI("G35SC01", request)
if callApiErr != nil {
return nil, callApiErr
}
// 第一步:提取外层的 data 字段
dataResult := gjson.GetBytes(resp, "data")
if !dataResult.Exists() {
return nil, fmt.Errorf("外层 data 字段不存在")
}
// 第二步:解析外层 data 的 JSON 字符串
var outerDataMap map[string]interface{}
if err := json.Unmarshal([]byte(dataResult.String()), &outerDataMap); err != nil {
return nil, fmt.Errorf("解析外层 data 字段失败: %v", err)
}
// 第三步:提取内层的 data 字段
innerData, ok := outerDataMap["data"].(string)
if !ok {
return nil, fmt.Errorf("内层 data 字段不存在或类型错误")
}
// 第四步:解析内层 data 的 JSON 字符串
var finalDataMap map[string]interface{}
if err := json.Unmarshal([]byte(innerData), &finalDataMap); err != nil {
return nil, fmt.Errorf("解析内层 data 字段失败: %v", err)
}
// 将最终的 JSON 对象编码为字节数组返回
finalDataBytes, err := json.Marshal(finalDataMap)
if err != nil {
return nil, fmt.Errorf("编码最终的 JSON 对象失败: %v", err)
}
return finalDataBytes, nil
}
func (a *ApiRequestService) ProcessG28BJ05Request(params []byte) ([]byte, error) {
name := gjson.GetBytes(params, "name")
idCard := gjson.GetBytes(params, "id_card")
mobile := gjson.GetBytes(params, "mobile")
if !name.Exists() || !idCard.Exists() || !mobile.Exists() {
return nil, errors.New("api请求, G28BJ05, 获取相关参数失败")
}
request := map[string]interface{}{
"data": map[string]interface{}{
"id": a.westDexService.Encrypt(idCard.String()),
"name": a.westDexService.Encrypt(name.String()),
"cell": a.westDexService.Encrypt(mobile.String()),
},
}
resp, callApiErr := a.westDexService.CallAPI("G28BJ05", request)
if callApiErr != nil {
return nil, callApiErr
}
// 获取 code 字段
codeResult := gjson.GetBytes(resp, "code")
if !codeResult.Exists() {
return nil, fmt.Errorf("code 字段不存在")
}
if codeResult.String() != "00" {
return nil, fmt.Errorf("未匹配到相关结果")
}
// 获取 data 字段
dataResult := gjson.GetBytes(resp, "data")
if !dataResult.Exists() {
return nil, fmt.Errorf("data 字段不存在")
}
// 将 data 字段解析为 map
var dataMap map[string]interface{}
if err := json.Unmarshal([]byte(dataResult.Raw), &dataMap); err != nil {
return nil, fmt.Errorf("解析 data 字段失败: %v", err)
}
// 删除指定字段
delete(dataMap, "swift_number")
delete(dataMap, "DataStrategy")
// 重新编码为 JSON
modifiedData, err := json.Marshal(dataMap)
if err != nil {
return nil, fmt.Errorf("编码修改后的 data 失败: %v", err)
}
return modifiedData, nil
}
func (a *ApiRequestService) ProcessG05HZ01Request(params []byte) ([]byte, error) {
idCard := gjson.GetBytes(params, "id_card")
if !idCard.Exists() {
return nil, errors.New("api请求, G05HZ01, 获取相关参数失败")
}
request := map[string]interface{}{
"pid": crypto.Md5Encrypt(idCard.String()),
}
resp, callApiErr := a.westDexService.G05HZ01CallAPI("G05HZ01", request)
if callApiErr != nil {
return nil, callApiErr
}
// 处理股东人企关系的响应数据
code := gjson.GetBytes(resp, "code")
if !code.Exists() {
return nil, fmt.Errorf("响应中缺少 code 字段")
}
// 判断 code 是否等于 "0000"
if code.String() == "0000" {
// 获取 data 字段的值
data := gjson.GetBytes(resp, "data")
if !data.Exists() {
return nil, fmt.Errorf("响应中缺少 data 字段")
}
// 返回 data 字段的内容
return []byte(data.Raw), nil
}
// code 不等于 "0000",返回错误
return nil, fmt.Errorf("响应code错误%s", code.String())
}
func (a *ApiRequestService) ProcessQ23SC01Request(params []byte) ([]byte, error) {
entName := gjson.GetBytes(params, "ent_name")
entCode := gjson.GetBytes(params, "ent_code")
if !entName.Exists() || !entCode.Exists() {
return nil, errors.New("api请求, Q23SC01, 获取相关参数失败")
}
request := map[string]interface{}{
"data": map[string]interface{}{
"uscc": a.westDexService.Encrypt(entCode.String()),
"org_name": a.westDexService.Encrypt(entName.String()),
"inquired_auth": a.westDexService.GetDateRange(),
},
}
resp, callApiErr := a.westDexService.CallAPI("Q23SC01", request)
logx.Infof("企业涉诉返回%+v", string(resp))
if callApiErr != nil {
return nil, callApiErr
}
// 第一步:提取外层的 data 字段
dataResult := gjson.GetBytes(resp, "data")
if !dataResult.Exists() {
return nil, fmt.Errorf("外层 data 字段不存在")
}
// 第二步:解析外层 data 的 JSON 字符串
var outerDataMap map[string]interface{}
if err := json.Unmarshal([]byte(dataResult.String()), &outerDataMap); err != nil {
return nil, fmt.Errorf("解析外层 data 字段失败: %v", err)
}
// 第三步:提取内层的 data 字段
innerData, ok := outerDataMap["data"].(string)
if !ok {
return nil, fmt.Errorf("内层 data 字段不存在或类型错误")
}
// 第四步:解析内层 data 的 JSON 字符串
var finalDataMap map[string]interface{}
if err := json.Unmarshal([]byte(innerData), &finalDataMap); err != nil {
return nil, fmt.Errorf("解析内层 data 字段失败: %v", err)
}
// 将最终的 JSON 对象编码为字节数组返回
finalDataBytes, err := json.Marshal(finalDataMap)
if err != nil {
return nil, fmt.Errorf("编码最终的 JSON 对象失败: %v", err)
}
statusResult := gjson.GetBytes(finalDataBytes, "status.status")
if statusResult.Exists() || statusResult.Int() == -1 {
return nil, fmt.Errorf("企业涉诉为空: %+v", finalDataBytes)
}
return finalDataBytes, nil
}

View File

@ -103,6 +103,65 @@ func (w *WechatPayService) CreateWechatAppOrder(ctx context.Context, amount floa
return *resp.PrepayId, nil return *resp.PrepayId, nil
} }
// CreateWechatMiniProgramOrder 创建微信小程序支付订单
func (w *WechatPayService) CreateWechatMiniProgramOrder(ctx context.Context, amount float64, description string, outTradeNo string, openid string) (string, error) {
totalAmount := lzUtils.ToWechatAmount(amount)
// 构建支付请求参数
payRequest := jsapi.PrepayRequest{
Appid: core.String(w.config.AppID),
Mchid: core.String(w.config.MchID),
Description: core.String(description),
OutTradeNo: core.String(outTradeNo),
NotifyUrl: core.String(w.config.NotifyUrl),
Amount: &jsapi.Amount{
Total: core.Int64(totalAmount),
},
Payer: &jsapi.Payer{
Openid: core.String(openid), // 用户的 OpenID通过前端传入
}}
// 初始化 AppApiService
svc := jsapi.JsapiApiService{Client: w.wechatClient}
// 发起预支付请求
resp, result, err := svc.PrepayWithRequestPayment(ctx, payRequest)
if err != nil {
return "", fmt.Errorf("微信支付订单创建失败: %v, 状态码: %d", err, result.Response.StatusCode)
}
// 返回预支付交易会话标识
return *resp.PrepayId, nil
}
// CreateWechatOrder 创建微信支付订单(集成 APP、H5、小程序
func (w *WechatPayService) CreateWechatOrder(ctx context.Context, amount float64, description string, outTradeNo string) (string, error) {
// 根据 ctx 中的 platform 判断平台
platform := ctx.Value("platform").(string)
var prepayId string
var err error
switch platform {
case "mp-weixin":
// 如果是小程序平台,调用小程序支付订单创建
prepayId, err = w.CreateWechatMiniProgramOrder(ctx, amount, description, outTradeNo, "asdasd")
case "app":
// 如果是 APP 平台,调用 APP 支付订单创建
prepayId, err = w.CreateWechatAppOrder(ctx, amount, description, outTradeNo)
default:
return "", fmt.Errorf("不支持的支付平台: %s", platform)
}
// 如果创建支付订单失败,返回错误
if err != nil {
return "", fmt.Errorf("支付订单创建失败: %v", err)
}
// 返回预支付ID
return prepayId, nil
}
// HandleWechatPayNotification 处理微信支付回调 // HandleWechatPayNotification 处理微信支付回调
func (w *WechatPayService) HandleWechatPayNotification(ctx context.Context, req *http.Request) (*payments.Transaction, error) { func (w *WechatPayService) HandleWechatPayNotification(ctx context.Context, req *http.Request) (*payments.Transaction, error) {
transaction := new(payments.Transaction) transaction := new(payments.Transaction)

View File

@ -2,21 +2,14 @@ package service
import ( import (
"bytes" "bytes"
"context"
"encoding/json" "encoding/json"
"fmt" "fmt"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/tidwall/gjson"
"github.com/zeromicro/go-zero/core/logx"
"io" "io"
"net/http" "net/http"
"qnc-server/app/user/cmd/api/internal/config" "qnc-server/app/user/cmd/api/internal/config"
"qnc-server/app/user/cmd/api/internal/types"
"qnc-server/pkg/lzkit/crypto" "qnc-server/pkg/lzkit/crypto"
"reflect"
"strconv" "strconv"
"sync"
"sync/atomic"
"time" "time"
) )
@ -39,13 +32,6 @@ type G05HZ01WestResp struct {
type WestDexService struct { type WestDexService struct {
config config.WestConfig config config.WestConfig
} }
type APIResponseData struct {
ApiID string `json:"apiID"`
Data json.RawMessage `json:"data"` // 这里用 RawMessage 来存储原始的 data
Success bool `json:"success"`
Timestamp string `json:"timestamp"`
Error string `json:"error,omitempty"`
}
// NewWestDexService 是一个构造函数,用于初始化 WestDexService // NewWestDexService 是一个构造函数,用于初始化 WestDexService
func NewWestDexService(c config.Config) *WestDexService { func NewWestDexService(c config.Config) *WestDexService {
@ -103,7 +89,6 @@ func (w *WestDexService) CallAPI(code string, reqData map[string]interface{}) (r
if UnmarshalErr != nil { if UnmarshalErr != nil {
return nil, UnmarshalErr return nil, UnmarshalErr
} }
logx.Infof("西部数据请求响应, code: %s, response: %v", code, westDexResp)
if westDexResp.Code != "00000" { if westDexResp.Code != "00000" {
if westDexResp.Data == "" { if westDexResp.Data == "" {
return nil, errors.New(westDexResp.Message) return nil, errors.New(westDexResp.Message)
@ -178,7 +163,6 @@ func (w *WestDexService) G05HZ01CallAPI(code string, reqData map[string]interfac
if UnmarshalErr != nil { if UnmarshalErr != nil {
return nil, UnmarshalErr return nil, UnmarshalErr
} }
logx.Infof("西部数据请求响应, code: %s, response: %v", code, westDexResp)
if westDexResp.Code != "0000" { if westDexResp.Code != "0000" {
if westDexResp.Data == nil { if westDexResp.Data == nil {
return nil, errors.New(westDexResp.Message) return nil, errors.New(westDexResp.Message)
@ -194,512 +178,16 @@ func (w *WestDexService) G05HZ01CallAPI(code string, reqData map[string]interfac
return nil, fmt.Errorf("西部请求失败Code: %d", httpResp.StatusCode) return nil, fmt.Errorf("西部请求失败Code: %d", httpResp.StatusCode)
} }
// EncryptStructFields 加密字段的函数,处理不同类型,并跳过空值字段 func (w *WestDexService) Encrypt(data string) string {
func (w *WestDexService) EncryptStructFields(inputStruct interface{}) (map[string]interface{}, error) { encryptedValue, err := crypto.WestDexEncrypt(data, w.config.Key)
encryptedFields := make(map[string]interface{})
// 使用反射获取结构体的类型和值
v := reflect.ValueOf(inputStruct)
// 检查并解引用指针类型
if v.Kind() == reflect.Ptr {
v = v.Elem()
}
if v.Kind() != reflect.Struct {
return nil, errors.New("传入的interfact不是struct")
}
// 遍历结构体字段
for i := 0; i < v.NumField(); i++ {
field := v.Type().Field(i)
fieldValue := v.Field(i)
// 检查字段的 encrypt 标签是否为 "false"
encryptTag := field.Tag.Get("encrypt")
if encryptTag == "false" {
encryptedFields[field.Name] = fieldValue.Interface()
continue
}
// 如果字段为空值,跳过
if fieldValue.IsZero() {
continue
}
// 将字段的值转换为字符串进行加密
strValue := fmt.Sprintf("%v", fieldValue.Interface())
// 执行加密操作
encryptedValue, err := crypto.WestDexEncrypt(strValue, w.config.Key)
if err != nil {
return nil, err
}
// 将加密后的值存入结果映射
encryptedFields[field.Name] = encryptedValue
}
return encryptedFields, nil
}
// MapStructToAPIRequest 字段映射
func (w *WestDexService) MapStructToAPIRequest(encryptedFields map[string]interface{}, fieldMapping map[string]string, wrapField string) map[string]interface{} {
apiRequest := make(map[string]interface{})
// 遍历字段映射表
for structField, apiField := range fieldMapping {
// 如果加密后的字段存在,才添加到请求
if structField == "InquiredAuth" {
apiRequest[apiField] = GetDateRange()
} else if structField == "TimeRange" {
apiRequest[apiField] = "5"
} else if value, exists := encryptedFields[structField]; exists {
apiRequest[apiField] = value
}
}
// 如果 wrapField 不为空,将 apiRequest 包裹到该字段下
if wrapField != "" {
return map[string]interface{}{
wrapField: apiRequest,
}
}
return apiRequest
}
// ProcessRequests 批量处理
func (w *WestDexService) ProcessRequests(data interface{}, requests []types.WestDexServiceRequestParams) ([]byte, error) {
var (
wg sync.WaitGroup
resultsCh = make(chan APIResponseData, len(requests))
errorsCh = make(chan error, len(requests))
ctx, cancel = context.WithCancel(context.Background())
errorCount int32
errorLimit = 4
)
defer cancel()
for i, req := range requests {
wg.Add(1)
go func(i int, req types.WestDexServiceRequestParams) {
defer wg.Done()
select {
case <-ctx.Done():
return
default:
}
// 请求参数预处理
apiRequest, preprocessErr := w.PreprocessRequestParams(req.ApiID, data)
if preprocessErr != nil {
errorsCh <- fmt.Errorf("请求预处理失败: %v", preprocessErr)
atomic.AddInt32(&errorCount, 1)
if atomic.LoadInt32(&errorCount) >= int32(errorLimit) {
cancel()
}
return
}
var resp []byte
var callApiErr error
if req.ApiID == "G05HZ01" {
resp, callApiErr = w.G05HZ01CallAPI(req.ApiID, apiRequest)
} else {
resp, callApiErr = w.CallAPI(req.ApiID, apiRequest)
}
timestamp := time.Now().Format("2006-01-02 15:04:05")
result := APIResponseData{
ApiID: req.ApiID,
Success: false,
Timestamp: timestamp,
}
if callApiErr != nil {
errorsCh <- fmt.Errorf("西部请求, 请求失败: %+v", callApiErr)
atomic.AddInt32(&errorCount, 1)
if atomic.LoadInt32(&errorCount) >= int32(errorLimit) {
cancel()
}
result.Error = callApiErr.Error()
result.Data = resp
resultsCh <- result
return
}
processedResp, processErr := processResponse(resp, req.ApiID)
if processErr != nil {
errorsCh <- fmt.Errorf("处理响应失败: %v", processErr)
atomic.AddInt32(&errorCount, 1)
if atomic.LoadInt32(&errorCount) >= int32(errorLimit) {
cancel()
}
result.Error = processErr.Error()
} else {
result.Data = processedResp
result.Success = true
}
resultsCh <- result
}(i, req)
}
go func() {
wg.Wait()
close(resultsCh)
close(errorsCh)
}()
// 收集所有结果并合并
var responseData []APIResponseData
for result := range resultsCh {
responseData = append(responseData, result)
}
if atomic.LoadInt32(&errorCount) >= int32(errorLimit) {
var allErrors []error
for err := range errorsCh {
allErrors = append(allErrors, err)
}
return nil, fmt.Errorf("请求失败次数超过 %d 次: %v", errorLimit, allErrors)
}
combinedResponse, err := json.Marshal(responseData)
if err != nil { if err != nil {
return nil, fmt.Errorf("响应数据转 JSON 失败: %+v", err) panic("WestDexEncrypt error: " + err.Error())
} }
return encryptedValue
return combinedResponse, nil
}
// ------------------------------------请求处理器--------------------------
var requestProcessors = map[string]func(*WestDexService, interface{}) (map[string]interface{}, error){
"G09SC02": (*WestDexService).ProcessG09SC02Request,
"G27BJ05": (*WestDexService).ProcessG27BJ05Request,
"G26BJ05": (*WestDexService).ProcessG26BJ05Request,
"G34BJ03": (*WestDexService).ProcessG34BJ03Request,
"G35SC01": (*WestDexService).ProcessG35SC01Request,
"G28BJ05": (*WestDexService).ProcessG28BJ05Request,
"G05HZ01": (*WestDexService).ProcessG05HZ01Request,
}
// PreprocessRequestParams 调用指定的请求处理函数
func (w *WestDexService) PreprocessRequestParams(apiID string, params interface{}) (map[string]interface{}, error) {
if processor, exists := requestProcessors[apiID]; exists {
return processor(w, params) // 调用 WestDexService 方法
}
var request map[string]interface{}
return request, nil
}
// / 将处理函数作为 WestDexService 的方法
func (w *WestDexService) ProcessG09SC02Request(params interface{}) (map[string]interface{}, error) {
encryptedFields, err := w.EncryptStructFields(params)
if err != nil {
return nil, fmt.Errorf("西部请求, 生成请求数据失败: %+v", err)
}
apiRequest := w.MapStructToAPIRequest(encryptedFields, types.G09SC02FieldMapping, "data")
return apiRequest, nil
}
func (w *WestDexService) ProcessG27BJ05Request(params interface{}) (map[string]interface{}, error) {
encryptedFields, err := w.EncryptStructFields(params)
if err != nil {
return nil, fmt.Errorf("西部请求, 生成请求数据失败: %+v", err)
}
apiRequest := w.MapStructToAPIRequest(encryptedFields, types.G27BJ05FieldMapping, "data")
return apiRequest, nil
}
func (w *WestDexService) ProcessG26BJ05Request(params interface{}) (map[string]interface{}, error) {
// 特殊名单 G26BJ05
encryptedFields, err := w.EncryptStructFields(params)
if err != nil {
return nil, fmt.Errorf("西部请求, 生成请求数据失败: %+v", err)
}
apiRequest := w.MapStructToAPIRequest(encryptedFields, types.G26BJ05FieldMapping, "data")
return apiRequest, nil
}
func (w *WestDexService) ProcessG34BJ03Request(params interface{}) (map[string]interface{}, error) {
// 个人不良 G34BJ03
encryptedFields, err := w.EncryptStructFields(params)
if err != nil {
return nil, fmt.Errorf("西部请求, 生成请求数据失败: %+v", err)
}
apiRequest := w.MapStructToAPIRequest(encryptedFields, types.G34BJ03FieldMapping, "data")
return apiRequest, nil
}
func (w *WestDexService) ProcessG35SC01Request(params interface{}) (map[string]interface{}, error) {
// 个人涉诉 G35SC01
encryptedFields, err := w.EncryptStructFields(params)
if err != nil {
return nil, fmt.Errorf("西部请求, 生成请求数据失败: %+v", err)
}
apiRequest := w.MapStructToAPIRequest(encryptedFields, types.G35SC01FieldMapping, "data")
return apiRequest, nil
}
func (w *WestDexService) ProcessG28BJ05Request(params interface{}) (map[string]interface{}, error) {
// 借贷行为 G28BJ05
encryptedFields, err := w.EncryptStructFields(params)
if err != nil {
return nil, fmt.Errorf("西部请求, 生成请求数据失败: %+v", err)
}
apiRequest := w.MapStructToAPIRequest(encryptedFields, types.G28BJ05FieldMapping, "data")
return apiRequest, nil
}
func (w *WestDexService) ProcessG05HZ01Request(params interface{}) (map[string]interface{}, error) {
// 使用 reflect 获取 params 的值和类型
val := reflect.ValueOf(params)
if val.Kind() == reflect.Ptr {
val = val.Elem() // 如果是指针,获取指向的实际值
}
if val.Kind() != reflect.Struct {
return nil, fmt.Errorf("请求参数必须是结构体类型")
}
// 初始化一个 map 来存储加密后的字段
encryptedFields := make(map[string]interface{})
// 遍历结构体字段,将其转换为 map[string]interface{}
valType := val.Type()
for i := 0; i < val.NumField(); i++ {
field := val.Field(i)
fieldName := valType.Field(i).Name
// 如果字段名为 "IDCard",对其值进行加密
if fieldName == "IDCard" {
if field.Kind() != reflect.String {
return nil, fmt.Errorf("IDCard 字段不是字符串类型")
}
idCard := field.String()
encryptedIDCard := crypto.Md5Encrypt(idCard)
encryptedFields[fieldName] = encryptedIDCard
} else {
// 否则直接将字段值添加到 map 中
encryptedFields[fieldName] = field.Interface()
}
}
// 使用字段映射表生成最终的 API 请求
apiRequest := w.MapStructToAPIRequest(encryptedFields, types.G05HZ01FieldMapping, "")
return apiRequest, nil
}
// -----------------------------------------------------------------------------
// 响应处理器
var responseProcessors = map[string]func([]byte) ([]byte, error){
"G09SC02": processG09SC02Response, // 单人婚姻
"G27BJ05": processG27BJ05Response, // 借贷意向
"G28BJ05": processG28BJ05Response, // 借贷行为
"G26BJ05": processG26BJ05Response, // 特殊名单
"G05HZ01": processG05HZ01Response, // 股东人企关系
"G34BJ03": processG34BJ03Response, // 个人不良
"G35SC01": processG35SC01Response, // 个人涉诉
}
// processResponse 处理响应数据
func processResponse(resp []byte, apiID string) ([]byte, error) {
if processor, exists := responseProcessors[apiID]; exists {
return processor(resp)
}
return resp, nil
}
func processG09SC02Response(resp []byte) ([]byte, error) {
result := gjson.GetBytes(resp, "data.0.maritalStatus")
if result.Exists() {
// 如果字段存在,构造包含 "status" 的 JSON 响应
responseMap := map[string]string{"status": result.String()}
jsonResponse, err := json.Marshal(responseMap)
if err != nil {
return nil, err
}
return jsonResponse, nil
} else {
return nil, errors.New("查询为空")
}
}
func processG27BJ05Response(resp []byte) ([]byte, error) {
// 获取 code 字段
codeResult := gjson.GetBytes(resp, "code")
if !codeResult.Exists() {
return nil, fmt.Errorf("code 字段不存在")
}
if codeResult.String() != "00" {
return nil, fmt.Errorf("未匹配到相关结果")
}
// 获取 data 字段
dataResult := gjson.GetBytes(resp, "data")
if !dataResult.Exists() {
return nil, fmt.Errorf("data 字段不存在")
}
// 将 data 字段解析为 map
var dataMap map[string]interface{}
if err := json.Unmarshal([]byte(dataResult.Raw), &dataMap); err != nil {
return nil, fmt.Errorf("解析 data 字段失败: %v", err)
}
// 删除指定字段
delete(dataMap, "swift_number")
delete(dataMap, "DataStrategy")
// 重新编码为 JSON
modifiedData, err := json.Marshal(dataMap)
if err != nil {
return nil, fmt.Errorf("编码修改后的 data 失败: %v", err)
}
return modifiedData, nil
}
func processG28BJ05Response(resp []byte) ([]byte, error) {
// 处理借贷行为的响应数据
// 获取 code 字段
codeResult := gjson.GetBytes(resp, "code")
if !codeResult.Exists() {
return nil, fmt.Errorf("code 字段不存在")
}
if codeResult.String() != "00" {
return nil, fmt.Errorf("未匹配到相关结果")
}
// 获取 data 字段
dataResult := gjson.GetBytes(resp, "data")
if !dataResult.Exists() {
return nil, fmt.Errorf("data 字段不存在")
}
// 将 data 字段解析为 map
var dataMap map[string]interface{}
if err := json.Unmarshal([]byte(dataResult.Raw), &dataMap); err != nil {
return nil, fmt.Errorf("解析 data 字段失败: %v", err)
}
// 删除指定字段
delete(dataMap, "swift_number")
delete(dataMap, "DataStrategy")
// 重新编码为 JSON
modifiedData, err := json.Marshal(dataMap)
if err != nil {
return nil, fmt.Errorf("编码修改后的 data 失败: %v", err)
}
return modifiedData, nil
}
func processG26BJ05Response(resp []byte) ([]byte, error) {
// 处理特殊名单的响应数据
// 获取 code 字段
codeResult := gjson.GetBytes(resp, "code")
if !codeResult.Exists() {
return nil, fmt.Errorf("code 字段不存在")
}
if codeResult.String() != "00" {
return nil, fmt.Errorf("未匹配到相关结果")
}
// 获取 data 字段
dataResult := gjson.GetBytes(resp, "data")
if !dataResult.Exists() {
return nil, fmt.Errorf("data 字段不存在")
}
// 将 data 字段解析为 map
var dataMap map[string]interface{}
if err := json.Unmarshal([]byte(dataResult.Raw), &dataMap); err != nil {
return nil, fmt.Errorf("解析 data 字段失败: %v", err)
}
// 删除指定字段
delete(dataMap, "swift_number")
delete(dataMap, "DataStrategy")
// 重新编码为 JSON
modifiedData, err := json.Marshal(dataMap)
if err != nil {
return nil, fmt.Errorf("编码修改后的 data 失败: %v", err)
}
return modifiedData, nil
}
func processG05HZ01Response(resp []byte) ([]byte, error) {
// 处理股东人企关系的响应数据
code := gjson.GetBytes(resp, "code")
if !code.Exists() {
return nil, fmt.Errorf("响应中缺少 code 字段")
}
// 判断 code 是否等于 "0000"
if code.String() == "0000" {
// 获取 data 字段的值
data := gjson.GetBytes(resp, "data")
if !data.Exists() {
return nil, fmt.Errorf("响应中缺少 data 字段")
}
// 返回 data 字段的内容
return []byte(data.Raw), nil
}
// code 不等于 "0000",返回错误
return nil, fmt.Errorf("响应code错误%s", code.String())
}
func processG34BJ03Response(resp []byte) ([]byte, error) {
// 处理个人不良的响应数据
dataResult := gjson.GetBytes(resp, "negative_info.data.risk_level")
if dataResult.Exists() {
// 如果字段存在,构造包含 "status" 的 JSON 响应
responseMap := map[string]string{"risk_level": dataResult.String()}
jsonResponse, err := json.Marshal(responseMap)
if err != nil {
return nil, err
}
return jsonResponse, nil
} else {
return nil, errors.New("查询为空")
}
}
func processG35SC01Response(resp []byte) ([]byte, error) {
// 第一步:提取外层的 data 字段
dataResult := gjson.GetBytes(resp, "data")
if !dataResult.Exists() {
return nil, fmt.Errorf("外层 data 字段不存在")
}
// 第二步:解析外层 data 的 JSON 字符串
var outerDataMap map[string]interface{}
if err := json.Unmarshal([]byte(dataResult.String()), &outerDataMap); err != nil {
return nil, fmt.Errorf("解析外层 data 字段失败: %v", err)
}
// 第三步:提取内层的 data 字段
innerData, ok := outerDataMap["data"].(string)
if !ok {
return nil, fmt.Errorf("内层 data 字段不存在或类型错误")
}
// 第四步:解析内层 data 的 JSON 字符串
var finalDataMap map[string]interface{}
if err := json.Unmarshal([]byte(innerData), &finalDataMap); err != nil {
return nil, fmt.Errorf("解析内层 data 字段失败: %v", err)
}
// 将最终的 JSON 对象编码为字节数组返回
finalDataBytes, err := json.Marshal(finalDataMap)
if err != nil {
return nil, fmt.Errorf("编码最终的 JSON 对象失败: %v", err)
}
return finalDataBytes, nil
} }
// GetDateRange 返回今天到明天的日期范围,格式为 "yyyyMMdd-yyyyMMdd" // GetDateRange 返回今天到明天的日期范围,格式为 "yyyyMMdd-yyyyMMdd"
func GetDateRange() string { func (w *WestDexService) GetDateRange() string {
today := time.Now().Format("20060102") // 获取今天的日期 today := time.Now().Format("20060102") // 获取今天的日期
tomorrow := time.Now().Add(24 * time.Hour).Format("20060102") // 获取明天的日期 tomorrow := time.Now().Add(24 * time.Hour).Format("20060102") // 获取明天的日期
return fmt.Sprintf("%s-%s", today, tomorrow) // 拼接日期范围并返回 return fmt.Sprintf("%s-%s", today, tomorrow) // 拼接日期范围并返回

View File

@ -5,7 +5,9 @@ import (
"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" "github.com/zeromicro/go-zero/core/stores/sqlx"
"github.com/zeromicro/go-zero/rest"
"qnc-server/app/user/cmd/api/internal/config" "qnc-server/app/user/cmd/api/internal/config"
"qnc-server/app/user/cmd/api/internal/middleware"
"qnc-server/app/user/cmd/api/internal/service" "qnc-server/app/user/cmd/api/internal/service"
"qnc-server/app/user/model" "qnc-server/app/user/model"
) )
@ -13,6 +15,7 @@ import (
type ServiceContext struct { type ServiceContext struct {
Config config.Config Config config.Config
Redis *redis.Redis Redis *redis.Redis
SourceInterceptor rest.Middleware
UserModel model.UserModel UserModel model.UserModel
UserAuthModel model.UserAuthModel UserAuthModel model.UserAuthModel
ProductModel model.ProductModel ProductModel model.ProductModel
@ -24,6 +27,7 @@ type ServiceContext struct {
WechatPayService *service.WechatPayService WechatPayService *service.WechatPayService
ApplePayService *service.ApplePayService ApplePayService *service.ApplePayService
WestDexService *service.WestDexService WestDexService *service.WestDexService
ApiRequestService *service.ApiRequestService
AsynqServer *asynq.Server // 服务端 AsynqServer *asynq.Server // 服务端
AsynqService *service.AsynqService // 客户端 AsynqService *service.AsynqService // 客户端
VerificationService *service.VerificationService VerificationService *service.VerificationService
@ -47,23 +51,27 @@ func NewServiceContext(c config.Config) *ServiceContext {
}, },
) )
westDexService := service.NewWestDexService(c) westDexService := service.NewWestDexService(c)
productFeatureModel := model.NewProductFeatureModel(db, c.CacheRedis)
featureModel := model.NewFeatureModel(db, c.CacheRedis)
return &ServiceContext{ return &ServiceContext{
Config: c, Config: c,
Redis: redis.MustNewRedis(redisConf), Redis: redis.MustNewRedis(redisConf),
SourceInterceptor: middleware.NewSourceInterceptorMiddleware().Handle,
AlipayService: service.NewAliPayService(c), AlipayService: service.NewAliPayService(c),
WechatPayService: service.NewWechatPayService(c), WechatPayService: service.NewWechatPayService(c),
ApplePayService: service.NewApplePayService(c), ApplePayService: service.NewApplePayService(c),
WestDexService: westDexService, WestDexService: westDexService,
VerificationService: service.NewVerificationService(c, westDexService), VerificationService: service.NewVerificationService(c, westDexService),
AsynqServer: asynqServer, AsynqServer: asynqServer,
ApiRequestService: service.NewApiRequestService(c, westDexService, featureModel, productFeatureModel),
AsynqService: service.NewAsynqService(c), AsynqService: service.NewAsynqService(c),
UserModel: model.NewUserModel(db, c.CacheRedis), UserModel: model.NewUserModel(db, c.CacheRedis),
UserAuthModel: model.NewUserAuthModel(db, c.CacheRedis), UserAuthModel: model.NewUserAuthModel(db, c.CacheRedis),
ProductModel: model.NewProductModel(db, c.CacheRedis), ProductModel: model.NewProductModel(db, c.CacheRedis),
OrderModel: model.NewOrderModel(db, c.CacheRedis), OrderModel: model.NewOrderModel(db, c.CacheRedis),
QueryModel: model.NewQueryModel(db, c.CacheRedis), QueryModel: model.NewQueryModel(db, c.CacheRedis),
FeatureModel: model.NewFeatureModel(db, c.CacheRedis), FeatureModel: featureModel,
ProductFeatureModel: model.NewProductFeatureModel(db, c.CacheRedis), ProductFeatureModel: productFeatureModel,
} }
} }
func (s *ServiceContext) Close() { func (s *ServiceContext) Close() {

View File

@ -6,3 +6,7 @@ type QueryCache struct {
Mobile string `json:"mobile"` Mobile string `json:"mobile"`
Product string `json:"product_id"` Product string `json:"product_id"`
} }
type QueryCacheLoad struct {
Product string `json:"product_en"`
Params map[string]interface{} `json:"params"`
}

View File

@ -52,3 +52,9 @@ type BackgroundCheckReq struct {
Mobile string `json:"mobile" validate:"required,mobile"` Mobile string `json:"mobile" validate:"required,mobile"`
Code string `json:"code" validate:"required"` Code string `json:"code" validate:"required"`
} }
type EntLawsuitReq struct {
EntName string `json:"ent_name" validate:"required,name"`
EntCode string `json:"ent_code" validate:"required,USCI"`
Mobile string `json:"mobile" validate:"required,mobile"`
Code string `json:"code" validate:"required"`
}

View File

@ -66,14 +66,14 @@ type ProductResponse struct {
} }
type Query struct { type Query struct {
Id int64 `json:"id"` // 主键ID Id int64 `json:"id"` // 主键ID
OrderId int64 `json:"order_id"` // 订单ID OrderId int64 `json:"order_id"` // 订单ID
UserId int64 `json:"user_id"` // 用户ID UserId int64 `json:"user_id"` // 用户ID
ProductId int64 `json:"product_id"` // 产品ID ProductName string `json:"product_name"` // 产品ID
QueryData []map[string]interface{} `json:"query_data"` QueryData []map[string]interface{} `json:"query_data"`
CreateTime string `json:"create_time"` // 创建时间 CreateTime string `json:"create_time"` // 创建时间
UpdateTime string `json:"update_time"` // 更新时间 UpdateTime string `json:"update_time"` // 更新时间
QueryState string `json:"query_state"` // 查询状态 QueryState string `json:"query_state"` // 查询状态
} }
type QueryDetailByOrderIdReq struct { type QueryDetailByOrderIdReq struct {
@ -84,6 +84,14 @@ type QueryDetailByOrderIdResp struct {
Query Query
} }
type QueryDetailByOrderNoReq struct {
OrderNo string `path:"order_no"`
}
type QueryDetailByOrderNoResp struct {
Query
}
type QueryDetailReq struct { type QueryDetailReq struct {
Id int64 `path:"id"` Id int64 `path:"id"`
} }
@ -136,6 +144,15 @@ type QueryRetryReq struct {
type QueryRetryResp struct { type QueryRetryResp struct {
} }
type QueryServiceReq struct {
Product string `path:"product"`
Data string `json:"data" validate:"required"`
}
type QueryServiceResp struct {
Id string `json:"id"`
}
type RegisterReq struct { type RegisterReq struct {
Mobile string `json:"mobile" validate:"required,mobile"` Mobile string `json:"mobile" validate:"required,mobile"`
Password string `json:"password" validate:"required,min=11,max=11,password"` Password string `json:"password" validate:"required,min=11,max=11,password"`
@ -158,6 +175,16 @@ type UserInfoResp struct {
UserInfo User `json:"userInfo"` UserInfo User `json:"userInfo"`
} }
type WXH5AuthReq struct {
Code string `json:"code"`
}
type WXH5AuthResp struct {
AccessToken string `json:"accessToken"`
AccessExpire int64 `json:"accessExpire"`
RefreshAfter int64 `json:"refreshAfter"`
}
type WXMiniAuthReq struct { type WXMiniAuthReq struct {
Code string `json:"code"` Code string `json:"code"`
IV string `json:"iv"` IV string `json:"iv"`

View File

@ -27,9 +27,8 @@ var (
productRowsExpectAutoSet = strings.Join(stringx.Remove(productFieldNames, "`id`", "`create_time`", "`update_time`"), ",") productRowsExpectAutoSet = strings.Join(stringx.Remove(productFieldNames, "`id`", "`create_time`", "`update_time`"), ",")
productRowsWithPlaceHolder = strings.Join(stringx.Remove(productFieldNames, "`id`", "`create_time`", "`update_time`"), "=?,") + "=?" productRowsWithPlaceHolder = strings.Join(stringx.Remove(productFieldNames, "`id`", "`create_time`", "`update_time`"), "=?,") + "=?"
cacheQncProductIdPrefix = "cache:qnc:product:id:" cacheQncProductIdPrefix = "cache:qnc:product:id:"
cacheQncProductProductEnPrefix = "cache:qnc:product:productEn:" cacheQncProductProductEnPrefix = "cache:qnc:product:productEn:"
cacheQncProductProductNamePrefix = "cache:qnc:product:productName:"
) )
type ( type (
@ -37,7 +36,6 @@ type (
Insert(ctx context.Context, session sqlx.Session, data *Product) (sql.Result, error) Insert(ctx context.Context, session sqlx.Session, data *Product) (sql.Result, error)
FindOne(ctx context.Context, id int64) (*Product, error) FindOne(ctx context.Context, id int64) (*Product, error)
FindOneByProductEn(ctx context.Context, productEn string) (*Product, error) FindOneByProductEn(ctx context.Context, productEn string) (*Product, error)
FindOneByProductName(ctx context.Context, productName string) (*Product, error)
Update(ctx context.Context, session sqlx.Session, data *Product) (sql.Result, error) Update(ctx context.Context, session sqlx.Session, data *Product) (sql.Result, error)
UpdateWithVersion(ctx context.Context, session sqlx.Session, data *Product) error UpdateWithVersion(ctx context.Context, session sqlx.Session, data *Product) error
Trans(ctx context.Context, fn func(context context.Context, session sqlx.Session) error) error Trans(ctx context.Context, fn func(context context.Context, session sqlx.Session) error) error
@ -85,14 +83,13 @@ func (m *defaultProductModel) Insert(ctx context.Context, session sqlx.Session,
data.DelState = globalkey.DelStateNo data.DelState = globalkey.DelStateNo
qncProductIdKey := fmt.Sprintf("%s%v", cacheQncProductIdPrefix, data.Id) qncProductIdKey := fmt.Sprintf("%s%v", cacheQncProductIdPrefix, data.Id)
qncProductProductEnKey := fmt.Sprintf("%s%v", cacheQncProductProductEnPrefix, data.ProductEn) qncProductProductEnKey := fmt.Sprintf("%s%v", cacheQncProductProductEnPrefix, data.ProductEn)
qncProductProductNameKey := fmt.Sprintf("%s%v", cacheQncProductProductNamePrefix, data.ProductName)
return m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) { 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, productRowsExpectAutoSet) query := fmt.Sprintf("INSERT INTO %s (%s) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)", m.table, productRowsExpectAutoSet)
if session != nil { if session != nil {
return session.ExecCtx(ctx, query, data.DeleteTime, data.DelState, data.Version, data.ProductName, data.ProductEn, data.Description, data.Notes, data.CostPrice, data.SellPrice) return session.ExecCtx(ctx, query, data.DeleteTime, data.DelState, data.Version, data.ProductName, data.ProductEn, data.Description, data.Notes, data.CostPrice, data.SellPrice)
} }
return conn.ExecCtx(ctx, query, data.DeleteTime, data.DelState, data.Version, data.ProductName, data.ProductEn, data.Description, data.Notes, data.CostPrice, data.SellPrice) return conn.ExecCtx(ctx, query, data.DeleteTime, data.DelState, data.Version, data.ProductName, data.ProductEn, data.Description, data.Notes, data.CostPrice, data.SellPrice)
}, qncProductIdKey, qncProductProductEnKey, qncProductProductNameKey) }, qncProductIdKey, qncProductProductEnKey)
} }
func (m *defaultProductModel) FindOne(ctx context.Context, id int64) (*Product, error) { func (m *defaultProductModel) FindOne(ctx context.Context, id int64) (*Product, error) {
@ -132,26 +129,6 @@ func (m *defaultProductModel) FindOneByProductEn(ctx context.Context, productEn
} }
} }
func (m *defaultProductModel) FindOneByProductName(ctx context.Context, productName string) (*Product, error) {
qncProductProductNameKey := fmt.Sprintf("%s%v", cacheQncProductProductNamePrefix, productName)
var resp Product
err := m.QueryRowIndexCtx(ctx, &resp, qncProductProductNameKey, m.formatPrimary, func(ctx context.Context, conn sqlx.SqlConn, v interface{}) (i interface{}, e error) {
query := fmt.Sprintf("SELECT %s FROM %s WHERE `product_name` = ? AND del_state = ? limit 1", productRows, m.table)
if err := conn.QueryRowCtx(ctx, &resp, query, productName, 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, model.ErrNotFound
default:
return nil, err
}
}
func (m *defaultProductModel) Update(ctx context.Context, session sqlx.Session, newData *Product) (sql.Result, error) { func (m *defaultProductModel) Update(ctx context.Context, session sqlx.Session, newData *Product) (sql.Result, error) {
data, err := m.FindOne(ctx, newData.Id) data, err := m.FindOne(ctx, newData.Id)
if err != nil { if err != nil {
@ -159,14 +136,13 @@ func (m *defaultProductModel) Update(ctx context.Context, session sqlx.Session,
} }
qncProductIdKey := fmt.Sprintf("%s%v", cacheQncProductIdPrefix, data.Id) qncProductIdKey := fmt.Sprintf("%s%v", cacheQncProductIdPrefix, data.Id)
qncProductProductEnKey := fmt.Sprintf("%s%v", cacheQncProductProductEnPrefix, data.ProductEn) qncProductProductEnKey := fmt.Sprintf("%s%v", cacheQncProductProductEnPrefix, data.ProductEn)
qncProductProductNameKey := fmt.Sprintf("%s%v", cacheQncProductProductNamePrefix, data.ProductName)
return m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) { 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, productRowsWithPlaceHolder) query := fmt.Sprintf("UPDATE %s SET %s WHERE `id` = ?", m.table, productRowsWithPlaceHolder)
if session != nil { if session != nil {
return session.ExecCtx(ctx, query, newData.DeleteTime, newData.DelState, newData.Version, newData.ProductName, newData.ProductEn, newData.Description, newData.Notes, newData.CostPrice, newData.SellPrice, newData.Id) return session.ExecCtx(ctx, query, newData.DeleteTime, newData.DelState, newData.Version, newData.ProductName, newData.ProductEn, newData.Description, newData.Notes, newData.CostPrice, newData.SellPrice, newData.Id)
} }
return conn.ExecCtx(ctx, query, newData.DeleteTime, newData.DelState, newData.Version, newData.ProductName, newData.ProductEn, newData.Description, newData.Notes, newData.CostPrice, newData.SellPrice, newData.Id) return conn.ExecCtx(ctx, query, newData.DeleteTime, newData.DelState, newData.Version, newData.ProductName, newData.ProductEn, newData.Description, newData.Notes, newData.CostPrice, newData.SellPrice, newData.Id)
}, qncProductIdKey, qncProductProductEnKey, qncProductProductNameKey) }, qncProductIdKey, qncProductProductEnKey)
} }
func (m *defaultProductModel) UpdateWithVersion(ctx context.Context, session sqlx.Session, newData *Product) error { func (m *defaultProductModel) UpdateWithVersion(ctx context.Context, session sqlx.Session, newData *Product) error {
@ -183,14 +159,13 @@ func (m *defaultProductModel) UpdateWithVersion(ctx context.Context, session sql
} }
qncProductIdKey := fmt.Sprintf("%s%v", cacheQncProductIdPrefix, data.Id) qncProductIdKey := fmt.Sprintf("%s%v", cacheQncProductIdPrefix, data.Id)
qncProductProductEnKey := fmt.Sprintf("%s%v", cacheQncProductProductEnPrefix, data.ProductEn) qncProductProductEnKey := fmt.Sprintf("%s%v", cacheQncProductProductEnPrefix, data.ProductEn)
qncProductProductNameKey := fmt.Sprintf("%s%v", cacheQncProductProductNamePrefix, data.ProductName)
sqlResult, err = m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) { 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, productRowsWithPlaceHolder) query := fmt.Sprintf("UPDATE %s SET %s WHERE `id` = ? AND version = ? ", m.table, productRowsWithPlaceHolder)
if session != nil { if session != nil {
return session.ExecCtx(ctx, query, newData.DeleteTime, newData.DelState, newData.Version, newData.ProductName, newData.ProductEn, newData.Description, newData.Notes, newData.CostPrice, newData.SellPrice, newData.Id, oldVersion) return session.ExecCtx(ctx, query, newData.DeleteTime, newData.DelState, newData.Version, newData.ProductName, newData.ProductEn, newData.Description, newData.Notes, newData.CostPrice, newData.SellPrice, newData.Id, oldVersion)
} }
return conn.ExecCtx(ctx, query, newData.DeleteTime, newData.DelState, newData.Version, newData.ProductName, newData.ProductEn, newData.Description, newData.Notes, newData.CostPrice, newData.SellPrice, newData.Id, oldVersion) return conn.ExecCtx(ctx, query, newData.DeleteTime, newData.DelState, newData.Version, newData.ProductName, newData.ProductEn, newData.Description, newData.Notes, newData.CostPrice, newData.SellPrice, newData.Id, oldVersion)
}, qncProductIdKey, qncProductProductEnKey, qncProductProductNameKey) }, qncProductIdKey, qncProductProductEnKey)
if err != nil { if err != nil {
return err return err
} }
@ -415,14 +390,13 @@ func (m *defaultProductModel) Delete(ctx context.Context, session sqlx.Session,
qncProductIdKey := fmt.Sprintf("%s%v", cacheQncProductIdPrefix, id) qncProductIdKey := fmt.Sprintf("%s%v", cacheQncProductIdPrefix, id)
qncProductProductEnKey := fmt.Sprintf("%s%v", cacheQncProductProductEnPrefix, data.ProductEn) qncProductProductEnKey := fmt.Sprintf("%s%v", cacheQncProductProductEnPrefix, data.ProductEn)
qncProductProductNameKey := fmt.Sprintf("%s%v", cacheQncProductProductNamePrefix, data.ProductName)
_, err = m.ExecCtx(ctx, func(ctx context.Context, conn sqlx.SqlConn) (result sql.Result, err error) { _, 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) query := fmt.Sprintf("DELETE FROM %s WHERE `id` = ?", m.table)
if session != nil { if session != nil {
return session.ExecCtx(ctx, query, id) return session.ExecCtx(ctx, query, id)
} }
return conn.ExecCtx(ctx, query, id) return conn.ExecCtx(ctx, query, id)
}, qncProductIdKey, qncProductProductEnKey, qncProductProductNameKey) }, qncProductIdKey, qncProductProductEnKey)
return err return err
} }
func (m *defaultProductModel) formatPrimary(primary interface{}) string { func (m *defaultProductModel) formatPrimary(primary interface{}) string {

View File

@ -39,7 +39,7 @@ func HttpResult(r *http.Request, w http.ResponseWriter, resp interface{}, err er
logx.WithContext(r.Context()).Errorf("【API-ERR】 : %+v ", err) logx.WithContext(r.Context()).Errorf("【API-ERR】 : %+v ", err)
httpx.WriteJson(w, http.StatusBadRequest, Error(errcode, errmsg)) httpx.WriteJson(w, http.StatusOK, Error(errcode, errmsg))
} }
} }
@ -79,7 +79,7 @@ func AuthHttpResult(r *http.Request, w http.ResponseWriter, resp interface{}, er
// http 参数错误返回 // http 参数错误返回
func ParamErrorResult(r *http.Request, w http.ResponseWriter, err error) { func ParamErrorResult(r *http.Request, w http.ResponseWriter, err error) {
errMsg := fmt.Sprintf("%s,%s", xerr.MapErrMsg(xerr.REUQEST_PARAM_ERROR), err.Error()) errMsg := fmt.Sprintf("%s,%s", xerr.MapErrMsg(xerr.REUQEST_PARAM_ERROR), err.Error())
httpx.WriteJson(w, http.StatusBadRequest, Error(xerr.REUQEST_PARAM_ERROR, errMsg)) httpx.WriteJson(w, http.StatusOK, Error(xerr.REUQEST_PARAM_ERROR, errMsg))
} }
// http 参数校验失败返回 // http 参数校验失败返回

View File

@ -19,7 +19,6 @@ CREATE TABLE `product` (
`cost_price` DECIMAL(10, 2) NOT NULL DEFAULT '1.00' COMMENT '成本', `cost_price` DECIMAL(10, 2) NOT NULL DEFAULT '1.00' COMMENT '成本',
`sell_price` DECIMAL(10, 2) NOT NULL DEFAULT '1.00' COMMENT '售价', `sell_price` DECIMAL(10, 2) NOT NULL DEFAULT '1.00' COMMENT '售价',
PRIMARY KEY (`id`), PRIMARY KEY (`id`),
UNIQUE KEY `unique_product_name` (`product_name`),
UNIQUE KEY `unique_product_en` (`product_en`) UNIQUE KEY `unique_product_en` (`product_en`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='产品表'; ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='产品表';
@ -33,8 +32,26 @@ INSERT INTO `product` (`product_name`, `product_en`, `description`, `notes`, `co
('婚姻状态', 'marriagelogic', '', '', 1, 1), ('婚姻状态', 'marriagelogic', '', '', 1, 1),
('贷前背调', 'preloanbackgroundchecklogic', '', '', 1, 1), ('贷前背调', 'preloanbackgroundchecklogic', '', '', 1, 1),
('租赁服务', 'rentalinfologic', '', '', 1, 1), ('租赁服务', 'rentalinfologic', '', '', 1, 1),
('个人风险评估', 'riskassessmentlogic', '', '', 1, 1); ('个人风险评估', 'riskassessmentlogic', '', '', 1, 1),
('手机三要素', 'toc_PhoneThreeElements', '', '', 1, 1),
('银行卡黑名单', 'toc_BankCardBlacklist', '', '', 1, 1),
('身份证二要素', 'toc_IDCardTwoElements', '', '', 1, 1),
('手机二要素', 'toc_PhoneTwoElements', '', '', 1, 1),
('在网时长', 'toc_NetworkDuration', '', '', 1, 1),
('手机二次卡', 'toc_PhoneSecondaryCard', '', '', 1, 1),
('手机号码风险', 'toc_PhoneNumberRisk', '', '', 1, 1),
('银行卡四要素', 'toc_BankCardFourElements', '', '', 1, 1),
('银行卡三要素', 'toc_BankCardThreeElements', '', '', 1, 1),
('自然人生存状态', 'toc_NaturalLifeStatus', '', '', 1, 1),
('学历核验', 'toc_EducationVerification', '', '', 1, 1),
('人车核验', 'toc_PersonVehicleVerification', '', '', 1, 1),
('名下车辆', 'toc_VehiclesUnderName', '', '', 1, 1),
('双人婚姻', 'toc_DualMarriage', '', '', 1, 1),
('个人不良', 'toc_PersonalBadRecord', '', '', 1, 1),
('股东人企关系', 'toc_ShareholderBusinessRelation', '', '', 1, 1),
('个人涉诉', 'toc_PersonalLawsuit', '', '', 1, 1),
('企业涉诉', 'toc_EnterpriseLawsuit', '', '', 1, 1),
('婚姻评估', 'toc_MarriageAssessment', '', '', 1, 1);
SET FOREIGN_KEY_CHECKS = 1; SET FOREIGN_KEY_CHECKS = 1;
@ -50,7 +67,7 @@ CREATE TABLE `feature` (
`delete_time` datetime DEFAULT NULL COMMENT '删除时间', `delete_time` datetime DEFAULT NULL COMMENT '删除时间',
`del_state` tinyint NOT NULL DEFAULT '0' COMMENT '删除状态', `del_state` tinyint NOT NULL DEFAULT '0' COMMENT '删除状态',
`version` bigint NOT NULL DEFAULT '0' COMMENT '版本号', `version` bigint NOT NULL DEFAULT '0' COMMENT '版本号',
`api_id` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT 'API标识', `api_id` varchar kujmio,5(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT 'API标识',
`name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '描述', `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '描述',
PRIMARY KEY (`id`), PRIMARY KEY (`id`),
UNIQUE KEY `unique_api_id` (`api_id`) UNIQUE KEY `unique_api_id` (`api_id`)

View File

@ -13,7 +13,9 @@ var customMessages = map[string]string{
"IDCard.idCard": "无效的身份证号码", "IDCard.idCard": "无效的身份证号码",
"Password.min": "密码不能少于8位数", "Password.min": "密码不能少于8位数",
"Password.max": "密码不能超过32位数", "Password.max": "密码不能超过32位数",
"password.password": "密码强度太弱", "Password.password": "密码强度太弱",
//"EntCode.required":"请输入统一社会信用代码",
//"EntCode.USCI": "请输入正确的统一社会信用代码",
} }
// 获取自定义错误消息 // 获取自定义错误消息

View File

@ -1 +0,0 @@
exit status 1