f
This commit is contained in:
@@ -9,24 +9,24 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"hyapi-server/internal/application/certification/dto/commands"
|
||||
"hyapi-server/internal/application/certification/dto/queries"
|
||||
"hyapi-server/internal/application/certification/dto/responses"
|
||||
"hyapi-server/internal/config"
|
||||
api_service "hyapi-server/internal/domains/api/services"
|
||||
"hyapi-server/internal/domains/certification/entities"
|
||||
certification_value_objects "hyapi-server/internal/domains/certification/entities/value_objects"
|
||||
"hyapi-server/internal/domains/certification/enums"
|
||||
"hyapi-server/internal/domains/certification/repositories"
|
||||
"hyapi-server/internal/domains/certification/services"
|
||||
finance_service "hyapi-server/internal/domains/finance/services"
|
||||
user_entities "hyapi-server/internal/domains/user/entities"
|
||||
user_service "hyapi-server/internal/domains/user/services"
|
||||
"hyapi-server/internal/infrastructure/external/notification"
|
||||
"hyapi-server/internal/infrastructure/external/storage"
|
||||
"hyapi-server/internal/shared/database"
|
||||
"hyapi-server/internal/shared/esign"
|
||||
sharedOCR "hyapi-server/internal/shared/ocr"
|
||||
"tyapi-server/internal/application/certification/dto/commands"
|
||||
"tyapi-server/internal/application/certification/dto/queries"
|
||||
"tyapi-server/internal/application/certification/dto/responses"
|
||||
"tyapi-server/internal/config"
|
||||
api_service "tyapi-server/internal/domains/api/services"
|
||||
"tyapi-server/internal/domains/certification/entities"
|
||||
certification_value_objects "tyapi-server/internal/domains/certification/entities/value_objects"
|
||||
"tyapi-server/internal/domains/certification/enums"
|
||||
"tyapi-server/internal/domains/certification/repositories"
|
||||
"tyapi-server/internal/domains/certification/services"
|
||||
finance_service "tyapi-server/internal/domains/finance/services"
|
||||
user_entities "tyapi-server/internal/domains/user/entities"
|
||||
user_service "tyapi-server/internal/domains/user/services"
|
||||
"tyapi-server/internal/infrastructure/external/notification"
|
||||
"tyapi-server/internal/infrastructure/external/storage"
|
||||
"tyapi-server/internal/shared/database"
|
||||
"tyapi-server/internal/shared/esign"
|
||||
sharedOCR "tyapi-server/internal/shared/ocr"
|
||||
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
package flxg
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
|
||||
"tyapi-server/internal/domains/api/dto"
|
||||
"tyapi-server/internal/domains/api/services/processors"
|
||||
"tyapi-server/internal/infrastructure/external/zhicha"
|
||||
)
|
||||
|
||||
// ProcessFLXG5A3BCOPYRequest FLXG5A3B COPY API处理方法 - 个人司法涉诉
|
||||
func ProcessFLXG5A3BCOPYRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) {
|
||||
var paramsDto dto.FLXG5A3BReq
|
||||
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)
|
||||
}
|
||||
if paramsDto.IDCard == "350681198611130611" || paramsDto.IDCard == "622301200006250550" || paramsDto.IDCard == "320682198910134998" || paramsDto.IDCard == "640102198708020925" || paramsDto.IDCard == "420624197310234034" || paramsDto.IDCard == "350104198501184416" || paramsDto.IDCard == "410521198606018056" || paramsDto.IDCard == "410482198504029333" || paramsDto.IDCard == "370982199012037272" || paramsDto.IDCard == "431027198810290730" || paramsDto.IDCard == "362502199510298017" || paramsDto.IDCard == "340826199008250378" || paramsDto.IDCard == "321027198304072129" || paramsDto.IDCard == "420116198907031413" || paramsDto.IDCard == "13032319930128263X" {
|
||||
return nil, errors.Join(processors.ErrNotFound, errors.New("查询为空"))
|
||||
}
|
||||
|
||||
encryptedName, err := deps.ZhichaService.Encrypt(paramsDto.Name)
|
||||
if err != nil {
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
|
||||
encryptedIDCard, err := deps.ZhichaService.Encrypt(paramsDto.IDCard)
|
||||
if err != nil {
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
|
||||
reqData := map[string]interface{}{
|
||||
"name": encryptedName,
|
||||
"idCard": encryptedIDCard,
|
||||
"authorized": paramsDto.Authorized,
|
||||
}
|
||||
|
||||
respData, err := deps.ZhichaService.CallAPI(ctx, "ZCI006", reqData)
|
||||
if err != nil {
|
||||
if errors.Is(err, zhicha.ErrDatasource) {
|
||||
return nil, errors.Join(processors.ErrDatasource, err)
|
||||
} else {
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
}
|
||||
|
||||
// 将响应数据转换为JSON字节
|
||||
respBytes, err := json.Marshal(respData)
|
||||
if err != nil {
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
|
||||
return respBytes, nil
|
||||
}
|
||||
@@ -7,7 +7,7 @@ import (
|
||||
|
||||
"tyapi-server/internal/domains/api/dto"
|
||||
"tyapi-server/internal/domains/api/services/processors"
|
||||
"tyapi-server/internal/infrastructure/external/zhicha"
|
||||
"tyapi-server/internal/infrastructure/external/nuoer"
|
||||
)
|
||||
|
||||
// ProcessFLXG5A3BRequest FLXG5A3B API处理方法 - 个人司法涉诉
|
||||
@@ -24,33 +24,33 @@ func ProcessFLXG5A3BRequest(ctx context.Context, params []byte, deps *processors
|
||||
return nil, errors.Join(processors.ErrNotFound, errors.New("查询为空"))
|
||||
}
|
||||
|
||||
encryptedName, err := deps.ZhichaService.Encrypt(paramsDto.Name)
|
||||
if err != nil {
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
body := map[string]string{
|
||||
"name": paramsDto.Name,
|
||||
"idCard": paramsDto.IDCard,
|
||||
}
|
||||
|
||||
encryptedIDCard, err := deps.ZhichaService.Encrypt(paramsDto.IDCard)
|
||||
if err != nil {
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
nuoerDoCheckAPIKey := "personalLawsuit_cv1"
|
||||
ApiPath := "/v1/doCheck"
|
||||
|
||||
reqData := map[string]interface{}{
|
||||
"name": encryptedName,
|
||||
"idCard": encryptedIDCard,
|
||||
"authorized": paramsDto.Authorized,
|
||||
}
|
||||
|
||||
respData, err := deps.ZhichaService.CallAPI(ctx, "ZCI006", reqData)
|
||||
resp, err := deps.NuoerService.CallAPI(ctx, nuoerDoCheckAPIKey, ApiPath, body)
|
||||
if err != nil {
|
||||
if errors.Is(err, zhicha.ErrDatasource) {
|
||||
if errors.Is(err, nuoer.ErrDatasource) {
|
||||
return nil, errors.Join(processors.ErrDatasource, err)
|
||||
} else {
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
if errors.Is(err, nuoer.ErrNotFound) {
|
||||
return nil, errors.Join(processors.ErrNotFound, err)
|
||||
}
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
|
||||
// 将响应数据转换为JSON字节
|
||||
respBytes, err := json.Marshal(respData)
|
||||
rawData, ok := resp.Data.(map[string]interface{})
|
||||
if !ok {
|
||||
return nil, errors.Join(processors.ErrSystem, errors.New("响应格式错误"))
|
||||
}
|
||||
|
||||
result := mapNuoerPersonalLawsuitToResponse(rawData)
|
||||
|
||||
respBytes, err := json.Marshal(result)
|
||||
if err != nil {
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,177 @@
|
||||
package flxg
|
||||
|
||||
// mapNuoerPersonalLawsuitToResponse 将 nuoer 响应转为对外结构(2.md):
|
||||
// lawsuitStat -> entout, breachCaseList -> sxbzxr, consumptionRestrictionList -> xgbzxr
|
||||
func mapNuoerPersonalLawsuitToResponse(data map[string]interface{}) map[string]interface{} {
|
||||
if data == nil {
|
||||
return defaultFLXG5A3BResponse()
|
||||
}
|
||||
if _, hasEntout := data["entout"]; hasEntout {
|
||||
return data
|
||||
}
|
||||
|
||||
flat := unwrapNuoerPersonalLawsuitData(data)
|
||||
return map[string]interface{}{
|
||||
"sxbzxr": asSlice(flat["breachCaseList"]),
|
||||
"xgbzxr": asSlice(flat["consumptionRestrictionList"]),
|
||||
"entout": pickEntout(flat["lawsuitStat"]),
|
||||
}
|
||||
}
|
||||
|
||||
func defaultFLXG5A3BResponse() map[string]interface{} {
|
||||
return map[string]interface{}{
|
||||
"sxbzxr": []interface{}{},
|
||||
"entout": map[string]interface{}{},
|
||||
"xgbzxr": []interface{}{},
|
||||
}
|
||||
}
|
||||
|
||||
func pickEntout(v interface{}) interface{} {
|
||||
if v == nil {
|
||||
return map[string]interface{}{}
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
// unwrapNuoerPersonalLawsuitData 解包 nuoer 嵌套结构 data.result.detail[],提取 1.md 平铺字段。
|
||||
func unwrapNuoerPersonalLawsuitData(data map[string]interface{}) map[string]interface{} {
|
||||
if _, ok := data["lawsuitStat"]; ok {
|
||||
return data
|
||||
}
|
||||
if result, ok := data["result"].(map[string]interface{}); ok {
|
||||
for _, item := range asSlice(result["detail"]) {
|
||||
if flat := extractFromNuoerDetailItem(asMap(item)); len(flat) > 0 {
|
||||
return flat
|
||||
}
|
||||
}
|
||||
}
|
||||
return data
|
||||
}
|
||||
|
||||
func extractFromNuoerDetailItem(item map[string]interface{}) map[string]interface{} {
|
||||
if len(item) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
lawsuitStat := extractLawsuitStatFromDetailItem(item)
|
||||
if !isLawsuitStatPayload(asMap(lawsuitStat)) {
|
||||
return nil
|
||||
}
|
||||
|
||||
return map[string]interface{}{
|
||||
"lawsuitStat": lawsuitStat,
|
||||
"breachCaseList": extractBreachCaseRecords(item),
|
||||
"consumptionRestrictionList": extractConsumptionRestrictionRecords(item),
|
||||
}
|
||||
}
|
||||
|
||||
func extractLawsuitStatFromDetailItem(item map[string]interface{}) interface{} {
|
||||
// nuoer 真实涉诉数据通常在 breachCaseList/consumptionRestrictionList 的包装对象内
|
||||
for _, v := range asSlice(item["breachCaseList"]) {
|
||||
if m := asMap(v); m != nil {
|
||||
if ls := asMap(m["lawsuitStat"]); isLawsuitStatPayload(ls) {
|
||||
return ls
|
||||
}
|
||||
}
|
||||
}
|
||||
for _, v := range asSlice(item["consumptionRestrictionList"]) {
|
||||
if m := asMap(v); m != nil {
|
||||
if ls := asMap(m["lawsuitStat"]); isLawsuitStatPayload(ls) {
|
||||
return ls
|
||||
}
|
||||
}
|
||||
}
|
||||
if lsWrap := asMap(item["lawsuitStat"]); lsWrap != nil {
|
||||
if ls := extractLawsuitStatFromWrapper(lsWrap); ls != nil {
|
||||
return ls
|
||||
}
|
||||
}
|
||||
return map[string]interface{}{}
|
||||
}
|
||||
|
||||
func extractLawsuitStatFromWrapper(wrap map[string]interface{}) map[string]interface{} {
|
||||
if isLawsuitStatPayload(wrap) {
|
||||
return wrap
|
||||
}
|
||||
for _, v := range asSlice(wrap["detail"]) {
|
||||
if m := asMap(v); m != nil {
|
||||
if ls := asMap(m["lawsuitStat"]); isLawsuitStatPayload(ls) {
|
||||
return ls
|
||||
}
|
||||
if isLawsuitStatPayload(m) {
|
||||
return m
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func isLawsuitStatPayload(m map[string]interface{}) bool {
|
||||
if len(m) == 0 {
|
||||
return false
|
||||
}
|
||||
for _, k := range []string{"criminal", "civil", "administrative", "cases_tree", "count", "crc", "implement", "preservation", "bankrupt"} {
|
||||
if _, ok := m[k]; ok {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func extractBreachCaseRecords(item map[string]interface{}) []interface{} {
|
||||
out := make([]interface{}, 0)
|
||||
collectBreachCaseRecords(asSlice(item["breachCaseList"]), &out)
|
||||
if lsWrap := asMap(item["lawsuitStat"]); lsWrap != nil {
|
||||
for _, v := range asSlice(lsWrap["detail"]) {
|
||||
collectBreachCaseRecords(asSlice(asMap(v)["breachCaseList"]), &out)
|
||||
}
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
func collectBreachCaseRecords(list []interface{}, out *[]interface{}) {
|
||||
for _, v := range list {
|
||||
m := asMap(v)
|
||||
if len(m) == 0 {
|
||||
continue
|
||||
}
|
||||
if _, isWrapper := m["lawsuitStat"]; isWrapper {
|
||||
if inner := asSlice(m["breachCaseList"]); len(inner) > 0 {
|
||||
collectBreachCaseRecords(inner, out)
|
||||
}
|
||||
continue
|
||||
}
|
||||
if _, hasAh := m["ah"]; hasAh {
|
||||
*out = append(*out, m)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func extractConsumptionRestrictionRecords(item map[string]interface{}) []interface{} {
|
||||
out := make([]interface{}, 0)
|
||||
collectConsumptionRestrictionRecords(asSlice(item["consumptionRestrictionList"]), &out)
|
||||
if lsWrap := asMap(item["lawsuitStat"]); lsWrap != nil {
|
||||
for _, v := range asSlice(lsWrap["detail"]) {
|
||||
collectConsumptionRestrictionRecords(asSlice(asMap(v)["consumptionRestrictionList"]), &out)
|
||||
}
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
func collectConsumptionRestrictionRecords(list []interface{}, out *[]interface{}) {
|
||||
for _, v := range list {
|
||||
m := asMap(v)
|
||||
if len(m) == 0 {
|
||||
continue
|
||||
}
|
||||
if _, isWrapper := m["lawsuitStat"]; isWrapper {
|
||||
if inner := asSlice(m["consumptionRestrictionList"]); len(inner) > 0 {
|
||||
collectConsumptionRestrictionRecords(inner, out)
|
||||
}
|
||||
continue
|
||||
}
|
||||
if _, hasAh := m["ah"]; hasAh {
|
||||
*out = append(*out, m)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -7,7 +7,7 @@ import (
|
||||
|
||||
"tyapi-server/internal/domains/api/dto"
|
||||
"tyapi-server/internal/domains/api/services/processors"
|
||||
"tyapi-server/internal/infrastructure/external/zhicha"
|
||||
"tyapi-server/internal/infrastructure/external/nuoer"
|
||||
)
|
||||
|
||||
// ProcessFLXGDEA9Request FLXGDEA9 API处理方法
|
||||
@@ -21,34 +21,36 @@ func ProcessFLXGDEA9Request(ctx context.Context, params []byte, deps *processors
|
||||
return nil, errors.Join(processors.ErrInvalidParam, err)
|
||||
}
|
||||
|
||||
encryptedName, err := deps.ZhichaService.Encrypt(paramsDto.Name)
|
||||
if err != nil {
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
if paramsDto.IDCard == "350681198611130611" || paramsDto.IDCard == "622301200006250550" || paramsDto.IDCard == "320682198910134998" || paramsDto.IDCard == "640102198708020925" || paramsDto.IDCard == "420624197310234034" || paramsDto.IDCard == "350104198501184416" || paramsDto.IDCard == "410521198606018056" || paramsDto.IDCard == "410482198504029333" || paramsDto.IDCard == "370982199012037272" || paramsDto.IDCard == "431027198810290730" || paramsDto.IDCard == "362502199510298017" || paramsDto.IDCard == "340826199008250378" || paramsDto.IDCard == "321027198304072129" || paramsDto.IDCard == "420116198907031413" || paramsDto.IDCard == "13032319930128263X" {
|
||||
return nil, errors.Join(processors.ErrNotFound, errors.New("查询为空"))
|
||||
}
|
||||
encryptedIDCard, err := deps.ZhichaService.Encrypt(paramsDto.IDCard)
|
||||
body := map[string]string{
|
||||
"name": paramsDto.Name,
|
||||
"idCard": paramsDto.IDCard,
|
||||
}
|
||||
|
||||
nuoerDoCheckAPIKey := "idRiskTagV106"
|
||||
ApiPath := "/v1/doCheck"
|
||||
|
||||
resp, err := deps.NuoerService.CallAPI(ctx, nuoerDoCheckAPIKey, ApiPath, body)
|
||||
if err != nil {
|
||||
if errors.Is(err, nuoer.ErrDatasource) {
|
||||
return nil, errors.Join(processors.ErrDatasource, err)
|
||||
}
|
||||
if errors.Is(err, nuoer.ErrNotFound) {
|
||||
return nil, errors.Join(processors.ErrNotFound, err)
|
||||
}
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
reqData := map[string]interface{}{
|
||||
"name": encryptedName,
|
||||
"idCard": encryptedIDCard,
|
||||
"authorized": paramsDto.Authorized,
|
||||
|
||||
rawData, ok := resp.Data.(map[string]interface{})
|
||||
if !ok {
|
||||
return nil, errors.Join(processors.ErrSystem, errors.New("响应格式错误"))
|
||||
}
|
||||
|
||||
respData, err := deps.ZhichaService.CallAPI(ctx, "ZCI005", reqData)
|
||||
if err != nil {
|
||||
if errors.Is(err, zhicha.ErrDatasource) {
|
||||
return nil, errors.Join(processors.ErrDatasource, err)
|
||||
} else {
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
}
|
||||
result := mapNuoerIdRiskToResponse(rawData)
|
||||
|
||||
// 将响应数据转换为JSON字节
|
||||
respBytes, err := json.Marshal(respData)
|
||||
respBytes, err := json.Marshal(result)
|
||||
if err != nil {
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,154 @@
|
||||
package flxg
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// riskCode 位序(从左至右 1-25)到 level 代码映射,见 2.md / 1.md。
|
||||
var riskCodeBitLevelMappings = map[int]string{
|
||||
1: "A",
|
||||
2: "B2",
|
||||
3: "B",
|
||||
4: "B",
|
||||
5: "B4",
|
||||
6: "B3",
|
||||
7: "B3",
|
||||
8: "B3",
|
||||
9: "B3",
|
||||
10: "B3",
|
||||
11: "A",
|
||||
12: "B",
|
||||
13: "J",
|
||||
14: "C3",
|
||||
15: "C3",
|
||||
16: "A",
|
||||
17: "D",
|
||||
18: "D4",
|
||||
19: "D2",
|
||||
20: "D",
|
||||
21: "E",
|
||||
22: "E",
|
||||
23: "E",
|
||||
24: "E",
|
||||
}
|
||||
|
||||
// mapNuoerIdRiskToResponse 将 nuoer 响应(2json.md)转为对外结构(1json.md):
|
||||
// 解包 result,将 riskCode 转为 level。
|
||||
func mapNuoerIdRiskToResponse(data map[string]interface{}) map[string]interface{} {
|
||||
if data == nil {
|
||||
return map[string]interface{}{"level": "0"}
|
||||
}
|
||||
if level, ok := data["level"]; ok && level != nil {
|
||||
if s := strings.TrimSpace(stringifyRiskCodeVal(level)); s != "" {
|
||||
return map[string]interface{}{"level": s}
|
||||
}
|
||||
}
|
||||
|
||||
payload := unwrapNuoerIdRiskData(data)
|
||||
riskCode := strings.TrimSpace(stringifyRiskCodeVal(payload["riskCode"]))
|
||||
return map[string]interface{}{
|
||||
"level": mapRiskCodeToLevel(riskCode),
|
||||
}
|
||||
}
|
||||
|
||||
func unwrapNuoerIdRiskData(data map[string]interface{}) map[string]interface{} {
|
||||
if _, ok := data["riskCode"]; ok {
|
||||
return data
|
||||
}
|
||||
if result, ok := data["result"].(map[string]interface{}); ok {
|
||||
return result
|
||||
}
|
||||
return data
|
||||
}
|
||||
|
||||
func mapRiskCodeToLevel(riskCode string) string {
|
||||
if riskCode == "" {
|
||||
return "0"
|
||||
}
|
||||
|
||||
codes := make([]string, 0, 8)
|
||||
for i, ch := range riskCode {
|
||||
if ch != '1' {
|
||||
continue
|
||||
}
|
||||
pos := i + 1
|
||||
if pos == 25 {
|
||||
continue
|
||||
}
|
||||
if code, ok := riskCodeBitLevelMappings[pos]; ok && code != "" {
|
||||
codes = append(codes, code)
|
||||
}
|
||||
}
|
||||
|
||||
codes = dedupeLevelCodes(codes)
|
||||
codes = collapseParentLevelCodes(codes)
|
||||
if len(codes) == 0 {
|
||||
return "0"
|
||||
}
|
||||
return strings.Join(codes, ",")
|
||||
}
|
||||
|
||||
func dedupeLevelCodes(codes []string) []string {
|
||||
if len(codes) == 0 {
|
||||
return codes
|
||||
}
|
||||
seen := make(map[string]struct{}, len(codes))
|
||||
out := make([]string, 0, len(codes))
|
||||
for _, code := range codes {
|
||||
if _, ok := seen[code]; ok {
|
||||
continue
|
||||
}
|
||||
seen[code] = struct{}{}
|
||||
out = append(out, code)
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
func collapseParentLevelCodes(codes []string) []string {
|
||||
if len(codes) == 0 {
|
||||
return codes
|
||||
}
|
||||
hasChild := func(parent string) bool {
|
||||
for _, code := range codes {
|
||||
if code != parent && strings.HasPrefix(code, parent) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
out := make([]string, 0, len(codes))
|
||||
for _, code := range codes {
|
||||
switch code {
|
||||
case "A", "B", "C", "D":
|
||||
if hasChild(code) {
|
||||
continue
|
||||
}
|
||||
}
|
||||
out = append(out, code)
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
func stringifyRiskCodeVal(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 int64:
|
||||
return strconv.FormatInt(val, 10)
|
||||
default:
|
||||
return fmt.Sprint(val)
|
||||
}
|
||||
}
|
||||
99
internal/domains/api/services/processors/jrzq/1.md
Normal file
99
internal/domains/api/services/processors/jrzq/1.md
Normal file
@@ -0,0 +1,99 @@
|
||||
|
||||
## 返回参数字段说明
|
||||
|
||||
| 字段名 | 类型 | 说明 |
|
||||
|-------------------------|---------|--------------------------------------------------------------|
|
||||
| seqNo | string | 调用唯一标识(如有接口问题,请提供此值) |
|
||||
| orgName | string | 查询人对应的企业名 |
|
||||
| pName | string | 查询人名称 |
|
||||
| relationship | array | 查询人与企业的关联(sh:股东,lp:法人,tm:高管,his_sh:历史股东,his_tm:历史高管) |
|
||||
| basicInfo | object | 查询人所在企业的基本信息 |
|
||||
| his_stockHolderItem | object | 历史持股信息 |
|
||||
| stockHolderItem | object | 持股信息 |
|
||||
| adminPenalty | object | 行政处罚 |
|
||||
| executedPerson | object | 被执行人 |
|
||||
| dishonestExecutedPerson | object | 失信被执行人 |
|
||||
|
||||
### basicInfo 返回信息
|
||||
|
||||
| 字段名 | 类型 | 说明 |
|
||||
|-------------------|---------|----------------|
|
||||
| regStatus | string | 企业状态 |
|
||||
| estiblishTime | string | 注册日期 |
|
||||
| regCapital | string | 注册资本 |
|
||||
| industry | string | 行业 |
|
||||
| type | string | 类型 1-人 2-公司|
|
||||
| regCapitalCurrency| string | 注册资本币种 |
|
||||
| legalPersonName | string | 法人姓名 |
|
||||
| regNumber | string | 注册号 |
|
||||
| creditCode | string | 统一社会信用代码|
|
||||
| name | string | 企业名 |
|
||||
| companyOrgType | string | 企业类型 |
|
||||
| base | string | 省份简称 |
|
||||
| revdate | string | 吊销日期 |
|
||||
| apprdate | string | 核准日期 |
|
||||
| candate | string | 注销日期 |
|
||||
| reccap | string | 实收注册资本 |
|
||||
| reccapcur | string | 实收注册资本币种|
|
||||
| province | string | 省 |
|
||||
| city | string | 市 |
|
||||
| district | string | 区 |
|
||||
| regorg | string | 登记机关 |
|
||||
| opscope | string | 经营范围 |
|
||||
| nic_code | string | 国民经济行业代码|
|
||||
| nic_name | string | 国民经济行业名称|
|
||||
| industry_code | string | 门类代码 |
|
||||
| his_staffList | object | 历史高管 |
|
||||
| tel | string | 电话 |
|
||||
|
||||
### stockHolderItem 返回信息
|
||||
|
||||
| 字段名 | 类型 | 说明 |
|
||||
|----------------|--------|----------|
|
||||
| orgHolderType | string | 股东类型 |
|
||||
| investDate | string | 出资时间 |
|
||||
| investRate | string | 占比 |
|
||||
| subscriptAmt | string | 出资金额 |
|
||||
| orgHolderName | string | 股东名 |
|
||||
|
||||
### adminPenalty 返回信息
|
||||
|
||||
| 字段名 | 类型 | 说明 |
|
||||
|----------------|--------|----------|
|
||||
| departmentName | string | 处罚单位 |
|
||||
| reason | string | 处罚事由 |
|
||||
| punishNumber | string | 决定书文号|
|
||||
| type | string | 处罚类别 |
|
||||
| content | string | 处罚结果 |
|
||||
| decisionDate | string | 处罚日期 |
|
||||
| legalPersonName| string | 法人 |
|
||||
|
||||
### executedPerson 返回信息
|
||||
|
||||
| 字段名 | 类型 | 说明 |
|
||||
|---------------|--------|----------------|
|
||||
| caseCode | string | 案号 |
|
||||
| pname | string | 被执行人名称 |
|
||||
| caseCreateTime| string | 立案日期 |
|
||||
| execCourtName | string | 执行法院 |
|
||||
| execMoney | string | 执行标的(元) |
|
||||
|
||||
### dishonestExecutedPerson 返回信息
|
||||
|
||||
| 字段名 | 类型 | 说明 |
|
||||
|----------------|--------|------------------------------|
|
||||
| businessentity | string | 法人/负责人姓名 |
|
||||
| areaname | string | 省份地区 |
|
||||
| courtname | string | 法院 |
|
||||
| unperformPart | string | 未履行部分 |
|
||||
| type | string | 失信人类型 0 代表人 |
|
||||
| performedPart | string | 已履行部分 |
|
||||
| iname | string | 失信人名称 |
|
||||
| disrupttypename| string | 失信被执行人行为具体情形 |
|
||||
| casecode | string | 案号 |
|
||||
| performance | string | 履行情况 |
|
||||
| regdate | string | 立案时间 |
|
||||
| duty | string | 生效法律文书确定的义务 |
|
||||
| gistunit | string | 做出执行的依据单位 |
|
||||
| publishdate | string | 发布时间 |
|
||||
| gistid | string | 执行依据文号 |
|
||||
120
internal/domains/api/services/processors/jrzq/1json.md
Normal file
120
internal/domains/api/services/processors/jrzq/1json.md
Normal file
@@ -0,0 +1,120 @@
|
||||
```
|
||||
{
|
||||
"datalist": [
|
||||
{
|
||||
"orgName": "南阳市宛城区张明健康服务中心",
|
||||
"pName": "张明",
|
||||
"relationship": [
|
||||
"lp"
|
||||
],
|
||||
"basicInfo": {
|
||||
"regStatus": "在营(开业)企业",
|
||||
"regCapital": "10.0万元人民币",
|
||||
"reccap": 0,
|
||||
"city": "南阳市",
|
||||
"industry_code": "O",
|
||||
"industry": "居民服务业",
|
||||
"type": "1",
|
||||
"nic_code": "O805",
|
||||
"legalPersonName": "张明",
|
||||
"regNumber": "411302601209908",
|
||||
"creditCode": "92411302MA3P3WW37Y",
|
||||
"province": "河南省",
|
||||
"regorg": "南阳市宛城区市场监督管理局",
|
||||
"companyOrgType": "个体",
|
||||
"tel": "",
|
||||
"revdate": "",
|
||||
"estiblishTime": "2019-01-28",
|
||||
"opscope": "",
|
||||
"reccapcur": "人民币",
|
||||
"regCapitalCurrency": "人民币",
|
||||
"nic_name": "居民服务、修理和其他服务业-居民服务业-洗浴和保健养生服务",
|
||||
"candate": "",
|
||||
"district": "宛城区",
|
||||
"name": "南阳市宛城区张明健康服务中心",
|
||||
"base": "hn",
|
||||
"apprdate": "2019-01-28"
|
||||
}
|
||||
},
|
||||
{
|
||||
"orgName": "南阳市宛城区宇旺日用品厂",
|
||||
"pName": "张明",
|
||||
"relationship": [
|
||||
"lp"
|
||||
],
|
||||
"basicInfo": {
|
||||
"regStatus": "已吊销",
|
||||
"regCapital": "8.0万元人民币",
|
||||
"reccap": 0,
|
||||
"city": "南阳市",
|
||||
"industry_code": "C",
|
||||
"industry": "化学原料和化学制品制造业",
|
||||
"type": "1",
|
||||
"nic_code": "C2681",
|
||||
"legalPersonName": "张明",
|
||||
"regNumber": "411302600394898",
|
||||
"creditCode": "",
|
||||
"province": "河南省",
|
||||
"regorg": "南阳市宛城区市场监督管理局",
|
||||
"companyOrgType": "个体",
|
||||
"tel": "",
|
||||
"revdate": "2011-01-14",
|
||||
"estiblishTime": "2008-05-27",
|
||||
"opscope": "",
|
||||
"reccapcur": "人民币",
|
||||
"regCapitalCurrency": "人民币",
|
||||
"nic_name": "制造业-化学原料和化学制品制造业-日用化学产品制造-肥皂及洗涤剂制造",
|
||||
"candate": "",
|
||||
"district": "宛城区",
|
||||
"name": "南阳市宛城区宇旺日用品厂",
|
||||
"base": "hn",
|
||||
"apprdate": "2008-05-27"
|
||||
}
|
||||
},
|
||||
{
|
||||
"orgName": "南阳市信和工程有限公司",
|
||||
"pName": "张明",
|
||||
"stockHolderItem": {
|
||||
"orgHolderType": "自然人",
|
||||
"investDate": "2011-12-19",
|
||||
"investRate": "10.0%",
|
||||
"subscriptAmt": 10,
|
||||
"orgHolderName": "张明"
|
||||
},
|
||||
"relationship": [
|
||||
"sh",
|
||||
"lp",
|
||||
"tm"
|
||||
],
|
||||
"basicInfo": {
|
||||
"regStatus": "注销企业",
|
||||
"regCapital": "100.000000万人民币",
|
||||
"reccap": 0,
|
||||
"city": "南阳市",
|
||||
"industry_code": "E",
|
||||
"industry": "建筑安装业",
|
||||
"type": "1",
|
||||
"nic_code": "E499",
|
||||
"legalPersonName": "张明",
|
||||
"regNumber": "411327200008561",
|
||||
"creditCode": "91411300MA9312Y112",
|
||||
"province": "河南省",
|
||||
"regorg": "南阳市高新技术开发区市场监督管理局",
|
||||
"companyOrgType": "有限责任公司(自然人投资或控股)",
|
||||
"tel": "",
|
||||
"revdate": "",
|
||||
"estiblishTime": "2012-01-04",
|
||||
"opscope": "通讯设备安装维护;电气设备安装维护;通信及电气工程施工。(不含无线电发射及卫星接收设备。需许可经营的,须凭许可证经营)(依法须经批准的项目,经相关部门批准后方可开展经营活动)。",
|
||||
"reccapcur": "人民币",
|
||||
"regCapitalCurrency": "人民币",
|
||||
"nic_name": "建筑业-建筑安装业-其他建筑安装业",
|
||||
"candate": "2015-08-31",
|
||||
"district": "宛城区",
|
||||
"name": "南阳市信和工程有限公司",
|
||||
"base": "hn",
|
||||
"apprdate": "2015-08-31"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
97
internal/domains/api/services/processors/jrzq/2.md
Normal file
97
internal/domains/api/services/processors/jrzq/2.md
Normal file
@@ -0,0 +1,97 @@
|
||||
# 5. 返回参数说明
|
||||
## result.items 整体结构(数组)
|
||||
| 参数名 | 类型 | 说明 |
|
||||
| ---- | ---- | ---- |
|
||||
| total | number | 条数 |
|
||||
| datalist | array | 结果列表 |
|
||||
|
||||
### datalist 子参数
|
||||
| 参数名 | 类型 | 说明 |
|
||||
| ---- | ---- | ---- |
|
||||
| orgName | string | 查询人对应的企业名 |
|
||||
| pName | string | 查询人名称 |
|
||||
| relationship | array | 查询人与这家企业的关联:sh:股东;lp:法人;tm:高管 |
|
||||
| basicInfo | object | 查询人作为股东所在公司的基本信息 |
|
||||
| stockholder | object | 查询人持股信息 |
|
||||
| adminPenalty | array | 行政处罚 |
|
||||
| executedPerson | array | 被执行人(人员) |
|
||||
| dishonestExecutedPerson | array | 失信被执行人(人员) |
|
||||
|
||||
#### basicInfo 企业基本信息(object)
|
||||
| 参数名 | 类型 | 说明 |
|
||||
| ---- | ---- | ---- |
|
||||
| regStatus | string | 企业状态 |
|
||||
| estiblishTime | string | 成立日期(注册日期) |
|
||||
| regCapital | string | 注册资本 |
|
||||
| industry | string | 行业 |
|
||||
| staffList | object | 主要人员 |
|
||||
| regCapitalCurrency | string | 注册资本币种:人民币、美元、欧元等 |
|
||||
| legalPersonName | string | 法人姓名 |
|
||||
| regNumber | string | 注册号 |
|
||||
| creditCode | string | 统一社会信用代码 |
|
||||
| name | string | 企业名 |
|
||||
| companyOrgType | string | 企业类型 |
|
||||
| base | string | 省份简称 |
|
||||
|
||||
##### staffList 主要人员(object)
|
||||
| 参数名 | 类型 | 说明 |
|
||||
| ---- | ---- | ---- |
|
||||
| result | array | 人员列表 |
|
||||
|
||||
###### staffList.result 人员列表(array)
|
||||
| 参数名 | 类型 | 说明 |
|
||||
| ---- | ---- | ---- |
|
||||
| name | string | 名称 |
|
||||
| type | string | 1-公司 2-人 |
|
||||
| typeJoin | array | 职位 |
|
||||
| type | string | 法人类型,1 人 2 公司 |
|
||||
|
||||
#### stockholder 持股信息(object)
|
||||
| 参数名 | 类型 | 说明 |
|
||||
| ---- | ---- | ---- |
|
||||
| orgHolderType | string | 股东类型 |
|
||||
| investDate | string | 出资时间 |
|
||||
| investRate | string | 占比 |
|
||||
| subscriptAmt | string | 出资金额(万元) |
|
||||
| orgHolderName | string | 股东名 |
|
||||
|
||||
#### adminPenalty 行政处罚(array)
|
||||
| 参数名 | 类型 | 说明 |
|
||||
| ---- | ---- | ---- |
|
||||
| departmentName | string | 处罚单位 |
|
||||
| reason | string | 处罚事由/违法行为类型 |
|
||||
| punishNumber | string | 决定文书号 |
|
||||
| type | string | 处罚类别 |
|
||||
| content | string | 处罚结果/内容 |
|
||||
| decisionDate | string | 处罚日期 |
|
||||
| legalPersonName | string | 法定代表人 |
|
||||
|
||||
#### executedPerson 被执行人(人员)(array)
|
||||
| 参数名 | 类型 | 说明 |
|
||||
| ---- | ---- | ---- |
|
||||
| caseCode | string | 案号 |
|
||||
| partyCardNum | string | 身份证号/组织机构代码 |
|
||||
| pname | string | 被执行人名称 |
|
||||
| caseCreateTime | string | 立案日期 |
|
||||
| execCourtName | string | 执行法院 |
|
||||
| execMoney | string | 执行标的(元) |
|
||||
|
||||
#### dishonestExecutedPerson 失信被执行人(人员)(array)
|
||||
| 参数名 | 类型 | 说明 |
|
||||
| ---- | ---- | ---- |
|
||||
| businessentity | string | 法人、负责人姓名 |
|
||||
| areaname | string | 省份地区 |
|
||||
| courtname | string | 法院 |
|
||||
| unperformPart | string | 未履行部分 |
|
||||
| type | string | 失信人类型,0代表人,1代表公司 |
|
||||
| performedPart | string | 已履行部分 |
|
||||
| iname | string | 失信人名称 |
|
||||
| disrupttypename | string | 失信被执行人行为具体情形 |
|
||||
| casecode | string | 案号 |
|
||||
| cardnum | string | 身份证号码/组织机构代码 |
|
||||
| performance | string | 履行情况 |
|
||||
| regdate | string | 立案时间 |
|
||||
| duty | string | 生效法律文书确定的义务 |
|
||||
| gistunit | string | 做出执行的依据单位 |
|
||||
| publishdate | string | 发布时间 |
|
||||
| gistid | string | 执行依据文号 |
|
||||
81
internal/domains/api/services/processors/jrzq/2json.md
Normal file
81
internal/domains/api/services/processors/jrzq/2json.md
Normal file
@@ -0,0 +1,81 @@
|
||||
{
|
||||
"result": {
|
||||
"total": 2,
|
||||
"datalist": [
|
||||
{
|
||||
"pName": "张三",
|
||||
"fsource": "1",
|
||||
"orgName": "****科技(杭州)有限公司",
|
||||
"basicInfo": {
|
||||
"dom": "浙江省杭州市余杭区************室",
|
||||
"tel": "",
|
||||
"base": "zj",
|
||||
"city": "杭州市",
|
||||
"name": "****科技(杭州)有限公司",
|
||||
"opto": "9999-09-09",
|
||||
"type": "1",
|
||||
"email": "",
|
||||
"taxid": "913**********EU3M",
|
||||
"empnum": 6,
|
||||
"opfrom": "2021-09-23",
|
||||
"reccap": 9.8376,
|
||||
"regcap": 500,
|
||||
"regorg": "杭州市余杭区市场监督管理局",
|
||||
"candate": "",
|
||||
"opscope": "一般项目:技术服务、技术开发、技术咨询、技术交流、技术转让、技术推广;信息系统集成服务;计算机系统服务;信息咨询服务(不含许可类信息咨询服务);专业设计服务;社会经济咨询服务;信息技术咨询服务;企业管理咨询;数据处理和存储支持服务;数字内容制作服务(不含出版发行);互联网销售(除销售需要许可的商品);计算机软硬件及辅助设备批发;计算机软硬件及辅助设备零售;国内贸易代理;电子产品销售;通讯设备销售;广告发布;广告设计、代理;广告制作;工程和技术研究和试验发展;市场调查(不含涉外调查);劳务服务(不含劳务派遣);信息系统运行维护服务;大数据服务(除依法须经批准的项目外,凭营业执照依法自主开展经营活动)。",
|
||||
"revdate": "",
|
||||
"apprdate": "2023-07-25",
|
||||
"district": "余杭区",
|
||||
"industry": "软件和信息技术服务业",
|
||||
"isListed": "0",
|
||||
"nic_code": "I6511",
|
||||
"nic_name": "信息传输、软件和信息技术服务业-软件和信息技术服务业-软件开发-应用软件开发",
|
||||
"province": "浙江省",
|
||||
"reccapcur": "人民币",
|
||||
"regNumber": "330106*******258",
|
||||
"regStatus": "存续",
|
||||
"staffList": {},
|
||||
"tax_level": "",
|
||||
"creditCode": "913**********EU3M",
|
||||
"regCapital": "500.000000万人民币",
|
||||
"estiblishTime": "2021-09-23",
|
||||
"his_staffList": {
|
||||
"result": [
|
||||
{
|
||||
"name": "张三",
|
||||
"type": "2",
|
||||
"typeJoin": [
|
||||
"监事"
|
||||
],
|
||||
"isLerepsign": 0
|
||||
}
|
||||
]
|
||||
},
|
||||
"industry_code": "I",
|
||||
"companyOrgType": "有限责任公司(自然人独资)",
|
||||
"legalPersonName": "李四",
|
||||
"companyOrgTypeCode": "1151",
|
||||
"regCapitalCurrency": "人民币"
|
||||
},
|
||||
"adminPenalty": [],
|
||||
"relationship": [
|
||||
"his_sh",
|
||||
"his_tm"
|
||||
],
|
||||
"executedPerson": [],
|
||||
"stockHolderItem": {},
|
||||
"his_stockHolderItem": {
|
||||
"acconam": "",
|
||||
"confrom": "",
|
||||
"currency": "人民币",
|
||||
"investDate": "2023-05-15",
|
||||
"investRate": "",
|
||||
"subscriptAmt": "",
|
||||
"orgHolderName": "张三",
|
||||
"orgHolderType": "自然人"
|
||||
},
|
||||
"dishonestExecutedPerson": []
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -7,7 +7,7 @@ import (
|
||||
|
||||
"tyapi-server/internal/domains/api/dto"
|
||||
"tyapi-server/internal/domains/api/services/processors"
|
||||
"tyapi-server/internal/infrastructure/external/zhicha"
|
||||
"tyapi-server/internal/infrastructure/external/nuoer"
|
||||
)
|
||||
|
||||
// ProcessJRZQ3C7BRequest JRZQ3C7B API处理方法 - 借贷意向验证
|
||||
@@ -21,39 +21,34 @@ func ProcessJRZQ3C7BRequest(ctx context.Context, params []byte, deps *processors
|
||||
return nil, errors.Join(processors.ErrInvalidParam, err)
|
||||
}
|
||||
|
||||
encryptedName, err := deps.ZhichaService.Encrypt(paramsDto.Name)
|
||||
if err != nil {
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
body := map[string]string{
|
||||
"name": paramsDto.Name,
|
||||
"idCard": paramsDto.IDCard,
|
||||
"mobile": paramsDto.MobileNo,
|
||||
}
|
||||
|
||||
encryptedIDCard, err := deps.ZhichaService.Encrypt(paramsDto.IDCard)
|
||||
if err != nil {
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
nuoerDoCheckAPIKey := "loanRiskTagV11"
|
||||
ApiPath := "/v1/doCheck"
|
||||
|
||||
encryptedMobileNo, err := deps.ZhichaService.Encrypt(paramsDto.MobileNo)
|
||||
resp, err := deps.NuoerService.CallAPI(ctx, nuoerDoCheckAPIKey, ApiPath, body)
|
||||
if err != nil {
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
|
||||
reqData := map[string]interface{}{
|
||||
"name": encryptedName,
|
||||
"idCard": encryptedIDCard,
|
||||
"phone": encryptedMobileNo,
|
||||
"authorized": paramsDto.Authorized,
|
||||
}
|
||||
|
||||
respData, err := deps.ZhichaService.CallAPI(ctx, "ZCI017", reqData)
|
||||
if err != nil {
|
||||
if errors.Is(err, zhicha.ErrDatasource) {
|
||||
if errors.Is(err, nuoer.ErrDatasource) {
|
||||
return nil, errors.Join(processors.ErrDatasource, err)
|
||||
} else {
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
if errors.Is(err, nuoer.ErrNotFound) {
|
||||
return nil, errors.Join(processors.ErrNotFound, err)
|
||||
}
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
|
||||
// 将响应数据转换为JSON字节
|
||||
respBytes, err := json.Marshal(respData)
|
||||
rawData, ok := resp.Data.(map[string]interface{})
|
||||
if !ok {
|
||||
return nil, errors.Join(processors.ErrSystem, errors.New("响应格式错误"))
|
||||
}
|
||||
|
||||
result := mapNuoerApplyLoanToResponse(rawData)
|
||||
|
||||
respBytes, err := json.Marshal(result)
|
||||
if err != nil {
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
package jrzq
|
||||
|
||||
import "strings"
|
||||
|
||||
// mapNuoerApplyLoanToResponse 将 nuoer 响应(2json.md)转为对外结构(1json.md):
|
||||
// 解包 result,保留 Rule_* / als_* 平铺字段。
|
||||
func mapNuoerApplyLoanToResponse(data map[string]interface{}) map[string]interface{} {
|
||||
if data == nil {
|
||||
return map[string]interface{}{}
|
||||
}
|
||||
return normalizeApplyLoanFlatMap(unwrapNuoerApplyLoanData(data))
|
||||
}
|
||||
|
||||
func unwrapNuoerApplyLoanData(data map[string]interface{}) map[string]interface{} {
|
||||
if result, ok := data["result"].(map[string]interface{}); ok {
|
||||
return result
|
||||
}
|
||||
return data
|
||||
}
|
||||
|
||||
func normalizeApplyLoanFlatMap(flat map[string]interface{}) map[string]interface{} {
|
||||
result := make(map[string]interface{}, len(flat))
|
||||
for key, val := range flat {
|
||||
if !isApplyLoanResponseKey(key) {
|
||||
continue
|
||||
}
|
||||
strVal := stringifyVal(val)
|
||||
if strVal == "" {
|
||||
continue
|
||||
}
|
||||
result[key] = strVal
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func isApplyLoanResponseKey(key string) bool {
|
||||
return strings.HasPrefix(key, "Rule_") || strings.HasPrefix(key, "als_")
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -7,7 +7,7 @@ import (
|
||||
|
||||
"tyapi-server/internal/domains/api/dto"
|
||||
"tyapi-server/internal/domains/api/services/processors"
|
||||
"tyapi-server/internal/infrastructure/external/zhicha"
|
||||
"tyapi-server/internal/infrastructure/external/nuoer"
|
||||
)
|
||||
|
||||
// ProcessJRZQ5E9FRequest JRZQ5E9F API处理方法 - 借选指数
|
||||
@@ -21,39 +21,34 @@ func ProcessJRZQ5E9FRequest(ctx context.Context, params []byte, deps *processors
|
||||
return nil, errors.Join(processors.ErrInvalidParam, err)
|
||||
}
|
||||
|
||||
encryptedName, err := deps.ZhichaService.Encrypt(paramsDto.Name)
|
||||
if err != nil {
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
body := map[string]string{
|
||||
"name": paramsDto.Name,
|
||||
"idCard": paramsDto.IDCard,
|
||||
"mobile": paramsDto.MobileNo,
|
||||
}
|
||||
|
||||
encryptedIDCard, err := deps.ZhichaService.Encrypt(paramsDto.IDCard)
|
||||
if err != nil {
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
nuoerDoCheckAPIKey := "loanRiskTagV21"
|
||||
ApiPath := "/v1/doCheck"
|
||||
|
||||
encryptedMobileNo, err := deps.ZhichaService.Encrypt(paramsDto.MobileNo)
|
||||
resp, err := deps.NuoerService.CallAPI(ctx, nuoerDoCheckAPIKey, ApiPath, body)
|
||||
if err != nil {
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
|
||||
reqData := map[string]interface{}{
|
||||
"name": encryptedName,
|
||||
"idCard": encryptedIDCard,
|
||||
"phone": encryptedMobileNo,
|
||||
"authorized": paramsDto.Authorized,
|
||||
}
|
||||
|
||||
respData, err := deps.ZhichaService.CallAPI(ctx, "ZCI021", reqData)
|
||||
if err != nil {
|
||||
if errors.Is(err, zhicha.ErrDatasource) {
|
||||
if errors.Is(err, nuoer.ErrDatasource) {
|
||||
return nil, errors.Join(processors.ErrDatasource, err)
|
||||
} else {
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
if errors.Is(err, nuoer.ErrNotFound) {
|
||||
return nil, errors.Join(processors.ErrNotFound, err)
|
||||
}
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
|
||||
// 将响应数据转换为JSON字节
|
||||
respBytes, err := json.Marshal(respData)
|
||||
rawData, ok := resp.Data.(map[string]interface{})
|
||||
if !ok {
|
||||
return nil, errors.Join(processors.ErrSystem, errors.New("响应格式错误"))
|
||||
}
|
||||
|
||||
result := mapNuoerLoanRiskToResponse(rawData)
|
||||
|
||||
respBytes, err := json.Marshal(result)
|
||||
if err != nil {
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,93 @@
|
||||
package jrzq
|
||||
|
||||
import (
|
||||
"math"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type loanRiskInterval struct {
|
||||
output string
|
||||
min float64
|
||||
max float64
|
||||
minInclusive bool
|
||||
maxInclusive bool
|
||||
}
|
||||
|
||||
// mapNuoerLoanRiskToResponse 将 nuoer 响应(2json.md)转为对外结构(1json.md):
|
||||
// 解包 result,区间化字段按 1.md 映射,其余字段原样透传。
|
||||
func mapNuoerLoanRiskToResponse(data map[string]interface{}) map[string]interface{} {
|
||||
if data == nil {
|
||||
return map[string]interface{}{}
|
||||
}
|
||||
return normalizeLoanRiskFlatMap(unwrapNuoerLoanRiskData(data))
|
||||
}
|
||||
|
||||
func unwrapNuoerLoanRiskData(data map[string]interface{}) map[string]interface{} {
|
||||
if result, ok := data["result"].(map[string]interface{}); ok {
|
||||
return result
|
||||
}
|
||||
return data
|
||||
}
|
||||
|
||||
func normalizeLoanRiskFlatMap(flat map[string]interface{}) map[string]interface{} {
|
||||
result := make(map[string]interface{}, len(flat))
|
||||
for key, val := range flat {
|
||||
if !strings.HasPrefix(key, "xyp_") {
|
||||
continue
|
||||
}
|
||||
raw := strings.TrimSpace(stringifyVal(val))
|
||||
if raw == "" {
|
||||
result[key] = "0"
|
||||
continue
|
||||
}
|
||||
if rules, ok := loanRiskIntervalMappings[key]; ok {
|
||||
result[key] = mapLoanRiskIntervalValue(raw, rules)
|
||||
continue
|
||||
}
|
||||
result[key] = raw
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func mapLoanRiskIntervalValue(raw string, rules []loanRiskInterval) string {
|
||||
value, ok := parseLoanRiskNumber(raw)
|
||||
if !ok {
|
||||
return "0"
|
||||
}
|
||||
for _, rule := range rules {
|
||||
if loanRiskValueInInterval(value, rule) {
|
||||
return rule.output
|
||||
}
|
||||
}
|
||||
return "0"
|
||||
}
|
||||
|
||||
func parseLoanRiskNumber(raw string) (float64, bool) {
|
||||
f, err := strconv.ParseFloat(strings.TrimSpace(raw), 64)
|
||||
if err != nil {
|
||||
return 0, false
|
||||
}
|
||||
if math.IsNaN(f) || math.IsInf(f, 0) {
|
||||
return 0, false
|
||||
}
|
||||
return f, true
|
||||
}
|
||||
|
||||
func loanRiskValueInInterval(value float64, rule loanRiskInterval) bool {
|
||||
if rule.minInclusive {
|
||||
if value < rule.min {
|
||||
return false
|
||||
}
|
||||
} else if value <= rule.min {
|
||||
return false
|
||||
}
|
||||
|
||||
if rule.max >= math.MaxFloat64/2 {
|
||||
return true
|
||||
}
|
||||
if rule.maxInclusive {
|
||||
return value <= rule.max
|
||||
}
|
||||
return value < rule.max
|
||||
}
|
||||
@@ -0,0 +1,107 @@
|
||||
package jrzq
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestMapNuoerLoanRiskToResponse_UnwrapsResult(t *testing.T) {
|
||||
raw := map[string]interface{}{
|
||||
"result": map[string]interface{}{
|
||||
"xyp_cpl0076": "2",
|
||||
"xyp_cpl0073": "0.58",
|
||||
"xyp_cpl0081": "0.6532",
|
||||
},
|
||||
}
|
||||
|
||||
got := mapNuoerLoanRiskToResponse(raw)
|
||||
|
||||
if got["xyp_cpl0073"] != "0.58" {
|
||||
t.Fatalf("xyp_cpl0073 = %v, want 0.58", got["xyp_cpl0073"])
|
||||
}
|
||||
if got["xyp_cpl0081"] != "0.6532" {
|
||||
t.Fatalf("xyp_cpl0081 = %v, want 0.6532", got["xyp_cpl0081"])
|
||||
}
|
||||
if got["xyp_cpl0076"] != "2" {
|
||||
t.Fatalf("xyp_cpl0076 = %v, want 2", got["xyp_cpl0076"])
|
||||
}
|
||||
}
|
||||
|
||||
func TestMapNuoerLoanRiskToResponse_IntervalMapping(t *testing.T) {
|
||||
raw := map[string]interface{}{
|
||||
"xyp_cpl0001": "14",
|
||||
"xyp_cpl0070": "0",
|
||||
}
|
||||
|
||||
got := mapNuoerLoanRiskToResponse(raw)
|
||||
|
||||
if got["xyp_cpl0001"] != "3" {
|
||||
t.Fatalf("xyp_cpl0001 = %v, want 3", got["xyp_cpl0001"])
|
||||
}
|
||||
if got["xyp_cpl0070"] != "0" {
|
||||
t.Fatalf("xyp_cpl0070 = %v, want 0", got["xyp_cpl0070"])
|
||||
}
|
||||
}
|
||||
|
||||
func TestMapNuoerLoanRiskToResponse_PreservesEmptyFieldsAsZero(t *testing.T) {
|
||||
raw := map[string]interface{}{
|
||||
"result": map[string]interface{}{
|
||||
"xyp_cpl0001": "",
|
||||
"xyp_cpl0073": "",
|
||||
"xyp_model_score_high": "-1",
|
||||
"xyp_model_score_mid": "-1",
|
||||
"xyp_model_score_low": "-1",
|
||||
},
|
||||
}
|
||||
|
||||
got := mapNuoerLoanRiskToResponse(raw)
|
||||
|
||||
if len(got) != 5 {
|
||||
t.Fatalf("got %d fields, want 5: %#v", len(got), got)
|
||||
}
|
||||
if got["xyp_cpl0001"] != "0" {
|
||||
t.Fatalf("xyp_cpl0001 = %v, want 0", got["xyp_cpl0001"])
|
||||
}
|
||||
if got["xyp_cpl0073"] != "0" {
|
||||
t.Fatalf("xyp_cpl0073 = %v, want 0", got["xyp_cpl0073"])
|
||||
}
|
||||
if got["xyp_model_score_high"] != "-1" {
|
||||
t.Fatalf("xyp_model_score_high = %v, want -1", got["xyp_model_score_high"])
|
||||
}
|
||||
}
|
||||
|
||||
func TestMapNuoerLoanRiskToResponse_2jsonSample(t *testing.T) {
|
||||
const sample = `{
|
||||
"result": {
|
||||
"xyp_cpl0063": "0",
|
||||
"xyp_cpl0065": "0",
|
||||
"xyp_cpl0070": "0",
|
||||
"xyp_cpl0071": "0",
|
||||
"xyp_cpl0073": "0.58",
|
||||
"xyp_cpl0074": "0.6",
|
||||
"xyp_cpl0076": "2",
|
||||
"xyp_cpl0081": "0.6532",
|
||||
"xyp_model_score_high": "668"
|
||||
}
|
||||
}`
|
||||
|
||||
var raw map[string]interface{}
|
||||
if err := json.Unmarshal([]byte(sample), &raw); err != nil {
|
||||
t.Fatalf("unmarshal sample: %v", err)
|
||||
}
|
||||
|
||||
got := mapNuoerLoanRiskToResponse(raw)
|
||||
|
||||
if got["xyp_cpl0073"] != "0.58" {
|
||||
t.Fatalf("xyp_cpl0073 = %v, want 0.58", got["xyp_cpl0073"])
|
||||
}
|
||||
if got["xyp_cpl0076"] != "2" {
|
||||
t.Fatalf("xyp_cpl0076 = %v, want 2", got["xyp_cpl0076"])
|
||||
}
|
||||
if got["xyp_model_score_high"] != "668" {
|
||||
t.Fatalf("xyp_model_score_high = %v, want 668", got["xyp_model_score_high"])
|
||||
}
|
||||
if _, ok := got["result"]; ok {
|
||||
t.Fatal("result wrapper should be removed")
|
||||
}
|
||||
}
|
||||
@@ -7,7 +7,7 @@ import (
|
||||
|
||||
"tyapi-server/internal/domains/api/dto"
|
||||
"tyapi-server/internal/domains/api/services/processors"
|
||||
"tyapi-server/internal/infrastructure/external/zhicha"
|
||||
"tyapi-server/internal/infrastructure/external/nuoer"
|
||||
)
|
||||
|
||||
// ProcessJRZQ8A2DRequest JRZQ8A2D API处理方法 - 特殊名单验证
|
||||
@@ -20,40 +20,55 @@ func ProcessJRZQ8A2DRequest(ctx context.Context, params []byte, deps *processors
|
||||
if err := deps.Validator.ValidateStruct(paramsDto); err != nil {
|
||||
return nil, errors.Join(processors.ErrInvalidParam, err)
|
||||
}
|
||||
encryptedName, err := deps.ZhichaService.Encrypt(paramsDto.Name)
|
||||
if err != nil {
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
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)
|
||||
|
||||
body := map[string]string{
|
||||
"name": paramsDto.Name,
|
||||
"idCard": paramsDto.IDCard,
|
||||
"mobile": paramsDto.MobileNo,
|
||||
}
|
||||
|
||||
reqData := map[string]interface{}{
|
||||
"name": encryptedName,
|
||||
"idCard": encryptedIDCard,
|
||||
"phone": encryptedMobileNo,
|
||||
"authorized": paramsDto.Authorized,
|
||||
}
|
||||
nuoerDoCheckAPIKey := "loanRiskTagV12"
|
||||
ApiPath := "/v1/doCheck"
|
||||
|
||||
respData, err := deps.ZhichaService.CallAPI(ctx, "ZCI018", reqData)
|
||||
resp, err := deps.NuoerService.CallAPI(ctx, nuoerDoCheckAPIKey, ApiPath, body)
|
||||
if err != nil {
|
||||
if errors.Is(err, zhicha.ErrDatasource) {
|
||||
if errors.Is(err, nuoer.ErrDatasource) {
|
||||
return nil, errors.Join(processors.ErrDatasource, err)
|
||||
} else {
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
if errors.Is(err, nuoer.ErrNotFound) {
|
||||
return nil, errors.Join(processors.ErrNotFound, err)
|
||||
}
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
|
||||
// 将响应数据转换为JSON字节
|
||||
respBytes, err := json.Marshal(respData)
|
||||
rawData, ok := resp.Data.(map[string]interface{})
|
||||
if !ok {
|
||||
return nil, errors.Join(processors.ErrSystem, errors.New("响应格式错误"))
|
||||
}
|
||||
|
||||
result := mapNuoerSpecialListToResponse(rawData)
|
||||
|
||||
respBytes, err := json.Marshal(result)
|
||||
if err != nil {
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
|
||||
return respBytes, nil
|
||||
|
||||
// respData, err := deps.ZhichaService.CallAPI(ctx, "ZCI018", reqData)
|
||||
// if err != nil {
|
||||
// if errors.Is(err, zhicha.ErrDatasource) {
|
||||
// return nil, errors.Join(processors.ErrDatasource, err)
|
||||
// } else {
|
||||
// return nil, errors.Join(processors.ErrSystem, err)
|
||||
// }
|
||||
// }
|
||||
|
||||
// // 将响应数据转换为JSON字节
|
||||
// respBytes, err := json.Marshal(respData)
|
||||
// if err != nil {
|
||||
// return nil, errors.Join(processors.ErrSystem, err)
|
||||
// }
|
||||
|
||||
// return respBytes, nil
|
||||
}
|
||||
|
||||
@@ -0,0 +1,102 @@
|
||||
package jrzq
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
// mapNuoerSpecialListToResponse 将 nuoer 响应(2.md)转为对外结构(1.md):
|
||||
// SpecialList_c -> id/cell,Rule -> Rule_final_* / Rule_name_odr* / Rule_weight_odr*
|
||||
func mapNuoerSpecialListToResponse(data map[string]interface{}) map[string]interface{} {
|
||||
if data == nil {
|
||||
return map[string]interface{}{
|
||||
"id": map[string]interface{}{},
|
||||
"cell": map[string]interface{}{},
|
||||
}
|
||||
}
|
||||
|
||||
if _, hasID := data["id"]; hasID {
|
||||
if _, hasSpecialList := data["SpecialList_c"]; !hasSpecialList {
|
||||
return data
|
||||
}
|
||||
}
|
||||
|
||||
payload := unwrapNuoerSpecialListData(data)
|
||||
result := make(map[string]interface{})
|
||||
|
||||
specialList := asMap(payload["SpecialList_c"])
|
||||
result["id"] = normalizeStringMap(specialList["id"])
|
||||
result["cell"] = normalizeStringMap(specialList["cell"])
|
||||
|
||||
rule := asMap(payload["Rule"])
|
||||
ruleResult := asMap(rule["result"])
|
||||
if v := stringifyVal(ruleResult["final_decision"]); v != "" {
|
||||
result["Rule_final_decision"] = v
|
||||
}
|
||||
if v := stringifyVal(ruleResult["final_weight"]); v != "" {
|
||||
result["Rule_final_weight"] = v
|
||||
}
|
||||
|
||||
hitRules := asMap(rule["hit_rules"])
|
||||
ruleSpecialList := asMap(hitRules["rulespeciallist_c"])
|
||||
for odrID, raw := range ruleSpecialList {
|
||||
odrRule := asMap(raw)
|
||||
if name := stringifyVal(odrRule["name_rule"]); name != "" {
|
||||
result["Rule_name_"+odrID] = name
|
||||
}
|
||||
if weight := stringifyVal(odrRule["weight"]); weight != "" {
|
||||
result["Rule_weight_"+odrID] = weight
|
||||
}
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
func unwrapNuoerSpecialListData(data map[string]interface{}) map[string]interface{} {
|
||||
if _, ok := data["SpecialList_c"]; ok {
|
||||
return data
|
||||
}
|
||||
if result, ok := data["result"].(map[string]interface{}); ok {
|
||||
if _, ok := result["SpecialList_c"]; ok {
|
||||
return result
|
||||
}
|
||||
}
|
||||
return data
|
||||
}
|
||||
|
||||
func normalizeStringMap(v interface{}) map[string]interface{} {
|
||||
src := asMap(v)
|
||||
if len(src) == 0 {
|
||||
return map[string]interface{}{}
|
||||
}
|
||||
out := make(map[string]interface{}, len(src))
|
||||
for k, val := range src {
|
||||
out[k] = stringifyVal(val)
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
func stringifyVal(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)
|
||||
case bool:
|
||||
return strconv.FormatBool(val)
|
||||
default:
|
||||
return fmt.Sprint(val)
|
||||
}
|
||||
}
|
||||
@@ -7,7 +7,7 @@ import (
|
||||
|
||||
"tyapi-server/internal/domains/api/dto"
|
||||
"tyapi-server/internal/domains/api/services/processors"
|
||||
"tyapi-server/internal/infrastructure/external/westdex"
|
||||
"tyapi-server/internal/infrastructure/external/nuoer"
|
||||
)
|
||||
|
||||
// ProcessQYGL6F2DRequest QYGL6F2D API处理方法
|
||||
@@ -20,26 +20,35 @@ func ProcessQYGL6F2DRequest(ctx context.Context, params []byte, deps *processors
|
||||
if err := deps.Validator.ValidateStruct(paramsDto); err != nil {
|
||||
return nil, errors.Join(processors.ErrInvalidParam, err)
|
||||
}
|
||||
body := map[string]string{
|
||||
"idCard": paramsDto.IDCard,
|
||||
}
|
||||
|
||||
encryptedIDCard, err := deps.WestDexService.Encrypt(paramsDto.IDCard)
|
||||
nuoerDoCheckAPIKey := "idRelationV101"
|
||||
ApiPath := "/v1/doCheck"
|
||||
|
||||
resp, err := deps.NuoerService.CallAPI(ctx, nuoerDoCheckAPIKey, ApiPath, body)
|
||||
if err != nil {
|
||||
if errors.Is(err, nuoer.ErrDatasource) {
|
||||
return nil, errors.Join(processors.ErrDatasource, err)
|
||||
}
|
||||
if errors.Is(err, nuoer.ErrNotFound) {
|
||||
return nil, errors.Join(processors.ErrNotFound, err)
|
||||
}
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
|
||||
rawData, ok := resp.Data.(map[string]interface{})
|
||||
if !ok {
|
||||
return nil, errors.Join(processors.ErrSystem, errors.New("响应格式错误"))
|
||||
}
|
||||
|
||||
result := mapNuoerIdRelationToResponse(rawData)
|
||||
|
||||
respBytes, err := json.Marshal(result)
|
||||
if err != nil {
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
|
||||
reqData := map[string]interface{}{
|
||||
"data": map[string]interface{}{
|
||||
"idno": encryptedIDCard,
|
||||
},
|
||||
}
|
||||
|
||||
respBytes, err := deps.WestDexService.CallAPI(ctx, "G05XM02", reqData)
|
||||
if err != nil {
|
||||
if errors.Is(err, westdex.ErrDatasource) {
|
||||
return nil, errors.Join(processors.ErrDatasource, err)
|
||||
} else {
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
}
|
||||
|
||||
return respBytes, nil
|
||||
}
|
||||
|
||||
@@ -0,0 +1,150 @@
|
||||
package qygl
|
||||
|
||||
var qygl6f2dBasicInfoFields = []string{
|
||||
"regStatus", "estiblishTime", "regCapital", "industry", "type",
|
||||
"regCapitalCurrency", "legalPersonName", "regNumber", "creditCode", "name",
|
||||
"companyOrgType", "base", "revdate", "apprdate", "candate", "reccap",
|
||||
"reccapcur", "province", "city", "district", "regorg", "opscope",
|
||||
"nic_code", "nic_name", "industry_code", "his_staffList", "tel",
|
||||
}
|
||||
|
||||
var qygl6f2dStockHolderFields = []string{
|
||||
"orgHolderType", "investDate", "investRate", "subscriptAmt", "orgHolderName",
|
||||
}
|
||||
|
||||
var qygl6f2dAdminPenaltyFields = []string{
|
||||
"departmentName", "reason", "punishNumber", "type", "content",
|
||||
"decisionDate", "legalPersonName",
|
||||
}
|
||||
|
||||
var qygl6f2dExecutedPersonFields = []string{
|
||||
"caseCode", "pname", "caseCreateTime", "execCourtName", "execMoney",
|
||||
}
|
||||
|
||||
var qygl6f2dDishonestExecutedPersonFields = []string{
|
||||
"businessentity", "areaname", "courname", "unperformPart", "type",
|
||||
"performedPart", "iname", "disrupttypename", "casecode", "performance",
|
||||
"regdate", "duty", "gistunit", "publishdate", "gistid",
|
||||
}
|
||||
|
||||
// mapNuoerIdRelationToResponse 将 nuoer 响应(2json.md)转为对外结构(1json.md):
|
||||
// 解包 result,去掉 total/fsource,并按 1.md 裁剪字段。
|
||||
func mapNuoerIdRelationToResponse(data map[string]interface{}) map[string]interface{} {
|
||||
if data == nil {
|
||||
return map[string]interface{}{"datalist": []interface{}{}}
|
||||
}
|
||||
|
||||
payload := unwrapNuoerIdRelationData(data)
|
||||
rawList := asSlice(payload["datalist"])
|
||||
|
||||
datalist := make([]interface{}, 0, len(rawList))
|
||||
for _, item := range rawList {
|
||||
if mapped := mapNuoerIdRelationItem(asMap(item)); mapped != nil {
|
||||
datalist = append(datalist, mapped)
|
||||
}
|
||||
}
|
||||
|
||||
return map[string]interface{}{"datalist": datalist}
|
||||
}
|
||||
|
||||
func unwrapNuoerIdRelationData(data map[string]interface{}) map[string]interface{} {
|
||||
if _, ok := data["datalist"]; ok {
|
||||
return data
|
||||
}
|
||||
if result, ok := data["result"].(map[string]interface{}); ok {
|
||||
return result
|
||||
}
|
||||
return data
|
||||
}
|
||||
|
||||
func mapNuoerIdRelationItem(item map[string]interface{}) map[string]interface{} {
|
||||
if len(item) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
out := make(map[string]interface{}, 8)
|
||||
for _, key := range []string{"orgName", "pName", "relationship"} {
|
||||
if val, ok := item[key]; ok && val != nil {
|
||||
out[key] = val
|
||||
}
|
||||
}
|
||||
|
||||
if basicInfo := pickFields(asMap(item["basicInfo"]), qygl6f2dBasicInfoFields); isNonemptyMap(basicInfo) {
|
||||
out["basicInfo"] = basicInfo
|
||||
}
|
||||
if stockHolder := pickFields(asMap(item["stockHolderItem"]), qygl6f2dStockHolderFields); isNonemptyMap(stockHolder) {
|
||||
out["stockHolderItem"] = stockHolder
|
||||
}
|
||||
if hisStockHolder := pickFields(asMap(item["his_stockHolderItem"]), qygl6f2dStockHolderFields); isNonemptyMap(hisStockHolder) {
|
||||
out["his_stockHolderItem"] = hisStockHolder
|
||||
}
|
||||
if adminPenalty := mapNuoerIdRelationRecords(item["adminPenalty"], qygl6f2dAdminPenaltyFields); len(adminPenalty) > 0 {
|
||||
out["adminPenalty"] = adminPenalty
|
||||
}
|
||||
if executedPerson := mapNuoerIdRelationRecords(item["executedPerson"], qygl6f2dExecutedPersonFields); len(executedPerson) > 0 {
|
||||
out["executedPerson"] = executedPerson
|
||||
}
|
||||
if dishonestExecutedPerson := mapNuoerIdRelationRecords(item["dishonestExecutedPerson"], qygl6f2dDishonestExecutedPersonFields); len(dishonestExecutedPerson) > 0 {
|
||||
out["dishonestExecutedPerson"] = dishonestExecutedPerson
|
||||
}
|
||||
|
||||
return out
|
||||
}
|
||||
|
||||
func mapNuoerIdRelationRecords(v interface{}, allowlist []string) []interface{} {
|
||||
list := asSlice(v)
|
||||
if len(list) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
out := make([]interface{}, 0, len(list))
|
||||
for _, item := range list {
|
||||
if mapped := pickFields(asMap(item), allowlist); isNonemptyMap(mapped) {
|
||||
out = append(out, mapped)
|
||||
}
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
func pickFields(src map[string]interface{}, allowlist []string) map[string]interface{} {
|
||||
if len(src) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
out := make(map[string]interface{}, len(allowlist))
|
||||
for _, key := range allowlist {
|
||||
val, ok := src[key]
|
||||
if !ok || val == nil {
|
||||
continue
|
||||
}
|
||||
out[key] = val
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
func isNonemptyMap(m map[string]interface{}) bool {
|
||||
return len(m) > 0
|
||||
}
|
||||
|
||||
func asMap(v interface{}) map[string]interface{} {
|
||||
if v == nil {
|
||||
return nil
|
||||
}
|
||||
m, ok := v.(map[string]interface{})
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
return m
|
||||
}
|
||||
|
||||
func asSlice(v interface{}) []interface{} {
|
||||
if v == nil {
|
||||
return nil
|
||||
}
|
||||
switch val := v.(type) {
|
||||
case []interface{}:
|
||||
return val
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
@@ -156,7 +156,7 @@ func (s *NuoerService) CallAPI(ctx context.Context, apiKey, apiPath string, body
|
||||
nuoerErr := NewNuoerError(nuoerResp.Code, nuoerResp.Msg)
|
||||
err = errors.Join(GetErrByPlatformCode(nuoerResp.Code), nuoerErr)
|
||||
if s.logger != nil {
|
||||
s.logger.LogError(requestID, transactionID, apiKey, nuoerErr, requestPayload)
|
||||
s.logger.LogErrorWithResponseID(requestID, transactionID, apiKey, nuoerErr, requestPayload, nuoerResp.SeqNo)
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
@@ -164,7 +164,7 @@ func (s *NuoerService) CallAPI(ctx context.Context, apiKey, apiPath string, body
|
||||
if nuoerResp.Data == nil {
|
||||
err = errors.Join(ErrSystem, errors.New("响应 data 为空"))
|
||||
if s.logger != nil {
|
||||
s.logger.LogError(requestID, transactionID, apiKey, err, requestPayload)
|
||||
s.logger.LogErrorWithResponseID(requestID, transactionID, apiKey, err, requestPayload, nuoerResp.SeqNo)
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
@@ -173,7 +173,7 @@ func (s *NuoerService) CallAPI(ctx context.Context, apiKey, apiPath string, body
|
||||
if !ok {
|
||||
err = errors.Join(ErrSystem, errors.New("响应 data 无法解析 busiCode"))
|
||||
if s.logger != nil {
|
||||
s.logger.LogError(requestID, transactionID, apiKey, err, requestPayload)
|
||||
s.logger.LogErrorWithResponseID(requestID, transactionID, apiKey, err, requestPayload, nuoerResp.SeqNo)
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
@@ -182,7 +182,7 @@ func (s *NuoerService) CallAPI(ctx context.Context, apiKey, apiPath string, body
|
||||
busiErr := NewNuoerBusiError(busiCode, busiMsg)
|
||||
err = errors.Join(GetErrByBusiCode(busiCode), busiErr)
|
||||
if s.logger != nil {
|
||||
s.logger.LogError(requestID, transactionID, apiKey, busiErr, requestPayload)
|
||||
s.logger.LogErrorWithResponseID(requestID, transactionID, apiKey, busiErr, requestPayload, nuoerResp.SeqNo)
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
@@ -191,7 +191,7 @@ func (s *NuoerService) CallAPI(ctx context.Context, apiKey, apiPath string, body
|
||||
if err != nil {
|
||||
err = errors.Join(ErrSystem, fmt.Errorf("响应 data 清理失败: %w", err))
|
||||
if s.logger != nil {
|
||||
s.logger.LogError(requestID, transactionID, apiKey, err, requestPayload)
|
||||
s.logger.LogErrorWithResponseID(requestID, transactionID, apiKey, err, requestPayload, nuoerResp.SeqNo)
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user