diff --git a/internal/domains/api/dto/api_request_dto.go b/internal/domains/api/dto/api_request_dto.go index c52998d..87eb35a 100644 --- a/internal/domains/api/dto/api_request_dto.go +++ b/internal/domains/api/dto/api_request_dto.go @@ -130,6 +130,12 @@ type QYGL7HBNReq struct { type QCXGA8V3Req struct { VinCode string `json:"vin_code" validate:"required"` } +type QCXGH3R8Req struct { + VinCode string `json:"vin_code" validate:"required"` +} +type QCXGK5M2Req struct { + VinCode string `json:"vin_code" validate:"required"` +} type QCXGCP77Req 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 aa3b9df..aa2ca90 100644 --- a/internal/domains/api/services/api_request_service.go +++ b/internal/domains/api/services/api_request_service.go @@ -255,6 +255,8 @@ func registerAllProcessors(combService *comb.CombService) { "QCXGIJY3": qcxg.ProcessQCXGIJY3Request, // 名下车辆诺尔 "QCXG6U5G": qcxg.ProcessQCXG6U5GRequest, // 车辆核验 "QCXG7K2N": qcxg.ProcessQCXG7K2NRequest, // 人车核验加强版 + "QCXGH3R8": qcxg.ProcessQCXGH3R8Request, // 车辆注册日期查询(VIN) + "QCXGK5M2": qcxg.ProcessQCXGK5M2Request, // 车辆投保日期与城市查询(VIN) // DWBG系列处理器 - 多维报告 diff --git a/internal/domains/api/services/form_config_service.go b/internal/domains/api/services/form_config_service.go index 4819f12..0da19f2 100644 --- a/internal/domains/api/services/form_config_service.go +++ b/internal/domains/api/services/form_config_service.go @@ -302,6 +302,8 @@ func (s *FormConfigServiceImpl) getDTOStruct(ctx context.Context, apiCode string "FLXGC4CT": &dto.FLXGC4CTReq{}, //汇博-个人涉诉 "QYGLLUCM": &dto.QYGLLUCMReq{}, //汇博-企业涉诉 "QCXGA8V3": &dto.QCXGA8V3Req{}, //全国车辆配置查验(车五项+使用性质+承保) + "QCXGH3R8": &dto.QCXGH3R8Req{}, //车辆注册日期查询(VIN) + "QCXGK5M2": &dto.QCXGK5M2Req{}, //车辆投保日期与城市查询(VIN) "QCXGCP77": &dto.QCXGCP77Req{}, //全国车辆配置查验(车辆详情) "QCXGX2X6": &dto.QCXGX2X6Req{}, //行驶证信息核验V2 "QCXG1S2L": &dto.QCXG1S2LReq{}, //汽车车辆五项 diff --git a/internal/domains/api/services/processors/qcxg/a8v3_shared.go b/internal/domains/api/services/processors/qcxg/a8v3_shared.go new file mode 100644 index 0000000..cafd310 --- /dev/null +++ b/internal/domains/api/services/processors/qcxg/a8v3_shared.go @@ -0,0 +1,67 @@ +package qcxg + +import ( + "context" + "encoding/json" + "errors" + "fmt" + + "hyapi-server/internal/domains/api/dto" + "hyapi-server/internal/domains/api/services/processors" +) + +// a8v3RawResult QCXGA8V3 上游原始字段 +type a8v3RawResult struct { + Usage string + RegisterDate string + InsuranceMonth string + VehicleModel string + Brand string + PlateNo string + EngineNo string + Vin string +} + +func callA8V3ByVin(ctx context.Context, vinCode string, deps *processors.ProcessorDependencies) (*a8v3RawResult, error) { + params, err := json.Marshal(dto.QCXGA8V3Req{VinCode: vinCode}) + if err != nil { + return nil, errors.Join(processors.ErrSystem, err) + } + + respBytes, err := ProcessQCXGA8V3Request(ctx, params, deps) + if err != nil { + return nil, err + } + + return parseA8V3Result(respBytes) +} + +func parseA8V3Result(respBytes []byte) (*a8v3RawResult, error) { + var raw map[string]interface{} + if err := json.Unmarshal(respBytes, &raw); err != nil { + return nil, errors.Join(processors.ErrSystem, err) + } + + return &a8v3RawResult{ + Usage: asString(raw["usage"]), + RegisterDate: asString(raw["registerDate"]), + InsuranceMonth: asString(raw["insuranceMonth"]), + VehicleModel: asString(raw["clxh"]), + Brand: asString(raw["brand"]), + PlateNo: asString(raw["cph"]), + EngineNo: asString(raw["fdjh"]), + Vin: asString(raw["vin"]), + }, nil +} + +func asString(v interface{}) string { + if v == nil { + return "" + } + switch t := v.(type) { + case string: + return t + default: + return fmt.Sprint(t) + } +} diff --git a/internal/domains/api/services/processors/qcxg/car_plate.go b/internal/domains/api/services/processors/qcxg/car_plate.go new file mode 100644 index 0000000..2083e84 --- /dev/null +++ b/internal/domains/api/services/processors/qcxg/car_plate.go @@ -0,0 +1,43 @@ +package qcxg + +import ( + _ "embed" + "encoding/json" + "strings" + "unicode/utf8" +) + +//go:embed data/car_plate.json +var carPlateJSON []byte + +var carPlateCityMap map[string]string + +func init() { + carPlateCityMap = make(map[string]string) + _ = json.Unmarshal(carPlateJSON, &carPlateCityMap) +} + +// lookupCityByPlateNo 根据车牌号前缀(省简称+字母)查城市,未匹配返回 "-" +func lookupCityByPlateNo(plateNo string) string { + prefix := extractPlatePrefix(plateNo) + if prefix == "" { + return "-" + } + if city, ok := carPlateCityMap[prefix]; ok && city != "" { + return city + } + return "-" +} + +// extractPlatePrefix 取车牌前两个字符作为字典键,如 "鲁A12345" -> "鲁A" +func extractPlatePrefix(plateNo string) string { + plateNo = strings.TrimSpace(plateNo) + if plateNo == "" { + return "" + } + if utf8.RuneCountInString(plateNo) < 2 { + return "" + } + runes := []rune(plateNo) + return string(runes[:2]) +} diff --git a/internal/domains/api/services/processors/qcxg/car_plate_test.go b/internal/domains/api/services/processors/qcxg/car_plate_test.go new file mode 100644 index 0000000..9db364a --- /dev/null +++ b/internal/domains/api/services/processors/qcxg/car_plate_test.go @@ -0,0 +1,59 @@ +package qcxg + +import "testing" + +func TestLookupCityByPlateNo(t *testing.T) { + tests := []struct { + name string + plateNo string + want string + }{ + {name: "济南", plateNo: "鲁A12345", want: "济南市"}, + {name: "青岛增补", plateNo: "鲁U88888", want: "青岛市(增补号段)"}, + {name: "北京", plateNo: "京A00001", want: "北京市"}, + {name: "空车牌", plateNo: "", want: "-"}, + {name: "单字", plateNo: "鲁", want: "-"}, + {name: "未知前缀", plateNo: "XX12345", want: "-"}, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := lookupCityByPlateNo(tt.plateNo); got != tt.want { + t.Fatalf("lookupCityByPlateNo(%q) = %q, want %q", tt.plateNo, got, tt.want) + } + }) + } +} + +func TestParseA8V3Result(t *testing.T) { + raw := []byte(`{ + "fdjh": "UJ91220946", + "clxh": "LZW1029PYA", + "usage": "非营业", + "insuranceMonth": "2025-02", + "cph": "鲁A12345", + "vin": "LZABCDEF00", + "brand": "五菱牌", + "registerDate": "2018-12" + }`) + + got, err := parseA8V3Result(raw) + if err != nil { + t.Fatalf("parseA8V3Result error: %v", err) + } + if got.RegisterDate != "2018-12" { + t.Fatalf("RegisterDate = %q", got.RegisterDate) + } + if got.InsuranceMonth != "2025-02" { + t.Fatalf("InsuranceMonth = %q", got.InsuranceMonth) + } + if got.PlateNo != "鲁A12345" { + t.Fatalf("PlateNo = %q", got.PlateNo) + } + if got.VehicleModel != "LZW1029PYA" { + t.Fatalf("VehicleModel = %q", got.VehicleModel) + } + if got.EngineNo != "UJ91220946" { + t.Fatalf("EngineNo = %q", got.EngineNo) + } +} diff --git a/internal/domains/api/services/processors/qcxg/data/car_plate.json b/internal/domains/api/services/processors/qcxg/data/car_plate.json new file mode 100644 index 0000000..ca9212c --- /dev/null +++ b/internal/domains/api/services/processors/qcxg/data/car_plate.json @@ -0,0 +1,420 @@ +{ + "京A": "北京市", + "京B": "北京市(出租车)", + "京C": "北京市", + "京E": "北京市", + "京F": "北京市", + "京G": "北京市(远郊区县)", + "京H": "北京市", + "京J": "北京市", + "京K": "北京市", + "京L": "北京市", + "京M": "北京市", + "京N": "北京市", + "京P": "北京市", + "京Q": "北京市", + "京Y": "北京市(远郊区县)", + "津A": "天津市", + "津B": "天津市", + "津C": "天津市", + "津D": "天津市", + "津E": "天津市(出租车)", + "津F": "天津市", + "津G": "天津市", + "津H": "天津市", + "津J": "天津市", + "津K": "天津市", + "津L": "天津市", + "津M": "天津市", + "津N": "天津市", + "津P": "天津市", + "津Q": "天津市", + "津R": "天津市", + "沪A": "上海市", + "沪B": "上海市", + "沪C": "上海市(远郊区县,禁入外环内)", + "沪D": "上海市", + "沪E": "上海市", + "沪F": "上海市", + "沪G": "上海市", + "沪H": "上海市", + "沪J": "上海市", + "沪K": "上海市", + "沪L": "上海市", + "沪M": "上海市", + "沪N": "上海市", + "沪R": "上海市(崇明、长兴、横沙)", + "渝A": "重庆市(主城九区)", + "渝B": "重庆市(主城区增补)", + "渝C": "重庆市(永川区、江津区、合川区、潼南区、铜梁区、璧山区、大足区、綦江区、荣昌区)", + "渝D": "重庆市(主城区增补)", + "渝F": "重庆市(万州区、开州区、梁平区、城口县、巫山县、巫溪县、忠县、云阳县、奉节县)", + "渝G": "重庆市(涪陵区、南川区、垫江县、丰都县、武隆区)", + "渝H": "重庆市(黔江区、石柱土家族自治县、秀山土家族苗族自治县、酉阳土家族苗族自治县、彭水苗族土家族自治县)", + "冀A": "石家庄市", + "冀B": "唐山市", + "冀C": "秦皇岛市", + "冀D": "邯郸市", + "冀E": "邢台市", + "冀F": "保定市", + "冀G": "张家口市", + "冀H": "承德市", + "冀J": "沧州市", + "冀R": "廊坊市", + "冀T": "衡水市", + "晋A": "太原市", + "晋B": "大同市", + "晋C": "阳泉市", + "晋D": "长治市", + "晋E": "晋城市", + "晋F": "朔州市", + "晋H": "忻州市", + "晋J": "吕梁市", + "晋K": "晋中市", + "晋L": "临汾市", + "晋M": "运城市", + "蒙A": "呼和浩特市", + "蒙B": "包头市", + "蒙C": "乌海市", + "蒙D": "赤峰市", + "蒙E": "呼伦贝尔市", + "蒙F": "兴安盟", + "蒙G": "通辽市", + "蒙H": "锡林郭勒盟", + "蒙J": "乌兰察布市", + "蒙K": "鄂尔多斯市", + "蒙L": "巴彦淖尔市", + "蒙M": "阿拉善盟", + "辽A": "沈阳市", + "辽B": "大连市", + "辽C": "鞍山市", + "辽D": "抚顺市", + "辽E": "本溪市", + "辽F": "丹东市", + "辽G": "锦州市", + "辽H": "营口市", + "辽J": "阜新市", + "辽K": "辽阳市", + "辽L": "盘锦市", + "辽M": "铁岭市", + "辽N": "朝阳市", + "辽P": "葫芦岛市", + "吉A": "长春市", + "吉B": "吉林市", + "吉C": "四平市", + "吉D": "辽源市", + "吉E": "通化市", + "吉F": "白山市", + "吉G": "白城市", + "吉H": "延边朝鲜族自治州", + "吉J": "松原市", + "吉K": "长白山保护开发区", + "黑A": "哈尔滨市", + "黑B": "齐齐哈尔市", + "黑C": "牡丹江市", + "黑D": "佳木斯市", + "黑E": "大庆市", + "黑F": "伊春市", + "黑G": "鸡西市", + "黑H": "鹤岗市", + "黑J": "双鸭山市", + "黑K": "七台河市", + "黑L": "哈尔滨市(原松花江地区)", + "黑M": "绥化市", + "黑N": "黑河市", + "黑P": "大兴安岭地区", + "黑R": "黑龙江省农垦系统", + "苏A": "南京市", + "苏B": "无锡市", + "苏C": "徐州市", + "苏D": "常州市", + "苏E": "苏州市", + "苏U": "苏州市(增补号段)", + "苏F": "南通市", + "苏G": "连云港市", + "苏H": "淮安市", + "苏J": "盐城市", + "苏K": "扬州市", + "苏L": "镇江市", + "苏M": "泰州市", + "苏N": "宿迁市", + "浙A": "杭州市", + "浙M": "杭州市(增补号段)", + "浙B": "宁波市", + "浙C": "温州市", + "浙D": "绍兴市", + "浙E": "湖州市", + "浙F": "嘉兴市", + "浙G": "金华市", + "浙H": "衢州市", + "浙J": "台州市", + "浙K": "丽水市", + "浙L": "舟山市", + "皖A": "合肥市", + "皖B": "芜湖市", + "皖C": "蚌埠市", + "皖D": "淮南市", + "皖E": "马鞍山市", + "皖F": "淮北市", + "皖G": "铜陵市", + "皖H": "安庆市", + "皖J": "黄山市", + "皖K": "阜阳市", + "皖L": "宿州市", + "皖M": "滁州市", + "皖N": "六安市", + "皖P": "宣城市", + "皖Q": "巢湖市(已撤销,存量继续使用)", + "皖R": "池州市", + "皖S": "亳州市", + "闽A": "福州市", + "闽B": "莆田市", + "闽C": "泉州市", + "闽D": "厦门市", + "闽E": "漳州市", + "闽F": "龙岩市", + "闽G": "三明市", + "闽H": "南平市", + "闽J": "宁德市", + "闽K": "平潭综合实验区", + "赣A": "南昌市", + "赣M": "南昌市(省直系统)", + "赣B": "赣州市", + "赣C": "宜春市", + "赣D": "吉安市", + "赣E": "上饶市", + "赣F": "抚州市", + "赣G": "九江市", + "赣H": "景德镇市", + "赣J": "萍乡市", + "赣K": "新余市", + "赣L": "鹰潭市", + "鲁A": "济南市", + "鲁S": "济南市(原莱芜市,存量继续使用)", + "鲁B": "青岛市", + "鲁U": "青岛市(增补号段)", + "鲁C": "淄博市", + "鲁D": "枣庄市", + "鲁E": "东营市", + "鲁F": "烟台市", + "鲁Y": "烟台市(增补号段)", + "鲁G": "潍坊市", + "鲁V": "潍坊市(增补号段)", + "鲁H": "济宁市", + "鲁J": "泰安市", + "鲁K": "威海市", + "鲁L": "日照市", + "鲁M": "滨州市", + "鲁N": "德州市", + "鲁P": "聊城市", + "鲁Q": "临沂市", + "鲁R": "菏泽市", + "豫A": "郑州市", + "豫V": "郑州市(增补号段)", + "豫B": "开封市", + "豫C": "洛阳市", + "豫D": "平顶山市", + "豫E": "安阳市", + "豫F": "鹤壁市", + "豫G": "新乡市", + "豫H": "焦作市", + "豫J": "濮阳市", + "豫K": "许昌市", + "豫L": "漯河市", + "豫M": "三门峡市", + "豫N": "商丘市", + "豫P": "周口市", + "豫Q": "驻马店市", + "豫R": "南阳市", + "豫S": "信阳市", + "豫U": "济源市", + "鄂A": "武汉市", + "鄂W": "武汉市(增补号段)", + "鄂B": "黄石市", + "鄂C": "十堰市", + "鄂D": "荆州市", + "鄂E": "宜昌市", + "鄂F": "襄阳市", + "鄂G": "鄂州市", + "鄂H": "荆门市", + "鄂J": "黄冈市", + "鄂K": "孝感市", + "鄂L": "咸宁市", + "鄂M": "仙桃市", + "鄂N": "潜江市", + "鄂P": "神农架林区", + "鄂Q": "恩施土家族苗族自治州", + "鄂R": "天门市", + "鄂S": "随州市", + "湘A": "长沙市", + "湘B": "株洲市", + "湘C": "湘潭市", + "湘D": "衡阳市", + "湘E": "邵阳市", + "湘F": "岳阳市", + "湘G": "张家界市", + "湘H": "益阳市", + "湘J": "常德市", + "湘K": "娄底市", + "湘L": "郴州市", + "湘M": "永州市", + "湘N": "怀化市", + "湘U": "湘西土家族苗族自治州", + "粤A": "广州市", + "粤B": "深圳市", + "粤C": "珠海市", + "粤D": "汕头市", + "粤E": "佛山市", + "粤X": "佛山市(顺德区,存量继续使用)", + "粤Y": "佛山市(南海区,存量继续使用)", + "粤F": "韶关市", + "粤G": "湛江市", + "粤H": "肇庆市", + "粤J": "江门市", + "粤K": "茂名市", + "粤L": "惠州市", + "粤M": "梅州市", + "粤N": "汕尾市", + "粤P": "河源市", + "粤Q": "阳江市", + "粤R": "清远市", + "粤S": "东莞市", + "粤T": "中山市", + "粤U": "潮州市", + "粤V": "揭阳市", + "粤W": "云浮市", + "桂A": "南宁市", + "桂B": "柳州市", + "桂C": "桂林市", + "桂H": "桂林市(原桂林地区)", + "桂D": "梧州市", + "桂E": "北海市", + "桂F": "崇左市", + "桂G": "来宾市", + "桂J": "贺州市", + "桂K": "玉林市", + "桂L": "百色市", + "桂M": "河池市", + "桂N": "钦州市", + "桂P": "防城港市", + "桂R": "贵港市", + "琼A": "海口市", + "琼B": "三亚市", + "琼C": "琼北地区(文昌市、琼海市、万宁市、定安县、屯昌县、澄迈县、临高县)", + "琼D": "琼南地区(五指山市、东方市、白沙黎族自治县、昌江黎族自治县、乐东黎族自治县、陵水黎族自治县、保亭黎族苗族自治县、琼中黎族苗族自治县)", + "琼E": "洋浦经济开发区", + "琼F": "儋州市", + "川A": "成都市", + "川G": "成都市(增补号段)", + "川B": "绵阳市", + "川C": "自贡市", + "川D": "攀枝花市", + "川E": "泸州市", + "川F": "德阳市", + "川H": "广元市", + "川J": "遂宁市", + "川K": "内江市", + "川L": "乐山市", + "川M": "资阳市", + "川Q": "宜宾市", + "川R": "南充市", + "川S": "达州市", + "川T": "雅安市", + "川U": "阿坝藏族羌族自治州", + "川V": "甘孜藏族自治州", + "川W": "凉山彝族自治州", + "川X": "广安市", + "川Y": "巴中市", + "川Z": "眉山市", + "贵A": "贵阳市", + "贵B": "六盘水市", + "贵C": "遵义市", + "贵D": "铜仁市", + "贵E": "黔西南布依族苗族自治州", + "贵F": "毕节市", + "贵G": "安顺市", + "贵H": "黔东南苗族侗族自治州", + "贵J": "黔南布依族苗族自治州", + "云A": "昆明市", + "云B": "东川市(已撤销,存量继续使用)", + "云C": "昭通市", + "云D": "曲靖市", + "云E": "楚雄彝族自治州", + "云F": "玉溪市", + "云G": "红河哈尼族彝族自治州", + "云H": "文山壮族苗族自治州", + "云J": "普洱市", + "云K": "西双版纳傣族自治州", + "云L": "大理白族自治州", + "云M": "保山市", + "云N": "德宏傣族景颇族自治州", + "云P": "丽江市", + "云Q": "怒江傈僳族自治州", + "云R": "迪庆藏族自治州", + "云S": "临沧市", + "藏A": "拉萨市", + "藏B": "昌都市", + "藏C": "山南市", + "藏D": "日喀则市", + "藏E": "那曲市", + "藏F": "阿里地区", + "藏G": "林芝市", + "藏H": "驻四川省天全县车辆管理所", + "藏J": "驻青海省格尔木市车辆管理所", + "陕A": "西安市", + "陕U": "西安市(增补号段)", + "陕B": "铜川市", + "陕C": "宝鸡市", + "陕D": "咸阳市", + "陕E": "渭南市", + "陕F": "汉中市", + "陕G": "安康市", + "陕H": "商洛市", + "陕J": "延安市", + "陕K": "榆林市", + "陕V": "杨凌农业高新技术产业示范区", + "甘A": "兰州市", + "甘B": "嘉峪关市", + "甘C": "金昌市", + "甘D": "白银市", + "甘E": "天水市", + "甘F": "酒泉市", + "甘G": "张掖市", + "甘H": "武威市", + "甘J": "定西市", + "甘K": "陇南市", + "甘L": "平凉市", + "甘M": "庆阳市", + "甘N": "临夏回族自治州", + "甘P": "甘南藏族自治州", + "青A": "西宁市", + "青B": "海东市", + "青C": "海北藏族自治州", + "青D": "黄南藏族自治州", + "青E": "海南藏族自治州", + "青F": "果洛藏族自治州", + "青G": "玉树藏族自治州", + "青H": "海西蒙古族藏族自治州", + "宁A": "银川市", + "宁B": "石嘴山市", + "宁C": "吴忠市", + "宁D": "固原市", + "宁E": "中卫市", + "新A": "乌鲁木齐市", + "新B": "昌吉回族自治州", + "新C": "石河子市", + "新D": "奎屯市", + "新E": "博尔塔拉蒙古自治州", + "新F": "伊犁哈萨克自治州", + "新G": "塔城地区", + "新H": "阿勒泰地区", + "新J": "克拉玛依市", + "新K": "吐鲁番市", + "新L": "哈密市", + "新M": "巴音郭楞蒙古自治州", + "新N": "阿克苏地区", + "新P": "克孜勒苏柯尔克孜自治州", + "新Q": "喀什地区", + "新R": "和田地区", + "新S": "昆玉市" +} \ No newline at end of file diff --git a/internal/domains/api/services/processors/qcxg/qcxgh3r8_processor.go b/internal/domains/api/services/processors/qcxg/qcxgh3r8_processor.go new file mode 100644 index 0000000..0da402b --- /dev/null +++ b/internal/domains/api/services/processors/qcxg/qcxgh3r8_processor.go @@ -0,0 +1,36 @@ +package qcxg + +import ( + "context" + "encoding/json" + "errors" + + "hyapi-server/internal/domains/api/dto" + "hyapi-server/internal/domains/api/services/processors" +) + +// ProcessQCXGH3R8Request QCXGH3R8 车辆注册日期查询(VIN) +// 复用 QCXGA8V3,仅返回 registerDate。 +func ProcessQCXGH3R8Request(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { + var paramsDto dto.QCXGH3R8Req + 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) + } + + result, err := callA8V3ByVin(ctx, paramsDto.VinCode, deps) + if err != nil { + return nil, err + } + + respBytes, err := json.Marshal(map[string]string{ + "registerDate": result.RegisterDate, + }) + if err != nil { + return nil, errors.Join(processors.ErrSystem, err) + } + return respBytes, nil +} diff --git a/internal/domains/api/services/processors/qcxg/qcxgk5m2_processor.go b/internal/domains/api/services/processors/qcxg/qcxgk5m2_processor.go new file mode 100644 index 0000000..dabc650 --- /dev/null +++ b/internal/domains/api/services/processors/qcxg/qcxgk5m2_processor.go @@ -0,0 +1,37 @@ +package qcxg + +import ( + "context" + "encoding/json" + "errors" + + "hyapi-server/internal/domains/api/dto" + "hyapi-server/internal/domains/api/services/processors" +) + +// ProcessQCXGK5M2Request QCXGK5M2 车辆投保日期与城市查询(VIN) +// 复用 QCXGA8V3,返回 insuranceMonth,并根据车牌前缀字典解析 city。 +func ProcessQCXGK5M2Request(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { + var paramsDto dto.QCXGK5M2Req + 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) + } + + result, err := callA8V3ByVin(ctx, paramsDto.VinCode, deps) + if err != nil { + return nil, err + } + + respBytes, err := json.Marshal(map[string]string{ + "insuranceMonth": result.InsuranceMonth, + "city": lookupCityByPlateNo(result.PlateNo), + }) + if err != nil { + return nil, errors.Join(processors.ErrSystem, err) + } + return respBytes, nil +}