This commit is contained in:
2026-07-02 14:12:51 +08:00
parent 40b50a5a5c
commit c08f40d212
3 changed files with 276 additions and 26 deletions

View File

@@ -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, &paramsDto); 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)
}

View File

@@ -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
}
}

View File

@@ -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])
}
}