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_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 } // 失信被执行人 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) }