f
This commit is contained in:
33
internal/domains/api/services/processors/dwbg/1.md
Normal file
33
internal/domains/api/services/processors/dwbg/1.md
Normal file
@@ -0,0 +1,33 @@
|
||||
|
|
||||
| 产品编码 | 产品名称 | 价格 |
|
||||
| :--- | :--- | :--- |
|
||||
|| mobile4Verify | 运营商状态查询 | ¥0.04 / 次 |
|
||||
|| mobileDuration | 手机入网时长 | ¥0.10 / 次 |
|
||||
|| mobile3Verify | 运营商三要素验证 | ¥0.15 / 次 |
|
||||
|| realNameAuth | 实名认证 | ¥0.02 / 次 |
|
||||
|| blackListV121_3 | 债务欺诈黑名单V3 | ¥0.22 / 次 |
|
||||
|| loanRiskTagV10 | 风险变量V10 | ¥0.38 / 次 |
|
||||
|| loanRiskTagV21 | 信用全景V21 | ¥0.30 / 次 |
|
||||
|| loanRiskTagV11 | 借贷意向查询 | ¥0.20 / 次 |
|
||||
|| loanRiskTagV12 | 特殊名单 | ¥0.00 / 次 |
|
||||
|| mobileRiskV709 | 投诉风险筛查V709 | ¥0.20 / 次 |
|
||||
|| blackListV110 | 特殊名单V110 | ¥0.20 / 次 |
|
||||
|| personalLawsuit_cv1 | 个人法院涉诉定制版 | ¥0.20 / 次 |
|
||||
|
||||
|
||||
|
||||
| 产品编码 | 产品名称 | 价格 | API接口名称 |
|
||||
| :--- | :--- | :--- | :--- |
|
||||
|| YYSYE7V5 | 手机在网状态V即时版 | ¥0.03 / 次 | /v1/mobile_status/check |
|
||||
|| YYSYP0T4 | 手机号码在网时长V即时版 | ¥0.15 / 次 | /v2/mobile_online/check |
|
||||
|| YYSYK9R4 | 全网手机三要素验证 | ¥0.16 / 次 | /communication/personal/1979 |
|
||||
|| IVYZN2P8 | 公安二要素政务版 | ¥0.02 / 次 | /v4/id_card/check |
|
||||
|| JRZQV3HM | 债务欺诈黑名单V3 | ¥0.22 / 次 | blackListV121_3 |
|
||||
|| JRZQ4B6C | 探针C | ¥0.38 / 次 | loanRiskTagV10 |
|
||||
|| JRZQ5E9F | 借选指数 | ¥0.30 / 次 | loanRiskTagV21 |
|
||||
|| JRZQ3C7B | 借贷意向验证 | ¥0.20 / 次 | loanRiskTagV11 |
|
||||
|| JRZQV7MD | 特殊名单 | ¥0.00 / 次 | loanRiskTagV12 |
|
||||
|| JRZQVT43 | 投诉风险筛查V709(投诉黑名单) | ¥0.20 / 次 | mobileRiskV709 |
|
||||
|| JRZQV0MD | 行为黑名单 | ¥0.20 / 次 | blackListV110 |
|
||||
|| FLXG7E8F | 个人司法数据查询 | ¥0.20 / 次 | personalLawsuit_cv1 |
|
||||
|
||||
174
internal/domains/api/services/processors/dwbg/dwbg9fb3.md
Normal file
174
internal/domains/api/services/processors/dwbg/dwbg9fb3.md
Normal file
@@ -0,0 +1,174 @@
|
||||
# DWBG9FB3 个人风险档案 — 响应结构说明
|
||||
|
||||
## 概述
|
||||
|
||||
`DWBG9FB3`(个人风险档案)本身是一个独立接口,接收三要素入参后,**并发**调用 12 个子产品处理器,将各子接口原始返回数据**直接拼接融合**为一个 JSON 对象返回。
|
||||
|
||||
- 不使用 `success` / `data` / `error` 等包装结构
|
||||
- 顶层 key 为简短**英文单词**字段名
|
||||
- 每个大字段的 value 即为对应子处理器的原始返回对象
|
||||
- 子产品调用失败时,该字段值为 `null`,不影响其他字段
|
||||
|
||||
## 字段映射表
|
||||
|
||||
| 产品编码 | 产品名称 | 英文字段名 | 子处理器 |
|
||||
| :--- | :--- | :--- | :--- |
|
||||
| YYSYE7V5 | 手机在网状态V即时版 | `presence` | `ProcessYYSYE7V5Request` |
|
||||
| YYSYP0T4 | 手机号码在网时长V即时版 | `duration` | `ProcessYYSYP0T4Request` |
|
||||
| YYSYK9R4 | 全网手机三要素验证 | `triple` | `ProcessYYSYK9R4Request` |
|
||||
| IVYZN2P8 | 公安二要素政务版 | `identity` | `ProcessIVYZN2P8Request` |
|
||||
| JRZQV3HM | 债务欺诈黑名单V3 | `fraud` | `ProcessJRZQV3HMRequest` |
|
||||
| JRZQ4B6C | 探针C | `probe` | `ProcessJRZQ4B6CRequest` |
|
||||
| JRZQ5E9F | 借选指数 | `rating` | `ProcessJRZQ5E9FRequest` |
|
||||
| JRZQ3C7B | 借贷意向验证 | `intent` | `ProcessJRZQ3C7BRequest` |
|
||||
| JRZQV7MD | 特殊名单 | `special` | `ProcessJRZQV7MDRequest` |
|
||||
| JRZQVT43 | 投诉风险筛查V709 | `complaint` | `ProcessJRZQVT43Request` |
|
||||
| JRZQV0MD | 行为黑名单 | `behavior` | `ProcessJRZQV0MDRequest` |
|
||||
| FLXG7E8F | 个人司法数据查询 | `judicial` | `ProcessFLXG7E8FRequest` |
|
||||
|
||||
## 请求参数
|
||||
|
||||
```json
|
||||
{
|
||||
"id_card": "110101199001011234",
|
||||
"name": "张三",
|
||||
"mobile_no": "13800138000"
|
||||
}
|
||||
```
|
||||
|
||||
## 响应结构
|
||||
|
||||
顶层为一个扁平对象,12 个字段并列,每个字段 value 为子处理器原始返回的 JSON 对象:
|
||||
|
||||
```json
|
||||
{
|
||||
"presence": { },
|
||||
"duration": { },
|
||||
"triple": { },
|
||||
"identity": { },
|
||||
"fraud": { },
|
||||
"probe": { },
|
||||
"rating": { },
|
||||
"intent": { },
|
||||
"special": { },
|
||||
"complaint": { },
|
||||
"behavior": { },
|
||||
"judicial": { }
|
||||
}
|
||||
```
|
||||
|
||||
## 响应示例
|
||||
|
||||
```json
|
||||
{
|
||||
"presence": {
|
||||
"status": "1",
|
||||
"operator": "1"
|
||||
},
|
||||
"duration": {
|
||||
"result": "3",
|
||||
"desc": "在网时长12-24个月"
|
||||
},
|
||||
"triple": {
|
||||
"state": "1",
|
||||
"operator": "1"
|
||||
},
|
||||
"identity": {
|
||||
"result": 0,
|
||||
"desc": "一致",
|
||||
"sex": "男",
|
||||
"birthday": "1990-01-01",
|
||||
"address": "北京市东城区"
|
||||
},
|
||||
"fraud": {
|
||||
"hit": 0
|
||||
},
|
||||
"probe": {
|
||||
"score": 650,
|
||||
"risk_level": "B"
|
||||
},
|
||||
"rating": {
|
||||
"score": 720,
|
||||
"level": "A"
|
||||
},
|
||||
"intent": {
|
||||
"apply_loan": {
|
||||
"d7": { "id": 0, "cell": 1 },
|
||||
"m1": { "id": 1, "cell": 2 }
|
||||
}
|
||||
},
|
||||
"special": {
|
||||
"hit": 0
|
||||
},
|
||||
"complaint": {
|
||||
"hit": 0
|
||||
},
|
||||
"behavior": {
|
||||
"hit": 0
|
||||
},
|
||||
"judicial": {
|
||||
"judicial_data": {
|
||||
"lawsuitStat": {
|
||||
"count_total": 0,
|
||||
"count_jie_total": 0,
|
||||
"count_wei_total": 0
|
||||
},
|
||||
"breachCaseList": [],
|
||||
"consumptionRestrictionList": []
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 部分失败示例
|
||||
|
||||
某个子产品查无记录或异常时,对应字段为 `null`,其余字段正常返回:
|
||||
|
||||
```json
|
||||
{
|
||||
"presence": {
|
||||
"status": "1",
|
||||
"operator": "1"
|
||||
},
|
||||
"judicial": null
|
||||
}
|
||||
```
|
||||
|
||||
## 调用流程
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
A[DWBG9FB3 请求] --> B[参数校验]
|
||||
B --> C[并发调用 12 个子处理器]
|
||||
C --> D1[presence]
|
||||
C --> D2[duration]
|
||||
C --> D3[triple]
|
||||
C --> D4[identity]
|
||||
C --> D5[fraud]
|
||||
C --> D6[probe]
|
||||
C --> D7[rating]
|
||||
C --> D8[intent]
|
||||
C --> D9[special]
|
||||
C --> D10[complaint]
|
||||
C --> D11[behavior]
|
||||
C --> D12[judicial]
|
||||
D1 --> E[拼接融合为一个对象]
|
||||
D2 --> E
|
||||
D3 --> E
|
||||
D4 --> E
|
||||
D5 --> E
|
||||
D6 --> E
|
||||
D7 --> E
|
||||
D8 --> E
|
||||
D9 --> E
|
||||
D10 --> E
|
||||
D11 --> E
|
||||
D12 --> E
|
||||
E --> F[返回 JSON]
|
||||
```
|
||||
|
||||
## 实现说明
|
||||
|
||||
- 复用 `dwbg8b4d` 中的 `callProcessor`,通过 `CombService.GetProcessor` 按产品编码路由。
|
||||
- 12 个 goroutine 并发执行,结果写入 `map[英文字段名]子处理器原始数据`。
|
||||
- 子产品数据保持各处理器原有返回结构,不做二次转换。
|
||||
@@ -4,13 +4,34 @@ import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"sync"
|
||||
|
||||
"tyapi-server/internal/domains/api/dto"
|
||||
"tyapi-server/internal/domains/api/services/processors"
|
||||
"tyapi-server/internal/infrastructure/external/nuoer"
|
||||
"tyapi-server/internal/shared/logger"
|
||||
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
// dwbg9FB3FieldNames 子产品编码 → 响应字段名(单词缩写)
|
||||
var dwbg9FB3FieldNames = map[string]string{
|
||||
"YYSYE7V5": "presence", // 在网状态
|
||||
"YYSYP0T4": "duration", // 在网时长
|
||||
"YYSYK9R4": "triple", // 三要素验证
|
||||
"IVYZN2P8": "identity", // 二要素认证
|
||||
"JRZQV3HM": "fraud", // 债务欺诈黑名单
|
||||
"JRZQ4B6C": "probe", // 探针C
|
||||
"JRZQ5E9F": "rating", // 借选指数
|
||||
"JRZQ3C7B": "intent", // 借贷意向
|
||||
"JRZQV7MD": "special", // 特殊名单
|
||||
"JRZQVT43": "complaint", // 投诉风险
|
||||
"JRZQV0MD": "behavior", // 行为黑名单
|
||||
"FLXG7E8F": "judicial", // 司法数据
|
||||
}
|
||||
|
||||
// ProcessDWBG9FB3Request DWBG9FB3 API处理方法 - 个人风险档案
|
||||
// 并发调用子产品处理器,将各子接口返回数据以大数据英文字段名拼接融合为一个对象
|
||||
func ProcessDWBG9FB3Request(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) {
|
||||
var paramsDto dto.DWBG9FB3Req
|
||||
if err := json.Unmarshal(params, ¶msDto); err != nil {
|
||||
@@ -21,30 +42,193 @@ func ProcessDWBG9FB3Request(ctx context.Context, params []byte, deps *processors
|
||||
return nil, errors.Join(processors.ErrInvalidParam, err)
|
||||
}
|
||||
|
||||
body := map[string]string{
|
||||
"idCard": paramsDto.IDCard,
|
||||
"name": paramsDto.Name,
|
||||
"mobile": paramsDto.MobileNo,
|
||||
}
|
||||
log := logger.GetGlobalLogger()
|
||||
log.Info("开始处理个人风险档案请求",
|
||||
zap.String("name", paramsDto.Name),
|
||||
zap.String("id_card", maskIDCard(paramsDto.IDCard)),
|
||||
zap.String("mobile_no", maskMobile(paramsDto.MobileNo)),
|
||||
)
|
||||
|
||||
nuoerDoCheckAPIKey := "gamaReportPageP01"
|
||||
ApiPath := "/v1/doCheck"
|
||||
result := collectDWBG9FB3SubProducts(ctx, paramsDto, deps, log)
|
||||
|
||||
resp, err := deps.NuoerService.CallAPI(ctx, nuoerDoCheckAPIKey, ApiPath, body)
|
||||
if err != nil {
|
||||
if errors.Is(err, nuoer.ErrNotFound) {
|
||||
return nil, errors.Join(processors.ErrNotFound, err)
|
||||
}
|
||||
if errors.Is(err, nuoer.ErrDatasource) {
|
||||
return nil, errors.Join(processors.ErrDatasource, err)
|
||||
}
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
|
||||
respBytes, err := json.Marshal(resp.Data)
|
||||
respBytes, err := json.Marshal(result)
|
||||
if err != nil {
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
|
||||
log.Info("个人风险档案处理完成", zap.Int("field_count", len(result)))
|
||||
return respBytes, nil
|
||||
}
|
||||
|
||||
type dwbg9fb3APICall struct {
|
||||
apiCode string
|
||||
fieldName string
|
||||
params map[string]interface{}
|
||||
}
|
||||
|
||||
func collectDWBG9FB3SubProducts(
|
||||
ctx context.Context,
|
||||
params dto.DWBG9FB3Req,
|
||||
deps *processors.ProcessorDependencies,
|
||||
log *zap.Logger,
|
||||
) map[string]interface{} {
|
||||
apiCalls := []dwbg9fb3APICall{
|
||||
{apiCode: "YYSYE7V5", fieldName: dwbg9FB3FieldNames["YYSYE7V5"], params: map[string]interface{}{"mobile_no": params.MobileNo}},
|
||||
{apiCode: "YYSYP0T4", fieldName: dwbg9FB3FieldNames["YYSYP0T4"], params: map[string]interface{}{"mobile_no": params.MobileNo}},
|
||||
{
|
||||
apiCode: "YYSYK9R4",
|
||||
fieldName: dwbg9FB3FieldNames["YYSYK9R4"],
|
||||
params: map[string]interface{}{
|
||||
"mobile_no": params.MobileNo,
|
||||
"id_card": params.IDCard,
|
||||
"name": params.Name,
|
||||
},
|
||||
},
|
||||
{
|
||||
apiCode: "IVYZN2P8",
|
||||
fieldName: dwbg9FB3FieldNames["IVYZN2P8"],
|
||||
params: map[string]interface{}{
|
||||
"id_card": params.IDCard,
|
||||
"name": params.Name,
|
||||
},
|
||||
},
|
||||
{
|
||||
apiCode: "JRZQV3HM",
|
||||
fieldName: dwbg9FB3FieldNames["JRZQV3HM"],
|
||||
params: map[string]interface{}{
|
||||
"id_card": params.IDCard,
|
||||
"name": params.Name,
|
||||
"mobile_no": params.MobileNo,
|
||||
},
|
||||
},
|
||||
{
|
||||
apiCode: "JRZQ4B6C",
|
||||
fieldName: dwbg9FB3FieldNames["JRZQ4B6C"],
|
||||
params: map[string]interface{}{
|
||||
"mobile_no": params.MobileNo,
|
||||
"id_card": params.IDCard,
|
||||
"name": params.Name,
|
||||
"authorized": "1",
|
||||
},
|
||||
},
|
||||
{
|
||||
apiCode: "JRZQ5E9F",
|
||||
fieldName: dwbg9FB3FieldNames["JRZQ5E9F"],
|
||||
params: map[string]interface{}{
|
||||
"mobile_no": params.MobileNo,
|
||||
"id_card": params.IDCard,
|
||||
"name": params.Name,
|
||||
"authorized": "1",
|
||||
},
|
||||
},
|
||||
{
|
||||
apiCode: "JRZQ3C7B",
|
||||
fieldName: dwbg9FB3FieldNames["JRZQ3C7B"],
|
||||
params: map[string]interface{}{
|
||||
"mobile_no": params.MobileNo,
|
||||
"id_card": params.IDCard,
|
||||
"name": params.Name,
|
||||
"authorized": "1",
|
||||
},
|
||||
},
|
||||
{
|
||||
apiCode: "JRZQV7MD",
|
||||
fieldName: dwbg9FB3FieldNames["JRZQV7MD"],
|
||||
params: map[string]interface{}{
|
||||
"id_card": params.IDCard,
|
||||
"name": params.Name,
|
||||
"mobile_no": params.MobileNo,
|
||||
},
|
||||
},
|
||||
{
|
||||
apiCode: "JRZQVT43",
|
||||
fieldName: dwbg9FB3FieldNames["JRZQVT43"],
|
||||
params: map[string]interface{}{
|
||||
"id_card": params.IDCard,
|
||||
"name": params.Name,
|
||||
"mobile_no": params.MobileNo,
|
||||
},
|
||||
},
|
||||
{
|
||||
apiCode: "JRZQV0MD",
|
||||
fieldName: dwbg9FB3FieldNames["JRZQV0MD"],
|
||||
params: map[string]interface{}{
|
||||
"id_card": params.IDCard,
|
||||
"name": params.Name,
|
||||
"mobile_no": params.MobileNo,
|
||||
},
|
||||
},
|
||||
{
|
||||
apiCode: "FLXG7E8F",
|
||||
fieldName: dwbg9FB3FieldNames["FLXG7E8F"],
|
||||
params: map[string]interface{}{
|
||||
"name": params.Name,
|
||||
"id_card": params.IDCard,
|
||||
"mobile_no": params.MobileNo,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
type callResult struct {
|
||||
fieldName string
|
||||
data interface{}
|
||||
err error
|
||||
}
|
||||
|
||||
results := make(chan callResult, len(apiCalls))
|
||||
var wg sync.WaitGroup
|
||||
|
||||
for _, apiCall := range apiCalls {
|
||||
wg.Add(1)
|
||||
go func(ac dwbg9fb3APICall) {
|
||||
defer wg.Done()
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
log.Error("调用子产品处理器时发生panic",
|
||||
zap.String("api_code", ac.apiCode),
|
||||
zap.String("field_name", ac.fieldName),
|
||||
zap.Any("panic", r),
|
||||
)
|
||||
results <- callResult{ac.fieldName, nil, fmt.Errorf("处理器panic: %v", r)}
|
||||
}
|
||||
}()
|
||||
|
||||
paramsBytes, err := json.Marshal(ac.params)
|
||||
if err != nil {
|
||||
results <- callResult{ac.fieldName, nil, err}
|
||||
return
|
||||
}
|
||||
|
||||
data, err := callProcessor(ctx, ac.apiCode, paramsBytes, deps)
|
||||
results <- callResult{ac.fieldName, data, err}
|
||||
}(apiCall)
|
||||
}
|
||||
|
||||
go func() {
|
||||
wg.Wait()
|
||||
close(results)
|
||||
}()
|
||||
|
||||
output := make(map[string]interface{}, len(apiCalls))
|
||||
successCount := 0
|
||||
for result := range results {
|
||||
if result.err != nil {
|
||||
log.Warn("子产品调用失败,该字段置空",
|
||||
zap.String("field_name", result.fieldName),
|
||||
zap.Error(result.err),
|
||||
)
|
||||
output[result.fieldName] = nil
|
||||
continue
|
||||
}
|
||||
output[result.fieldName] = result.data
|
||||
successCount++
|
||||
}
|
||||
|
||||
log.Info("子产品调用完成",
|
||||
zap.Int("total", len(apiCalls)),
|
||||
zap.Int("success", successCount),
|
||||
zap.Int("failed", len(apiCalls)-successCount),
|
||||
)
|
||||
|
||||
return output
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user