From c08f40d212750e29f31c98ffc392585d68a8eec6 Mon Sep 17 00:00:00 2001 From: liangzai <2440983361@qq.com> Date: Thu, 2 Jul 2026 14:12:51 +0800 Subject: [PATCH] f --- .../processors/dwbg/dwbg7f3a_processor.go | 56 +++---- .../processors/dwbg/dwbg7f3a_transform.go | 143 ++++++++++++++++++ .../dwbg/dwbg7f3a_transform_test.go | 103 +++++++++++++ 3 files changed, 276 insertions(+), 26 deletions(-) create mode 100644 internal/domains/api/services/processors/dwbg/dwbg7f3a_transform.go create mode 100644 internal/domains/api/services/processors/dwbg/dwbg7f3a_transform_test.go diff --git a/internal/domains/api/services/processors/dwbg/dwbg7f3a_processor.go b/internal/domains/api/services/processors/dwbg/dwbg7f3a_processor.go index 4ee2c27..74ed49b 100644 --- a/internal/domains/api/services/processors/dwbg/dwbg7f3a_processor.go +++ b/internal/domains/api/services/processors/dwbg/dwbg7f3a_processor.go @@ -7,10 +7,10 @@ import ( "tyapi-server/internal/domains/api/dto" "tyapi-server/internal/domains/api/services/processors" - "tyapi-server/internal/infrastructure/external/xingwei" + "tyapi-server/internal/infrastructure/external/zhicha" ) -// ProcessDWBG7F3ARequest DWBG7F3A API处理方法 - 行为数据查询 +// ProcessDWBG7F3ARequest DWBG7F3A API处理方法 - 多头借贷行业风险版 func ProcessDWBG7F3ARequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { var paramsDto dto.DWBG7F3AReq if err := json.Unmarshal(params, ¶msDto); err != nil { @@ -21,31 +21,35 @@ func ProcessDWBG7F3ARequest(ctx context.Context, params []byte, deps *processors return nil, errors.Join(processors.ErrInvalidParam, err) } - // 构建请求数据,使用xingwei服务的正确字段名 - reqData := map[string]interface{}{ - "name": paramsDto.Name, - "idCardNum": paramsDto.IDCard, - "phoneNumber": paramsDto.MobileNo, - } - - // 调用行为数据API,使用指定的project_id - projectID := "CDJ-1101695406546284544" - respBytes, err := deps.XingweiService.CallAPI(ctx, projectID, reqData) + encryptedName, err := deps.ZhichaService.Encrypt(paramsDto.Name) if err != nil { - if errors.Is(err, xingwei.ErrNotFound) { - // 查空情况,返回特定的查空错误 - return nil, errors.Join(processors.ErrNotFound, err) - } else if errors.Is(err, xingwei.ErrDatasource) { - // 数据源错误 - return nil, errors.Join(processors.ErrDatasource, err) - } else if errors.Is(err, xingwei.ErrSystem) { - // 系统错误 - return nil, errors.Join(processors.ErrSystem, err) - } else { - // 其他未知错误 - return nil, errors.Join(processors.ErrSystem, err) - } + return nil, errors.Join(processors.ErrSystem, err) } - return respBytes, nil + encryptedIDCard, err := deps.ZhichaService.Encrypt(paramsDto.IDCard) + if err != nil { + return nil, errors.Join(processors.ErrSystem, err) + } + + encryptedMobileNo, err := deps.ZhichaService.Encrypt(paramsDto.MobileNo) + if err != nil { + return nil, errors.Join(processors.ErrSystem, err) + } + + reqData := map[string]interface{}{ + "name": encryptedName, + "idCard": encryptedIDCard, + "phone": encryptedMobileNo, + "authorized": "1", + } + + respData, err := deps.ZhichaService.CallAPI(ctx, "ZCI047", reqData) + if err != nil { + if errors.Is(err, zhicha.ErrDatasource) { + return nil, errors.Join(processors.ErrDatasource, err) + } + return nil, errors.Join(processors.ErrSystem, err) + } + + return transformDWBG7F3AResponse(respData) } diff --git a/internal/domains/api/services/processors/dwbg/dwbg7f3a_transform.go b/internal/domains/api/services/processors/dwbg/dwbg7f3a_transform.go new file mode 100644 index 0000000..3cd8cd3 --- /dev/null +++ b/internal/domains/api/services/processors/dwbg/dwbg7f3a_transform.go @@ -0,0 +1,143 @@ +package dwbg + +import ( + "encoding/json" + "fmt" + "strconv" +) + +const dwbg7F3AReportKey = "riskInfo_report_v3.1" + +// intRiskCodes 旧版 DWBG7F3A 响应中 riskCode / riskCodeValue 使用数值类型的指标。 +var intRiskCodes = map[string]struct{}{ + "21007": {}, + "22006": {}, + "23006": {}, +} + +// transformDWBG7F3AResponse 将 JRZQ8F7C(ZCI047) 响应适配为 DWBG7F3A 旧结构。 +func transformDWBG7F3AResponse(respData interface{}) ([]byte, error) { + items, ok := extractDWBG7F3ARiskItems(respData) + if !ok || len(items) == 0 { + return json.Marshal(map[string]interface{}{ + dwbg7F3AReportKey: "-1", + }) + } + + normalized := make([]map[string]interface{}, 0, len(items)) + for _, item := range items { + itemMap, ok := item.(map[string]interface{}) + if !ok { + continue + } + normalized = append(normalized, normalizeDWBG7F3ARiskItem(itemMap)) + } + + if len(normalized) == 0 { + return json.Marshal(map[string]interface{}{ + dwbg7F3AReportKey: "-1", + }) + } + + return json.Marshal(map[string]interface{}{ + dwbg7F3AReportKey: normalized, + }) +} + +func extractDWBG7F3ARiskItems(data interface{}) ([]interface{}, bool) { + switch v := data.(type) { + case nil: + return nil, false + case []interface{}: + return v, true + case map[string]interface{}: + if len(v) == 0 { + return nil, false + } + if nested, ok := v["data"]; ok { + return extractDWBG7F3ARiskItems(nested) + } + if nested, ok := v[dwbg7F3AReportKey]; ok { + if reportStr, ok := nested.(string); ok && reportStr == "-1" { + return nil, false + } + return extractDWBG7F3ARiskItems(nested) + } + return nil, false + default: + return nil, false + } +} + +func normalizeDWBG7F3ARiskItem(item map[string]interface{}) map[string]interface{} { + codeStr := stringifyDWBG7F3AValue(item["riskCode"]) + valueRaw := item["riskCodeValue"] + + if _, useInt := intRiskCodes[codeStr]; useInt { + return map[string]interface{}{ + "riskCode": parseDWBG7F3AInt(codeStr), + "riskCodeValue": parseDWBG7F3AIntValue(valueRaw), + } + } + + return map[string]interface{}{ + "riskCode": codeStr, + "riskCodeValue": stringifyDWBG7F3AValue(valueRaw), + } +} + +func stringifyDWBG7F3AValue(v interface{}) string { + if v == nil { + return "" + } + switch val := v.(type) { + case string: + return val + case float64: + if val == float64(int64(val)) { + return strconv.FormatInt(int64(val), 10) + } + return strconv.FormatFloat(val, 'f', -1, 64) + case int: + return strconv.Itoa(val) + case int32: + return strconv.FormatInt(int64(val), 10) + case int64: + return strconv.FormatInt(val, 10) + default: + return fmt.Sprint(val) + } +} + +func parseDWBG7F3AInt(code string) int { + n, err := strconv.Atoi(code) + if err != nil { + return 0 + } + return n +} + +func parseDWBG7F3AIntValue(v interface{}) int { + switch val := v.(type) { + case float64: + return int(val) + case int: + return val + case int32: + return int(val) + case int64: + return int(val) + case string: + n, err := strconv.Atoi(val) + if err != nil { + return 0 + } + return n + default: + n, err := strconv.Atoi(stringifyDWBG7F3AValue(v)) + if err != nil { + return 0 + } + return n + } +} diff --git a/internal/domains/api/services/processors/dwbg/dwbg7f3a_transform_test.go b/internal/domains/api/services/processors/dwbg/dwbg7f3a_transform_test.go new file mode 100644 index 0000000..ab3b106 --- /dev/null +++ b/internal/domains/api/services/processors/dwbg/dwbg7f3a_transform_test.go @@ -0,0 +1,103 @@ +package dwbg + +import ( + "encoding/json" + "testing" + + "github.com/tidwall/gjson" +) + +const dwbg7F3AReportGJSONPath = `riskInfo_report_v3\.1` + +func TestTransformDWBG7F3AResponseNotFound(t *testing.T) { + cases := []interface{}{ + nil, + map[string]interface{}{}, + []interface{}{}, + map[string]interface{}{"data": []interface{}{}}, + map[string]interface{}{dwbg7F3AReportKey: "-1"}, + } + + for _, input := range cases { + respBytes, err := transformDWBG7F3AResponse(input) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + if got := gjson.GetBytes(respBytes, dwbg7F3AReportGJSONPath).String(); got != "-1" { + t.Fatalf("expected -1, got %q for input %#v", got, input) + } + } +} + +func TestTransformDWBG7F3AResponseSuccess(t *testing.T) { + input := []interface{}{ + map[string]interface{}{"riskCode": 23006, "riskCodeValue": 16}, + map[string]interface{}{"riskCode": 21007, "riskCodeValue": 40}, + map[string]interface{}{"riskCode": "41001", "riskCodeValue": "43"}, + map[string]interface{}{"riskCodeValue": "1", "riskCode": "40025"}, + } + + respBytes, err := transformDWBG7F3AResponse(input) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + + report := gjson.GetBytes(respBytes, dwbg7F3AReportGJSONPath) + if !report.IsArray() { + t.Fatalf("expected array, got %s", report.Raw) + } + if report.Get("#").Int() != 4 { + t.Fatalf("expected 4 items, got %d", report.Get("#").Int()) + } + + if report.Get("0.riskCode").Type != gjson.Number || report.Get("0.riskCode").Int() != 23006 { + t.Fatalf("unexpected first riskCode: %s", report.Get("0.riskCode").Raw) + } + if report.Get("0.riskCodeValue").Type != gjson.Number || report.Get("0.riskCodeValue").Int() != 16 { + t.Fatalf("unexpected first riskCodeValue: %s", report.Get("0.riskCodeValue").Raw) + } + if report.Get("2.riskCode").Type != gjson.String || report.Get("2.riskCode").String() != "41001" { + t.Fatalf("unexpected third riskCode: %s", report.Get("2.riskCode").Raw) + } + if report.Get("2.riskCodeValue").Type != gjson.String || report.Get("2.riskCodeValue").String() != "43" { + t.Fatalf("unexpected third riskCodeValue: %s", report.Get("2.riskCodeValue").Raw) + } +} + +func TestTransformDWBG7F3AResponseWrappedData(t *testing.T) { + input := map[string]interface{}{ + "data": []interface{}{ + map[string]interface{}{"riskCode": 22006, "riskCodeValue": 1}, + }, + } + + respBytes, err := transformDWBG7F3AResponse(input) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + + report := gjson.GetBytes(respBytes, dwbg7F3AReportGJSONPath) + if report.Get("#").Int() != 1 { + t.Fatalf("expected 1 item, got %d", report.Get("#").Int()) + } + if report.Get("0.riskCode").Int() != 22006 { + t.Fatalf("unexpected riskCode: %s", report.Get("0.riskCode").Raw) + } +} + +func TestTransformDWBG7F3AResponseNullData(t *testing.T) { + input := map[string]interface{}{"data": nil} + + respBytes, err := transformDWBG7F3AResponse(input) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + + var result map[string]interface{} + if err := json.Unmarshal(respBytes, &result); err != nil { + t.Fatalf("invalid json: %v", err) + } + if result[dwbg7F3AReportKey] != "-1" { + t.Fatalf("expected -1, got %#v", result[dwbg7F3AReportKey]) + } +}