From bdb2e78e10f1c80b13409454487b9147f030c802 Mon Sep 17 00:00:00 2001 From: liangzai <2440983361@qq.com> Date: Sun, 5 Jul 2026 00:48:32 +0800 Subject: [PATCH 1/4] add QCXG7K2N --- internal/domains/api/dto/api_request_dto.go | 4 ++ .../api/services/api_request_service.go | 1 + .../api/services/form_config_service.go | 1 + .../processors/qcxg/qcxg7k2n_processor.go | 38 +++++++++++++++++++ 4 files changed, 44 insertions(+) create mode 100644 internal/domains/api/services/processors/qcxg/qcxg7k2n_processor.go diff --git a/internal/domains/api/dto/api_request_dto.go b/internal/domains/api/dto/api_request_dto.go index ea16585..4ef0685 100644 --- a/internal/domains/api/dto/api_request_dto.go +++ b/internal/domains/api/dto/api_request_dto.go @@ -138,6 +138,10 @@ type QCXGX2X6Req struct { VehicleType string `json:"vehicle_type" validate:"omitempty"` Name string `json:"name" validate:"required,min=1,validName"` } +type QCXG7K2NReq struct { + PlateNo string `json:"plate_no" validate:"required"` + Name string `json:"name" validate:"required,min=1,validName"` +} type QCXG1S2LReq struct { VinCode string `json:"vin_code" validate:"required"` } diff --git a/internal/domains/api/services/api_request_service.go b/internal/domains/api/services/api_request_service.go index 30b12c1..5d72952 100644 --- a/internal/domains/api/services/api_request_service.go +++ b/internal/domains/api/services/api_request_service.go @@ -253,6 +253,7 @@ func registerAllProcessors(combService *comb.CombService) { "QCXG521L": qcxg.ProcessQCXG521LRequest, // 车辆静态信息查询 10479 "QCXGIJY3": qcxg.ProcessQCXGIJY3Request, // 名下车辆诺尔 "QCXG6U5G": qcxg.ProcessQCXG6U5GRequest, // 车辆核验 + "QCXG7K2N": qcxg.ProcessQCXG7K2NRequest, // 人车核验加强版 // DWBG系列处理器 - 多维报告 diff --git a/internal/domains/api/services/form_config_service.go b/internal/domains/api/services/form_config_service.go index ce7eb57..bd31532 100644 --- a/internal/domains/api/services/form_config_service.go +++ b/internal/domains/api/services/form_config_service.go @@ -311,6 +311,7 @@ func (s *FormConfigServiceImpl) getDTOStruct(ctx context.Context, apiCode string "JRZQFC59": &dto.JRZQFC59Req{}, //房产核验 "IVYZX7J9": &dto.IVYZX7J9Req{}, //学籍核验 "QCXG6U5G": &dto.QCXG6U5GReq{}, //车辆核验 + "QCXG7K2N": &dto.QCXG7K2NReq{}, //人车核验加强版 } // 优先返回已配置的DTO diff --git a/internal/domains/api/services/processors/qcxg/qcxg7k2n_processor.go b/internal/domains/api/services/processors/qcxg/qcxg7k2n_processor.go new file mode 100644 index 0000000..dfffa2e --- /dev/null +++ b/internal/domains/api/services/processors/qcxg/qcxg7k2n_processor.go @@ -0,0 +1,38 @@ +package qcxg + +import ( + "context" + "encoding/json" + "errors" + + "hyapi-server/internal/domains/api/dto" + "hyapi-server/internal/domains/api/services/processors" +) + +// ProcessQCXG7K2NRequest QCXG7K2N 人车核验加强版: +// 优先经天远调用 QCXG3M7Z(人车关系核验 ETC),查无结果时降级调用本地 QCXGX2X6(行驶证信息核验V2)。 +func ProcessQCXG7K2NRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { + var paramsDto dto.QCXG7K2NReq + if err := json.Unmarshal(params, ¶msDto); err != nil { + return nil, errors.Join(processors.ErrSystem, err) + } + + if err := deps.Validator.ValidateStruct(paramsDto); err != nil { + return nil, errors.Join(processors.ErrInvalidParam, err) + } + + reqParams, err := json.Marshal(paramsDto) + if err != nil { + return nil, errors.Join(processors.ErrSystem, err) + } + + respBytes, err := processors.CallTianyuanByProduct(ctx, deps, "QCXG3M7Z", reqParams) + if err == nil { + return respBytes, nil + } + if !errors.Is(err, processors.ErrNotFound) { + return nil, err + } + + return ProcessQCXGX2X6Request(ctx, reqParams, deps) +} From bd0727277e530ba86ad6df14c363bb58fcac962d Mon Sep 17 00:00:00 2001 From: liangzai <2440983361@qq.com> Date: Sun, 5 Jul 2026 00:58:25 +0800 Subject: [PATCH 2/4] f --- .../processors/qcxg/qcxg7k2n_processor.go | 11 +++++- .../processors/qcxg/qcxg7k2n_transform.go | 29 ++++++++++++++ .../qcxg/qcxg7k2n_transform_test.go | 38 +++++++++++++++++++ 3 files changed, 77 insertions(+), 1 deletion(-) create mode 100644 internal/domains/api/services/processors/qcxg/qcxg7k2n_transform.go create mode 100644 internal/domains/api/services/processors/qcxg/qcxg7k2n_transform_test.go diff --git a/internal/domains/api/services/processors/qcxg/qcxg7k2n_processor.go b/internal/domains/api/services/processors/qcxg/qcxg7k2n_processor.go index dfffa2e..bcdba6a 100644 --- a/internal/domains/api/services/processors/qcxg/qcxg7k2n_processor.go +++ b/internal/domains/api/services/processors/qcxg/qcxg7k2n_processor.go @@ -34,5 +34,14 @@ func ProcessQCXG7K2NRequest(ctx context.Context, params []byte, deps *processors return nil, err } - return ProcessQCXGX2X6Request(ctx, reqParams, deps) + respBytes, err = ProcessQCXGX2X6Request(ctx, reqParams, deps) + if err != nil { + return nil, err + } + + transformed, err := transformX2X6To3M7Z(respBytes) + if err != nil { + return nil, errors.Join(processors.ErrSystem, err) + } + return transformed, nil } diff --git a/internal/domains/api/services/processors/qcxg/qcxg7k2n_transform.go b/internal/domains/api/services/processors/qcxg/qcxg7k2n_transform.go new file mode 100644 index 0000000..779545c --- /dev/null +++ b/internal/domains/api/services/processors/qcxg/qcxg7k2n_transform.go @@ -0,0 +1,29 @@ +package qcxg + +import ( + "encoding/json" + "fmt" +) + +// transformX2X6To3M7Z 将行驶证信息核验V2响应转换为 ETC 人车关系核验格式。 +// checkResult: 00 姓名一致 -> status 1;01 姓名不一致 -> status 2。 +func transformX2X6To3M7Z(respBytes []byte) ([]byte, error) { + var raw map[string]interface{} + if err := json.Unmarshal(respBytes, &raw); err != nil { + return nil, err + } + + status := mapCheckResultToStatus(raw["checkResult"]) + return json.Marshal(map[string]string{"status": status}) +} + +func mapCheckResultToStatus(checkResult interface{}) string { + switch fmt.Sprint(checkResult) { + case "00": + return "1" + case "01": + return "2" + default: + return "2" + } +} diff --git a/internal/domains/api/services/processors/qcxg/qcxg7k2n_transform_test.go b/internal/domains/api/services/processors/qcxg/qcxg7k2n_transform_test.go new file mode 100644 index 0000000..a0b7a5b --- /dev/null +++ b/internal/domains/api/services/processors/qcxg/qcxg7k2n_transform_test.go @@ -0,0 +1,38 @@ +package qcxg + +import ( + "encoding/json" + "testing" +) + +func TestTransformX2X6To3M7Z(t *testing.T) { + tests := []struct { + name string + input string + wantStat string + }{ + {"姓名一致", `{"checkResult":"00","plate":"桂A12345"}`, "1"}, + {"姓名不一致", `{"checkResult":"01","plate":"桂A12345"}`, "2"}, + {"未知结果默认不一致", `{"checkResult":"99"}`, "2"}, + {"缺少checkResult默认不一致", `{"plate":"桂A12345"}`, "2"}, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := transformX2X6To3M7Z([]byte(tt.input)) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + var out map[string]string + if err := json.Unmarshal(got, &out); err != nil { + t.Fatalf("invalid json: %v", err) + } + if len(out) != 1 { + t.Fatalf("expected only status field, got %v", out) + } + if out["status"] != tt.wantStat { + t.Fatalf("status = %q, want %q", out["status"], tt.wantStat) + } + }) + } +} From e4751067e3d2fd0679641515b6dfcffd30483432 Mon Sep 17 00:00:00 2001 From: liangzai <2440983361@qq.com> Date: Sun, 5 Jul 2026 01:26:44 +0800 Subject: [PATCH 3/4] f --- internal/domains/api/dto/api_request_dto.go | 5 +- .../processors/qcxg/qcxg7k2n_plate_type.go | 53 +++++++++++++++++++ .../processors/qcxg/qcxg7k2n_processor.go | 21 ++++++-- 3 files changed, 74 insertions(+), 5 deletions(-) create mode 100644 internal/domains/api/services/processors/qcxg/qcxg7k2n_plate_type.go diff --git a/internal/domains/api/dto/api_request_dto.go b/internal/domains/api/dto/api_request_dto.go index 4ef0685..c1c54e3 100644 --- a/internal/domains/api/dto/api_request_dto.go +++ b/internal/domains/api/dto/api_request_dto.go @@ -139,8 +139,9 @@ type QCXGX2X6Req struct { Name string `json:"name" validate:"required,min=1,validName"` } type QCXG7K2NReq struct { - PlateNo string `json:"plate_no" validate:"required"` - Name string `json:"name" validate:"required,min=1,validName"` + PlateNo string `json:"plate_no" validate:"required"` + Name string `json:"name" validate:"required,min=1,validName"` + PlateType string `json:"plate_type" validate:"omitempty,oneof=01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 20 21 22 23 24 38 51 52"` } type QCXG1S2LReq struct { VinCode string `json:"vin_code" validate:"required"` diff --git a/internal/domains/api/services/processors/qcxg/qcxg7k2n_plate_type.go b/internal/domains/api/services/processors/qcxg/qcxg7k2n_plate_type.go new file mode 100644 index 0000000..6e86e46 --- /dev/null +++ b/internal/domains/api/services/processors/qcxg/qcxg7k2n_plate_type.go @@ -0,0 +1,53 @@ +package qcxg + +import "strings" + +const defaultPlateType = "02" + +// plateTypeToPlateColor 将车牌类型编码转换为 ETC 人车关系核验所需的车牌颜色。 +func plateTypeToPlateColor(plateType string) string { + code := normalizePlateType(plateType) + if color, ok := plateTypePlateColorMap[code]; ok { + return color + } + return "0" +} + +// normalizePlateType 归一化车牌类型,空值默认小型汽车(02)。 +func normalizePlateType(plateType string) string { + code := strings.TrimSpace(plateType) + if code == "" { + return defaultPlateType + } + return code +} + +// plateTypePlateColorMap 车牌类型 -> ETC 车牌颜色 +// 0蓝 1黄 2黑 3白 4渐变绿 5黄绿双拼 6蓝白渐变 7临时 11绿 12红 +var plateTypePlateColorMap = map[string]string{ + "01": "1", + "02": "0", + "03": "2", + "04": "2", + "05": "2", + "06": "2", + "07": "1", + "08": "0", + "09": "2", + "10": "2", + "11": "2", + "12": "2", + "13": "1", + "14": "1", + "15": "1", + "16": "1", + "17": "1", + "20": "7", + "21": "7", + "22": "7", + "23": "3", + "24": "3", + "38": "0", + "51": "5", + "52": "11", +} diff --git a/internal/domains/api/services/processors/qcxg/qcxg7k2n_processor.go b/internal/domains/api/services/processors/qcxg/qcxg7k2n_processor.go index bcdba6a..8e719da 100644 --- a/internal/domains/api/services/processors/qcxg/qcxg7k2n_processor.go +++ b/internal/domains/api/services/processors/qcxg/qcxg7k2n_processor.go @@ -21,12 +21,18 @@ func ProcessQCXG7K2NRequest(ctx context.Context, params []byte, deps *processors return nil, errors.Join(processors.ErrInvalidParam, err) } - reqParams, err := json.Marshal(paramsDto) + plateType := normalizePlateType(paramsDto.PlateType) + + etcParams, err := json.Marshal(map[string]string{ + "plate_no": paramsDto.PlateNo, + "name": paramsDto.Name, + "plate_color": plateTypeToPlateColor(paramsDto.PlateType), + }) if err != nil { return nil, errors.Join(processors.ErrSystem, err) } - respBytes, err := processors.CallTianyuanByProduct(ctx, deps, "QCXG3M7Z", reqParams) + respBytes, err := processors.CallTianyuanByProduct(ctx, deps, "QCXG3M7Z", etcParams) if err == nil { return respBytes, nil } @@ -34,7 +40,16 @@ func ProcessQCXG7K2NRequest(ctx context.Context, params []byte, deps *processors return nil, err } - respBytes, err = ProcessQCXGX2X6Request(ctx, reqParams, deps) + x2x6Params, err := json.Marshal(dto.QCXGX2X6Req{ + PlateNo: paramsDto.PlateNo, + Name: paramsDto.Name, + VehicleType: plateType, + }) + if err != nil { + return nil, errors.Join(processors.ErrSystem, err) + } + + respBytes, err = ProcessQCXGX2X6Request(ctx, x2x6Params, deps) if err != nil { return nil, err } From 642ce2eb253e1e5915d0d3dd876e0b34e6ececdc Mon Sep 17 00:00:00 2001 From: liangzai <2440983361@qq.com> Date: Sun, 5 Jul 2026 01:42:00 +0800 Subject: [PATCH 4/4] f --- .../processors/qcxg/qcxg7k2n_plate_type.go | 47 ++++++++++++++----- .../processors/qcxg/qcxg7k2n_processor.go | 6 +-- 2 files changed, 36 insertions(+), 17 deletions(-) diff --git a/internal/domains/api/services/processors/qcxg/qcxg7k2n_plate_type.go b/internal/domains/api/services/processors/qcxg/qcxg7k2n_plate_type.go index 6e86e46..d814b48 100644 --- a/internal/domains/api/services/processors/qcxg/qcxg7k2n_plate_type.go +++ b/internal/domains/api/services/processors/qcxg/qcxg7k2n_plate_type.go @@ -4,16 +4,6 @@ import "strings" const defaultPlateType = "02" -// plateTypeToPlateColor 将车牌类型编码转换为 ETC 人车关系核验所需的车牌颜色。 -func plateTypeToPlateColor(plateType string) string { - code := normalizePlateType(plateType) - if color, ok := plateTypePlateColorMap[code]; ok { - return color - } - return "0" -} - -// normalizePlateType 归一化车牌类型,空值默认小型汽车(02)。 func normalizePlateType(plateType string) string { code := strings.TrimSpace(plateType) if code == "" { @@ -22,8 +12,18 @@ func normalizePlateType(plateType string) string { return code } -// plateTypePlateColorMap 车牌类型 -> ETC 车牌颜色 -// 0蓝 1黄 2黑 3白 4渐变绿 5黄绿双拼 6蓝白渐变 7临时 11绿 12红 +func etcPlateColorParam(plateType string) (color string, include bool) { + code := strings.TrimSpace(plateType) + if code == "" || code == "02" { + return "", false + } + color, ok := plateTypePlateColorMap[code] + if !ok || color == "0" { + return "", false + } + return color, true +} + var plateTypePlateColorMap = map[string]string{ "01": "1", "02": "0", @@ -51,3 +51,26 @@ var plateTypePlateColorMap = map[string]string{ "51": "5", "52": "11", } + +func buildETCShujubaoParams(plateNo, name, plateType string) map[string]interface{} { + params := map[string]interface{}{ + "key": "a2f32fc54b44ebc85b97a2aaff1734ec", + "carNo": plateNo, + "name": name, + } + if color, include := etcPlateColorParam(plateType); include { + params["plateColor"] = color + } + return params +} + +func buildETCTianyuanParams(plateNo, name, plateType string) map[string]string { + params := map[string]string{ + "plate_no": plateNo, + "name": name, + } + if color, include := etcPlateColorParam(plateType); include { + params["plate_color"] = color + } + return params +} diff --git a/internal/domains/api/services/processors/qcxg/qcxg7k2n_processor.go b/internal/domains/api/services/processors/qcxg/qcxg7k2n_processor.go index 8e719da..82f8935 100644 --- a/internal/domains/api/services/processors/qcxg/qcxg7k2n_processor.go +++ b/internal/domains/api/services/processors/qcxg/qcxg7k2n_processor.go @@ -23,11 +23,7 @@ func ProcessQCXG7K2NRequest(ctx context.Context, params []byte, deps *processors plateType := normalizePlateType(paramsDto.PlateType) - etcParams, err := json.Marshal(map[string]string{ - "plate_no": paramsDto.PlateNo, - "name": paramsDto.Name, - "plate_color": plateTypeToPlateColor(paramsDto.PlateType), - }) + etcParams, err := json.Marshal(buildETCTianyuanParams(paramsDto.PlateNo, paramsDto.Name, paramsDto.PlateType)) if err != nil { return nil, errors.Join(processors.ErrSystem, err) }