Merge branch 'main' of http://1.117.67.95:3000/team/hyapi-server
This commit is contained in:
@@ -0,0 +1,76 @@
|
||||
package qcxg
|
||||
|
||||
import "strings"
|
||||
|
||||
const defaultPlateType = "02"
|
||||
|
||||
func normalizePlateType(plateType string) string {
|
||||
code := strings.TrimSpace(plateType)
|
||||
if code == "" {
|
||||
return defaultPlateType
|
||||
}
|
||||
return code
|
||||
}
|
||||
|
||||
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",
|
||||
"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",
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
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)
|
||||
}
|
||||
|
||||
plateType := normalizePlateType(paramsDto.PlateType)
|
||||
|
||||
etcParams, err := json.Marshal(buildETCTianyuanParams(paramsDto.PlateNo, paramsDto.Name, paramsDto.PlateType))
|
||||
if err != nil {
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
|
||||
respBytes, err := processors.CallTianyuanByProduct(ctx, deps, "QCXG3M7Z", etcParams)
|
||||
if err == nil {
|
||||
return respBytes, nil
|
||||
}
|
||||
if !errors.Is(err, processors.ErrNotFound) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
transformed, err := transformX2X6To3M7Z(respBytes)
|
||||
if err != nil {
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
return transformed, nil
|
||||
}
|
||||
@@ -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"
|
||||
}
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user