Files
tyc-server-v2/app/main/api/internal/logic/query/queryservicelogic.go
2026-03-02 16:51:05 +08:00

898 lines
39 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package query
import (
"context"
"database/sql"
"encoding/hex"
"encoding/json"
"fmt"
"os"
"time"
"tyc-server/app/main/api/internal/service"
"tyc-server/app/main/model"
"tyc-server/common/ctxdata"
"tyc-server/common/globalkey"
"tyc-server/common/xerr"
"tyc-server/pkg/captcha"
"tyc-server/pkg/lzkit/crypto"
"tyc-server/pkg/lzkit/validator"
"github.com/pkg/errors"
"github.com/zeromicro/go-zero/core/stores/redis"
"tyc-server/app/main/api/internal/svc"
"tyc-server/app/main/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) {
if req.AgentIdentifier != "" {
l.ctx = context.WithValue(l.ctx, "agentIdentifier", req.AgentIdentifier)
} else if req.App {
l.ctx = context.WithValue(l.ctx, "app", req.App)
}
return l.PreprocessLogic(req, req.Product)
}
// queryHandlerFunc 通用查询 handler解密后的数据 + 产品名 -> 校验并返回待缓存的 params
// 新增产品时只需在 productHandlers 里加一行并选用已有 handler 类型即可,无需再写 ProcessXxx
type queryHandlerFunc func(l *QueryServiceLogic, decryptData []byte, product string) (map[string]interface{}, error)
var productHandlers = map[string]queryHandlerFunc{
"marriage": runMarriageReq,
"homeservice": runMarriageReq,
"riskassessment": runMarriageReq,
"companyinfo": runMarriageReq,
"rentalinfo": runMarriageReq,
"preloanbackgroundcheck": runMarriageReq,
"backgroundcheck": runMarriageReq,
"personalData": runMarriageReq,
"toc_PersonalBadRecord": runPersonalBadRecordReq,
"toc_PersonalLawsuit": runMarriageReq,
"toc_EnterpriseLawsuit": runEntLawsuitReq,
// 人企关系加强版:仅身份证号
"toc_PersonEnterprisePro": runPersonEnterpriseProReq,
// 新司法涉诉类产品
"toc_EnterpriseLawsuitQYGL66SL": runEnterpriseLawsuitSimpleReq,
"toc_LimitHighExecuted": runLimitHighExecutedReq,
"toc_DishonestExecutedPerson": runDishonestExecutedReq,
"toc_Marriage": runMarriageReq,
"toc_PersonalMarriageStatus": runMarriageReq,
"toc_MarriageStatusRegisterTime": runMarriageReq,
"toc_MarriageStatusSupplement": runMarriageReq,
"toc_MarriageStatusVerify": runMarriageReq,
"toc_DualMarriageStatusRegisterTime": runDualMarriageReq,
"toc_VehiclesUnderName": runMarriageReq,
"toc_VehiclesUnderNamePlate": runMarriageReq,
"toc_PersonVehicleVerification": runPersonVehicleVerificationReq,
"toc_PersonVehicleVerificationDetail": runPersonVehicleVerificationReq,
// 车辆类产品(按 md 传参)
"toc_VehiclesUnderNameCount": runVehiclesUnderNameCountReq,
"toc_VehicleStaticInfo": runVehicleVinCodeReq,
"toc_VehicleMileageMixed": runVehicleMileageMixedReq,
"toc_VehicleVinValuation": runVehicleVinValuationReq,
"toc_VehicleTransferSimple": runVehicleTransferSimpleReq,
"toc_VehicleTransferDetail": runVehicleVinCodeReq,
"toc_VehicleMaintenanceSimple": runVehicleMaintenanceSimpleReq,
"toc_VehicleMaintenanceDetail": runVehicleMaintenanceDetailReq,
"toc_VehicleClaimDetail": runVehicleClaimDetailReq,
"toc_VehicleClaimVerify": runVehicleClaimVerifyReq,
// 核验工具verify feature.md
"toc_PoliceTwoFactors": runVerifyAuthTwoReq,
"toc_PoliceThreeFactors": runVerifyAuthThreeReq,
"toc_ProfessionalCertificate": runVerifyCertReq,
"toc_PersonalConsumptionCapacityLevel": runVerifyConsumptionReq, // 个人消费能力(沿用现有 product_en
"toc_OperatorTwoFactors": runVerifyYysTwoReq,
"toc_MobileThreeFactors": runVerifyYysThreeReq,
"toc_NumberRecycle": runVerifyMobileOnlyReq,
"toc_MobileEmptyCheck": runVerifyMobileOnlyReq,
"toc_MobilePortability": runVerifyMobileOnlyReq,
"toc_MobileOnlineStatus": runVerifyMobileOnlyReq,
"toc_MobileOnlineDuration": runVerifyMobileOnlyReq,
"toc_MobileAttribution": runVerifyMobileOnlyReq,
"toc_MobileConsumptionRange": runVerifyYysConsumptionReq,
"toc_EnterpriseRelation": runVerifyEntRelationReq,
"toc_BankcardFourFactors": runVerifyBankFourReq,
"toc_BankcardBlacklist": runVerifyBankBlackReq,
}
// productHasSmsCode 表示该 product 解密后的请求结构体中是否包含必填短信验证码 Code。
// 有 Code 的产品在「获取验证码」时已经做了滑块,这里不再强制要求 CaptchaVerifyParam。
// 其他产品(无 Code在查询时必须传并校验 CaptchaVerifyParam防止跳过图形验证。
func productHasSmsCode(product string) bool {
switch product {
case "marriage",
"homeservice",
"riskassessment",
"companyinfo",
"rentalinfo",
"preloanbackgroundcheck",
"backgroundcheck",
"personalData",
"toc_PersonalLawsuit",
"toc_EnterpriseLawsuit",
"toc_Marriage",
"toc_PersonalMarriageStatus",
"toc_MarriageStatusRegisterTime",
"toc_MarriageStatusSupplement",
"toc_MarriageStatusVerify",
"toc_DualMarriageStatusRegisterTime",
"toc_VehiclesUnderName",
"toc_VehiclesUnderNamePlate":
return true
default:
return false
}
}
func (l *QueryServiceLogic) PreprocessLogic(req *types.QueryServiceReq, product string) (*types.QueryServiceResp, error) {
// 无短信验证码 Code 的 product查询前必须传并校验滑块否则不允许跳过
if !productHasSmsCode(product) {
if req.CaptchaVerifyParam == "" {
return nil, errors.Wrapf(xerr.NewErrMsg("请完成图形验证"), "product %s requires captcha", product)
}
cfg := l.svcCtx.Config.Captcha
if err := captcha.Verify(captcha.Config{
AccessKeyID: cfg.AccessKeyID,
AccessKeySecret: cfg.AccessKeySecret,
EndpointURL: cfg.EndpointURL,
SceneID: cfg.SceneID,
}, req.CaptchaVerifyParam); err != nil {
return nil, err
}
}
decryptData, err := l.DecryptData(req.Data)
if err != nil {
return nil, err
}
handler, exists := productHandlers[product]
if !exists {
return nil, errors.New("未找到相应的处理程序")
}
params, err := handler(l, decryptData, product)
if err != nil {
return nil, err
}
return l.commonQueryTail(params, product)
}
// commonQueryTail 通用收尾:写缓存、生成 token 并返回
func (l *QueryServiceLogic) commonQueryTail(params map[string]interface{}, product string) (*types.QueryServiceResp, error) {
userID, err := l.GetOrCreateUser()
if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "查询服务, 处理用户失败: %v", err)
}
cacheNo, cacheDataErr := l.CacheData(params, product, userID)
if cacheDataErr != nil {
return nil, cacheDataErr
}
token, err := l.svcCtx.UserService.GeneralUserToken(l.ctx, userID, model.UserTypeNormal)
if err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "查询服务, 生成token失败 : %d", userID)
}
now := time.Now().Unix()
return &types.QueryServiceResp{
Id: cacheNo,
AccessToken: token,
AccessExpire: now + l.svcCtx.Config.JwtAuth.AccessExpire,
RefreshAfter: now + l.svcCtx.Config.JwtAuth.RefreshAfter,
}, nil
}
// runMarriageReq 姓名+身份证+手机+验证码 类产品(婚恋、家政、司法涉诉、婚姻状况、名下车辆等)
func runMarriageReq(l *QueryServiceLogic, decryptData []byte, product string) (map[string]interface{}, error) {
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)
}
if verifyCodeErr := l.VerifyCode(data.Mobile, data.Code); verifyCodeErr != nil {
return nil, verifyCodeErr
}
if verifyErr := l.Verify(data.Name, data.IDCard, data.Mobile); verifyErr != nil {
return nil, verifyErr
}
return map[string]interface{}{
"name": data.Name,
"id_card": data.IDCard,
"mobile": data.Mobile,
}, nil
}
// runEntLawsuitReq 企业司法涉诉:企业名称+统一社会信用代码+手机+验证码
func runEntLawsuitReq(l *QueryServiceLogic, decryptData []byte, product string) (map[string]interface{}, error) {
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)
}
if verifyCodeErr := l.VerifyCode(data.Mobile, data.Code); verifyCodeErr != nil {
return nil, verifyCodeErr
}
return map[string]interface{}{
"ent_name": data.EntName,
"ent_code": data.EntCode,
"mobile": data.Mobile,
}, nil
}
// 企业司法涉诉简版 QYGL66SL仅企业名称auth_date 与授权文件编码由后端自动生成
func runEnterpriseLawsuitSimpleReq(l *QueryServiceLogic, decryptData []byte, product string) (map[string]interface{}, error) {
var data types.EnterpriseLawsuitSimpleReq
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)
}
now := time.Now()
start := now.AddDate(0, 0, -7)
end := now.AddDate(0, 0, 7)
authDate := fmt.Sprintf("%s-%s", start.Format("20060102"), end.Format("20060102"))
return map[string]interface{}{
"ent_name": data.EntName,
"auth_date": authDate,
"auth_authorize_file_code": "AUTHTYC0001",
}, nil
}
// 限高被执行人 FLXG3A9B
func runLimitHighExecutedReq(l *QueryServiceLogic, decryptData []byte, product string) (map[string]interface{}, error) {
var data types.LimitHighExecutedReq
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)
}
auth := data.Authorized
if auth == "" {
auth = "1"
}
return map[string]interface{}{
"name": data.Name,
"id_card": data.IDCard,
"mobile_no": data.Mobile,
"authorized": auth,
}, nil
}
// 本人不良 FLXGDEA9姓名 + 身份证(授权由 ApiRequest 默认传 1
func runPersonalBadRecordReq(l *QueryServiceLogic, decryptData []byte, product string) (map[string]interface{}, error) {
var data types.PersonalBadRecordReq
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)
}
return map[string]interface{}{
"name": data.Name,
"id_card": data.IDCard,
}, nil
}
// 失信被执行人 QYGL2S0W
func runDishonestExecutedReq(l *QueryServiceLogic, decryptData []byte, product string) (map[string]interface{}, error) {
var data types.DishonestExecutedReq
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)
}
tp := data.Type
if tp == "" {
tp = "per"
}
return map[string]interface{}{
"type": tp,
"name": data.Name,
"id_card": data.IDCard,
}, nil
}
// runDualMarriageReq 双人婚姻状态:男方/女方姓名+身份证+手机+验证码
func runDualMarriageReq(l *QueryServiceLogic, decryptData []byte, product string) (map[string]interface{}, error) {
var data types.TocDualMarriageReq
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)
}
if verifyCodeErr := l.VerifyCode(data.Mobile, data.Code); verifyCodeErr != nil {
return nil, verifyCodeErr
}
if verifyErr := l.VerifyTwo(data.NameMan, data.IDCardMan); verifyErr != nil {
return nil, verifyErr
}
if verifyErr := l.VerifyTwo(data.NameWoman, data.IDCardWoman); verifyErr != nil {
return nil, verifyErr
}
return map[string]interface{}{
"name": data.NameMan,
"id_card": data.IDCardMan,
"mobile": data.Mobile,
"name_man": data.NameMan,
"id_card_man": data.IDCardMan,
"name_woman": data.NameWoman,
"id_card_woman": data.IDCardWoman,
}, nil
}
// runPersonVehicleVerificationReq 人车核验简版:姓名+号牌类型+车牌号
func runPersonVehicleVerificationReq(l *QueryServiceLogic, decryptData []byte, product string) (map[string]interface{}, error) {
var data types.TocPersonVehicleVerification
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)
}
return map[string]interface{}{
"name": data.Name,
"plate_no": data.CarLicense,
"carplate_type": data.CarType,
}, nil
}
// runVehiclesUnderNameCountReq 名下车辆(数量) QCXG4D2E仅 user_type + id_card
func runVehiclesUnderNameCountReq(l *QueryServiceLogic, decryptData []byte, product string) (map[string]interface{}, error) {
var data types.TocVehiclesUnderNameCountReq
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)
}
userType := data.UserType
if userType == "" {
userType = "1"
}
return map[string]interface{}{
"user_type": userType,
"id_card": data.IDCard,
}, nil
}
// runVehicleVinCodeReq 仅 vin_code车辆静态信息、过户详版等
func runVehicleVinCodeReq(l *QueryServiceLogic, decryptData []byte, product string) (map[string]interface{}, error) {
var data types.TocVehicleVinCodeReq
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)
}
if data.Mobile != "" && data.Code != "" {
if verifyCodeErr := l.VerifyCode(data.Mobile, data.Code); verifyCodeErr != nil {
return nil, verifyCodeErr
}
}
return map[string]interface{}{
"vin_code": data.VinCode,
}, nil
}
// runVehicleMileageMixedReq 车辆里程记录(混合) QCXG1U4U
func runVehicleMileageMixedReq(l *QueryServiceLogic, decryptData []byte, product string) (map[string]interface{}, error) {
var data types.TocVehicleMileageMixedReq
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)
}
if data.Mobile != "" && data.Code != "" {
if verifyCodeErr := l.VerifyCode(data.Mobile, data.Code); verifyCodeErr != nil {
return nil, verifyCodeErr
}
}
// 回调地址由后端在 ApiRequestService 中统一生成,此处不再下发 return_url
return map[string]interface{}{
"vin_code": data.VinCode,
"image_url": data.ImageURL,
}, nil
}
// runVehicleVinValuationReq 二手车VIN估值 QCXGY7F2仅必填
func runVehicleVinValuationReq(l *QueryServiceLogic, decryptData []byte, product string) (map[string]interface{}, error) {
var data types.TocVehicleVinValuationReq
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)
}
if data.Mobile != "" && data.Code != "" {
if verifyCodeErr := l.VerifyCode(data.Mobile, data.Code); verifyCodeErr != nil {
return nil, verifyCodeErr
}
}
return map[string]interface{}{
"vin_code": data.VinCode,
"vehicle_location": data.VehicleLocation,
"first_registrationdate": data.FirstRegistrationDate,
}, nil
}
// runVehicleTransferSimpleReq 车辆过户简版 QCXG1H7Y仅必填 vin_code
func runVehicleTransferSimpleReq(l *QueryServiceLogic, decryptData []byte, product string) (map[string]interface{}, error) {
var data types.TocVehicleTransferSimpleReq
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)
}
if data.Mobile != "" && data.Code != "" {
if verifyCodeErr := l.VerifyCode(data.Mobile, data.Code); verifyCodeErr != nil {
return nil, verifyCodeErr
}
}
return map[string]interface{}{"vin_code": data.VinCode}, nil
}
// runVehicleMaintenanceSimpleReq 车辆维保简版 QCXG3Y6B仅必填 vin_code回调地址后端自动生成
func runVehicleMaintenanceSimpleReq(l *QueryServiceLogic, decryptData []byte, product string) (map[string]interface{}, error) {
var data types.TocVehicleMaintenanceSimpleReq
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)
}
if data.Mobile != "" && data.Code != "" {
if verifyCodeErr := l.VerifyCode(data.Mobile, data.Code); verifyCodeErr != nil {
return nil, verifyCodeErr
}
}
// 回调地址由后端在 ApiRequestService 中统一生成,此处不再下发 return_url
return map[string]interface{}{
"vin_code": data.VinCode,
}, nil
}
// runVehicleMaintenanceDetailReq 车辆维保详细版 QCXG3Z3L仅必填 vin_code回调地址后端自动生成
func runVehicleMaintenanceDetailReq(l *QueryServiceLogic, decryptData []byte, product string) (map[string]interface{}, error) {
var data types.TocVehicleMaintenanceDetailReq
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)
}
if data.Mobile != "" && data.Code != "" {
if verifyCodeErr := l.VerifyCode(data.Mobile, data.Code); verifyCodeErr != nil {
return nil, verifyCodeErr
}
}
// 回调地址由后端在 ApiRequestService 中统一生成,此处不再下发 return_url
return map[string]interface{}{
"vin_code": data.VinCode,
}, nil
}
// runVehicleClaimDetailReq 车辆出险详版 QCXGP00W仅必填 vin_code, vlphoto_data回调地址后端自动生成vlphoto_data 由 API 层加密为 data
func runVehicleClaimDetailReq(l *QueryServiceLogic, decryptData []byte, product string) (map[string]interface{}, error) {
var data types.TocVehicleClaimDetailReq
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)
}
if data.Mobile != "" && data.Code != "" {
if verifyCodeErr := l.VerifyCode(data.Mobile, data.Code); verifyCodeErr != nil {
return nil, verifyCodeErr
}
}
// 回调地址由后端在 ApiRequestService 中统一生成,此处不再下发 return_url
return map[string]interface{}{
"vin_code": data.VinCode,
"vlphoto_data": data.VlphotoData,
}, nil
}
// runVehicleClaimVerifyReq 车辆出险记录核验 QCXG6B4E
func runVehicleClaimVerifyReq(l *QueryServiceLogic, decryptData []byte, product string) (map[string]interface{}, error) {
var data types.TocVehicleClaimVerifyReq
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)
}
if data.Mobile != "" && data.Code != "" {
if verifyCodeErr := l.VerifyCode(data.Mobile, data.Code); verifyCodeErr != nil {
return nil, verifyCodeErr
}
}
auth := data.Authorized
if auth == "" {
auth = "1"
}
return map[string]interface{}{
"vin_code": data.VINCode,
"authorized": auth,
}, nil
}
// runPersonEnterpriseProReq 人企关系加强版预查询:仅身份证号
func runPersonEnterpriseProReq(l *QueryServiceLogic, decryptData []byte, product string) (map[string]interface{}, error) {
var data types.TocPersonEnterpriseProReq
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)
}
return map[string]interface{}{
"id_card": data.IDCard,
}, nil
}
// --------------- 核验工具 handlers ---------------
func runVerifyAuthTwoReq(l *QueryServiceLogic, decryptData []byte, product string) (map[string]interface{}, error) {
var data types.TocVerifyAuthTwoReq
if err := json.Unmarshal(decryptData, &data); err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "查询服务, 解密后的数据格式不正确: %+v", err)
}
if err := validator.Validate(data); err != nil {
return nil, errors.Wrapf(xerr.NewErrCodeMsg(xerr.PARAM_VERIFICATION_ERROR, err.Error()), "查询服务, 参数不正确: %+v", err)
}
return map[string]interface{}{"mobile_no": data.MobileNo, "id_card": data.IDCard, "name": data.Name}, nil
}
func runVerifyAuthThreeReq(l *QueryServiceLogic, decryptData []byte, product string) (map[string]interface{}, error) {
var data types.TocVerifyAuthThreeReq
if err := json.Unmarshal(decryptData, &data); err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "查询服务, 解密后的数据格式不正确: %+v", err)
}
if err := validator.Validate(data); err != nil {
return nil, errors.Wrapf(xerr.NewErrCodeMsg(xerr.PARAM_VERIFICATION_ERROR, err.Error()), "查询服务, 参数不正确: %+v", err)
}
return map[string]interface{}{"photo_data": data.PhotoData, "id_card": data.IDCard, "name": data.Name}, nil
}
func runVerifyCertReq(l *QueryServiceLogic, decryptData []byte, product string) (map[string]interface{}, error) {
var data types.TocVerifyCertReq
if err := json.Unmarshal(decryptData, &data); err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "查询服务, 解密后的数据格式不正确: %+v", err)
}
if err := validator.Validate(data); err != nil {
return nil, errors.Wrapf(xerr.NewErrCodeMsg(xerr.PARAM_VERIFICATION_ERROR, err.Error()), "查询服务, 参数不正确: %+v", err)
}
return map[string]interface{}{"id_card": data.IDCard, "name": data.Name}, nil
}
func runVerifyConsumptionReq(l *QueryServiceLogic, decryptData []byte, product string) (map[string]interface{}, error) {
var data types.TocVerifyConsumptionReq
if err := json.Unmarshal(decryptData, &data); err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "查询服务, 解密后的数据格式不正确: %+v", err)
}
if err := validator.Validate(data); err != nil {
return nil, errors.Wrapf(xerr.NewErrCodeMsg(xerr.PARAM_VERIFICATION_ERROR, err.Error()), "查询服务, 参数不正确: %+v", err)
}
return map[string]interface{}{"mobile_no": data.MobileNo, "id_card": data.IDCard, "name": data.Name}, nil
}
func runVerifyYysTwoReq(l *QueryServiceLogic, decryptData []byte, product string) (map[string]interface{}, error) {
var data types.TocVerifyYysTwoReq
if err := json.Unmarshal(decryptData, &data); err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "查询服务, 解密后的数据格式不正确: %+v", err)
}
if err := validator.Validate(data); err != nil {
return nil, errors.Wrapf(xerr.NewErrCodeMsg(xerr.PARAM_VERIFICATION_ERROR, err.Error()), "查询服务, 参数不正确: %+v", err)
}
return map[string]interface{}{"mobile_no": data.MobileNo, "name": data.Name}, nil
}
func runVerifyYysThreeReq(l *QueryServiceLogic, decryptData []byte, product string) (map[string]interface{}, error) {
var data types.TocVerifyYysThreeReq
if err := json.Unmarshal(decryptData, &data); err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "查询服务, 解密后的数据格式不正确: %+v", err)
}
if err := validator.Validate(data); err != nil {
return nil, errors.Wrapf(xerr.NewErrCodeMsg(xerr.PARAM_VERIFICATION_ERROR, err.Error()), "查询服务, 参数不正确: %+v", err)
}
return map[string]interface{}{"mobile_no": data.MobileNo, "id_card": data.IDCard, "name": data.Name}, nil
}
func runVerifyMobileOnlyReq(l *QueryServiceLogic, decryptData []byte, product string) (map[string]interface{}, error) {
var data types.TocVerifyMobileOnlyReq
if err := json.Unmarshal(decryptData, &data); err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "查询服务, 解密后的数据格式不正确: %+v", err)
}
if err := validator.Validate(data); err != nil {
return nil, errors.Wrapf(xerr.NewErrCodeMsg(xerr.PARAM_VERIFICATION_ERROR, err.Error()), "查询服务, 参数不正确: %+v", err)
}
return map[string]interface{}{"mobile_no": data.MobileNo}, nil
}
func runVerifyYysConsumptionReq(l *QueryServiceLogic, decryptData []byte, product string) (map[string]interface{}, error) {
var data types.TocVerifyYysConsumptionReq
if err := json.Unmarshal(decryptData, &data); err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "查询服务, 解密后的数据格式不正确: %+v", err)
}
if err := validator.Validate(data); err != nil {
return nil, errors.Wrapf(xerr.NewErrCodeMsg(xerr.PARAM_VERIFICATION_ERROR, err.Error()), "查询服务, 参数不正确: %+v", err)
}
return map[string]interface{}{"mobile_no": data.MobileNo, "authorized": data.Authorized}, nil
}
func runVerifyEntRelationReq(l *QueryServiceLogic, decryptData []byte, product string) (map[string]interface{}, error) {
var data types.TocVerifyEntRelationReq
if err := json.Unmarshal(decryptData, &data); err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "查询服务, 解密后的数据格式不正确: %+v", err)
}
out := map[string]interface{}{}
if data.IDCard != "" {
out["id_card"] = data.IDCard
}
return out, nil
}
func runVerifyBankFourReq(l *QueryServiceLogic, decryptData []byte, product string) (map[string]interface{}, error) {
var data types.TocVerifyBankFourReq
if err := json.Unmarshal(decryptData, &data); err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "查询服务, 解密后的数据格式不正确: %+v", err)
}
if err := validator.Validate(data); err != nil {
return nil, errors.Wrapf(xerr.NewErrCodeMsg(xerr.PARAM_VERIFICATION_ERROR, err.Error()), "查询服务, 参数不正确: %+v", err)
}
return map[string]interface{}{
"mobile_no": data.MobileNo,
"id_card": data.IDCard,
"bank_card": data.BankCard,
"name": data.Name,
}, nil
}
func runVerifyBankBlackReq(l *QueryServiceLogic, decryptData []byte, product string) (map[string]interface{}, error) {
var data types.TocVerifyBankBlackReq
if err := json.Unmarshal(decryptData, &data); err != nil {
return nil, errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "查询服务, 解密后的数据格式不正确: %+v", err)
}
if err := validator.Validate(data); err != nil {
return nil, errors.Wrapf(xerr.NewErrCodeMsg(xerr.PARAM_VERIFICATION_ERROR, err.Error()), "查询服务, 参数不正确: %+v", err)
}
return map[string]interface{}{
"mobile_no": data.MobileNo,
"id_card": data.IDCard,
"name": data.Name,
"bank_card": data.BankCard,
}, 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
}
// 校验验证码(开发环境 ENV=development 可跳过)
func (l *QueryServiceLogic) VerifyCode(mobile string, code string) error {
if os.Getenv("ENV") == "development" {
return nil
}
secretKey := l.svcCtx.Config.Encrypt.SecretKey
encryptedMobile, err := crypto.EncryptMobile(mobile, secretKey)
if err != nil {
return errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "加密手机号失败: %+v", err)
}
codeRedisKey := fmt.Sprintf("%s:%s", "query", encryptedMobile)
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) IsAgentQuery() bool {
agentID, _ := l.ctx.Value("agentIdentifier").(string)
return agentID != ""
}
// 二要素验证(仅姓名+身份证号)(开发环境不调用验证 API
func (l *QueryServiceLogic) VerifyTwo(Name string, IDCard string) error {
if os.Getenv("ENV") == "development" {
return nil
}
twoVerification := service.TwoFactorVerificationRequest{
Name: Name,
IDCard: 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
}
// 按代理/非代理切换要素验证:代理走三要素;非代理走二要素(开发环境不调用验证 API
func (l *QueryServiceLogic) Verify(Name string, IDCard string, Mobile string) error {
if os.Getenv("ENV") == "development" {
return nil
}
if !l.IsAgentQuery() {
twoVerification := service.TwoFactorVerificationRequest{
Name: Name,
IDCard: 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)
}
} else {
// 三要素验证
if Mobile == "" {
return errors.Wrapf(xerr.NewErrCodeMsg(xerr.PARAM_VERIFICATION_ERROR, "手机号不能为空"), "三要素验证参数不正确: mobile为空")
}
threeVerification := service.ThreeFactorVerificationRequest{
Name: Name,
IDCard: IDCard,
Mobile: 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)
}
}
return nil
}
// 缓存
func (l *QueryServiceLogic) CacheData(params map[string]interface{}, Product string, userID int64) (string, error) {
agentIdentifier, _ := l.ctx.Value("agentIdentifier").(string)
secretKey := l.svcCtx.Config.Encrypt.SecretKey
key, decodeErr := hex.DecodeString(secretKey)
if decodeErr != nil {
return "", errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "查询服务, 获取AES密钥失败: %+v", decodeErr)
}
paramsMarshal, marshalErr := json.Marshal(params)
if marshalErr != nil {
return "", errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "查询服务, 序列化参数失败: %+v", marshalErr)
}
encryptParams, aesEncryptErr := crypto.AesEncrypt(paramsMarshal, key)
if aesEncryptErr != nil {
return "", errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "查询服务, 加密参数失败: %+v", aesEncryptErr)
}
queryCache := types.QueryCacheLoad{
Params: encryptParams,
Product: Product,
AgentIdentifier: agentIdentifier,
}
jsonData, marshalErr := json.Marshal(queryCache)
if marshalErr != nil {
return "", errors.Wrapf(xerr.NewErrCode(xerr.SERVER_COMMON_ERROR), "查询服务, 序列化参数失败: %+v", marshalErr)
}
outTradeNo := "Q_" + l.svcCtx.AlipayService.GenerateOutTradeNo()
redisKey := fmt.Sprintf(types.QueryCacheKey, userID, outTradeNo)
cacheErr := l.svcCtx.Redis.SetexCtx(l.ctx, redisKey, string(jsonData), int(2*time.Hour))
if cacheErr != nil {
return "", cacheErr
}
// 写入 query_user_record用于后台按被查询人姓名/身份证/手机号追溯订单(见 query_user_record.sql 说明 1
nameStr, _ := params["name"].(string)
idCardStr, _ := params["id_card"].(string)
mobileStr, _ := params["mobile"].(string)
if nameStr != "" || idCardStr != "" || mobileStr != "" {
var encName, encIdCard, encMobile string
if nameStr != "" {
encName, _ = crypto.AesEcbEncrypt([]byte(nameStr), key)
}
if idCardStr != "" {
encIdCard, _ = crypto.EncryptIDCard(idCardStr, key)
}
if mobileStr != "" {
encMobile, _ = crypto.EncryptMobile(mobileStr, secretKey)
}
agentIdent := sql.NullString{}
if agentIdentifier != "" {
agentIdent = sql.NullString{String: agentIdentifier, Valid: true}
}
rec := &model.QueryUserRecord{
DeleteTime: sql.NullTime{},
DelState: globalkey.DelStateNo,
Version: 0,
UserId: userID,
Name: encName,
IdCard: encIdCard,
Mobile: encMobile,
Product: Product,
QueryNo: outTradeNo,
OrderId: 0,
PlatformOrderId: sql.NullString{},
AgentIdentifier: agentIdent,
}
_, insertErr := l.svcCtx.QueryUserRecordModel.Insert(l.ctx, nil, rec)
if insertErr != nil {
logx.WithContext(l.ctx).Errorf("CacheData 写入 query_user_record 失败: %v", insertErr)
}
}
return outTradeNo, nil
}
// GetOrCreateUser 获取或创建用户
// 1. 如果上下文中已有用户ID直接返回
// 2. 如果是代理查询或APP请求创建新用户
// 3. 其他情况返回未登录错误
func (l *QueryServiceLogic) GetOrCreateUser() (int64, error) {
// 尝试获取用户ID
claims, err := ctxdata.GetClaimsFromCtx(l.ctx)
if err != nil {
return 0, err
}
userID := claims.UserId
return userID, nil
// // 如果不是未登录错误,说明是其他错误,直接返回
// if !ctxdata.IsNoUserIdError(err) {
// return 0, err
// }
// // 检查是否是代理查询或APP请求
// isAgentQuery := false
// if agentID, ok := l.ctx.Value("agentIdentifier").(string); ok && agentID != "" {
// isAgentQuery = true
// }
// if app, ok := l.ctx.Value("app").(bool); ok && app {
// isAgentQuery = true
// }
// // 如果不是代理查询或APP请求返回未登录错误
// if !isAgentQuery {
// return 0, ctxdata.ErrNoUserIdInCtx
// }
// // 创建新用户
// return l.svcCtx.UserService.RegisterUUIDUser(l.ctx)
}