f
This commit is contained in:
@@ -7,10 +7,10 @@ import (
|
|||||||
|
|
||||||
"tyapi-server/internal/domains/api/dto"
|
"tyapi-server/internal/domains/api/dto"
|
||||||
"tyapi-server/internal/domains/api/services/processors"
|
"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) {
|
func ProcessDWBG7F3ARequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) {
|
||||||
var paramsDto dto.DWBG7F3AReq
|
var paramsDto dto.DWBG7F3AReq
|
||||||
if err := json.Unmarshal(params, ¶msDto); err != nil {
|
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)
|
return nil, errors.Join(processors.ErrInvalidParam, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 构建请求数据,使用xingwei服务的正确字段名
|
encryptedName, err := deps.ZhichaService.Encrypt(paramsDto.Name)
|
||||||
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)
|
|
||||||
if err != nil {
|
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)
|
return nil, errors.Join(processors.ErrSystem, err)
|
||||||
} else {
|
|
||||||
// 其他未知错误
|
|
||||||
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)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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])
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user