f
This commit is contained in:
@@ -9,24 +9,24 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"hyapi-server/internal/application/certification/dto/commands"
|
"tyapi-server/internal/application/certification/dto/commands"
|
||||||
"hyapi-server/internal/application/certification/dto/queries"
|
"tyapi-server/internal/application/certification/dto/queries"
|
||||||
"hyapi-server/internal/application/certification/dto/responses"
|
"tyapi-server/internal/application/certification/dto/responses"
|
||||||
"hyapi-server/internal/config"
|
"tyapi-server/internal/config"
|
||||||
api_service "hyapi-server/internal/domains/api/services"
|
api_service "tyapi-server/internal/domains/api/services"
|
||||||
"hyapi-server/internal/domains/certification/entities"
|
"tyapi-server/internal/domains/certification/entities"
|
||||||
certification_value_objects "hyapi-server/internal/domains/certification/entities/value_objects"
|
certification_value_objects "tyapi-server/internal/domains/certification/entities/value_objects"
|
||||||
"hyapi-server/internal/domains/certification/enums"
|
"tyapi-server/internal/domains/certification/enums"
|
||||||
"hyapi-server/internal/domains/certification/repositories"
|
"tyapi-server/internal/domains/certification/repositories"
|
||||||
"hyapi-server/internal/domains/certification/services"
|
"tyapi-server/internal/domains/certification/services"
|
||||||
finance_service "hyapi-server/internal/domains/finance/services"
|
finance_service "tyapi-server/internal/domains/finance/services"
|
||||||
user_entities "hyapi-server/internal/domains/user/entities"
|
user_entities "tyapi-server/internal/domains/user/entities"
|
||||||
user_service "hyapi-server/internal/domains/user/services"
|
user_service "tyapi-server/internal/domains/user/services"
|
||||||
"hyapi-server/internal/infrastructure/external/notification"
|
"tyapi-server/internal/infrastructure/external/notification"
|
||||||
"hyapi-server/internal/infrastructure/external/storage"
|
"tyapi-server/internal/infrastructure/external/storage"
|
||||||
"hyapi-server/internal/shared/database"
|
"tyapi-server/internal/shared/database"
|
||||||
"hyapi-server/internal/shared/esign"
|
"tyapi-server/internal/shared/esign"
|
||||||
sharedOCR "hyapi-server/internal/shared/ocr"
|
sharedOCR "tyapi-server/internal/shared/ocr"
|
||||||
|
|
||||||
"go.uber.org/zap"
|
"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/dto"
|
||||||
"tyapi-server/internal/domains/api/services/processors"
|
"tyapi-server/internal/domains/api/services/processors"
|
||||||
"tyapi-server/internal/infrastructure/external/zhicha"
|
"tyapi-server/internal/infrastructure/external/nuoer"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ProcessFLXG5A3BRequest FLXG5A3B API处理方法 - 个人司法涉诉
|
// ProcessFLXG5A3BRequest FLXG5A3B API处理方法 - 个人司法涉诉
|
||||||
@@ -24,33 +24,33 @@ func ProcessFLXG5A3BRequest(ctx context.Context, params []byte, deps *processors
|
|||||||
return nil, errors.Join(processors.ErrNotFound, errors.New("查询为空"))
|
return nil, errors.Join(processors.ErrNotFound, errors.New("查询为空"))
|
||||||
}
|
}
|
||||||
|
|
||||||
encryptedName, err := deps.ZhichaService.Encrypt(paramsDto.Name)
|
body := map[string]string{
|
||||||
if err != nil {
|
"name": paramsDto.Name,
|
||||||
return nil, errors.Join(processors.ErrSystem, err)
|
"idCard": paramsDto.IDCard,
|
||||||
}
|
}
|
||||||
|
|
||||||
encryptedIDCard, err := deps.ZhichaService.Encrypt(paramsDto.IDCard)
|
nuoerDoCheckAPIKey := "personalLawsuit_cv1"
|
||||||
if err != nil {
|
ApiPath := "/v1/doCheck"
|
||||||
return nil, errors.Join(processors.ErrSystem, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
reqData := map[string]interface{}{
|
resp, err := deps.NuoerService.CallAPI(ctx, nuoerDoCheckAPIKey, ApiPath, body)
|
||||||
"name": encryptedName,
|
|
||||||
"idCard": encryptedIDCard,
|
|
||||||
"authorized": paramsDto.Authorized,
|
|
||||||
}
|
|
||||||
|
|
||||||
respData, err := deps.ZhichaService.CallAPI(ctx, "ZCI006", reqData)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if errors.Is(err, zhicha.ErrDatasource) {
|
if errors.Is(err, nuoer.ErrDatasource) {
|
||||||
return nil, errors.Join(processors.ErrDatasource, err)
|
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字节
|
rawData, ok := resp.Data.(map[string]interface{})
|
||||||
respBytes, err := json.Marshal(respData)
|
if !ok {
|
||||||
|
return nil, errors.Join(processors.ErrSystem, errors.New("响应格式错误"))
|
||||||
|
}
|
||||||
|
|
||||||
|
result := mapNuoerPersonalLawsuitToResponse(rawData)
|
||||||
|
|
||||||
|
respBytes, err := json.Marshal(result)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Join(processors.ErrSystem, err)
|
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/dto"
|
||||||
"tyapi-server/internal/domains/api/services/processors"
|
"tyapi-server/internal/domains/api/services/processors"
|
||||||
"tyapi-server/internal/infrastructure/external/zhicha"
|
"tyapi-server/internal/infrastructure/external/nuoer"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ProcessFLXGDEA9Request FLXGDEA9 API处理方法
|
// ProcessFLXGDEA9Request FLXGDEA9 API处理方法
|
||||||
@@ -21,34 +21,36 @@ func ProcessFLXGDEA9Request(ctx context.Context, params []byte, deps *processors
|
|||||||
return nil, errors.Join(processors.ErrInvalidParam, err)
|
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" {
|
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("查询为空"))
|
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 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)
|
return nil, errors.Join(processors.ErrSystem, err)
|
||||||
}
|
}
|
||||||
reqData := map[string]interface{}{
|
|
||||||
"name": encryptedName,
|
rawData, ok := resp.Data.(map[string]interface{})
|
||||||
"idCard": encryptedIDCard,
|
if !ok {
|
||||||
"authorized": paramsDto.Authorized,
|
return nil, errors.Join(processors.ErrSystem, errors.New("响应格式错误"))
|
||||||
}
|
}
|
||||||
|
|
||||||
respData, err := deps.ZhichaService.CallAPI(ctx, "ZCI005", reqData)
|
result := mapNuoerIdRiskToResponse(rawData)
|
||||||
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(result)
|
||||||
respBytes, err := json.Marshal(respData)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Join(processors.ErrSystem, err)
|
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/dto"
|
||||||
"tyapi-server/internal/domains/api/services/processors"
|
"tyapi-server/internal/domains/api/services/processors"
|
||||||
"tyapi-server/internal/infrastructure/external/zhicha"
|
"tyapi-server/internal/infrastructure/external/nuoer"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ProcessJRZQ3C7BRequest JRZQ3C7B API处理方法 - 借贷意向验证
|
// ProcessJRZQ3C7BRequest JRZQ3C7B API处理方法 - 借贷意向验证
|
||||||
@@ -21,39 +21,34 @@ func ProcessJRZQ3C7BRequest(ctx context.Context, params []byte, deps *processors
|
|||||||
return nil, errors.Join(processors.ErrInvalidParam, err)
|
return nil, errors.Join(processors.ErrInvalidParam, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
encryptedName, err := deps.ZhichaService.Encrypt(paramsDto.Name)
|
body := map[string]string{
|
||||||
if err != nil {
|
"name": paramsDto.Name,
|
||||||
return nil, errors.Join(processors.ErrSystem, err)
|
"idCard": paramsDto.IDCard,
|
||||||
|
"mobile": paramsDto.MobileNo,
|
||||||
}
|
}
|
||||||
|
|
||||||
encryptedIDCard, err := deps.ZhichaService.Encrypt(paramsDto.IDCard)
|
nuoerDoCheckAPIKey := "loanRiskTagV11"
|
||||||
if err != nil {
|
ApiPath := "/v1/doCheck"
|
||||||
return nil, errors.Join(processors.ErrSystem, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
encryptedMobileNo, err := deps.ZhichaService.Encrypt(paramsDto.MobileNo)
|
resp, err := deps.NuoerService.CallAPI(ctx, nuoerDoCheckAPIKey, ApiPath, body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Join(processors.ErrSystem, err)
|
if errors.Is(err, nuoer.ErrDatasource) {
|
||||||
}
|
|
||||||
|
|
||||||
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) {
|
|
||||||
return nil, errors.Join(processors.ErrDatasource, err)
|
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字节
|
rawData, ok := resp.Data.(map[string]interface{})
|
||||||
respBytes, err := json.Marshal(respData)
|
if !ok {
|
||||||
|
return nil, errors.Join(processors.ErrSystem, errors.New("响应格式错误"))
|
||||||
|
}
|
||||||
|
|
||||||
|
result := mapNuoerApplyLoanToResponse(rawData)
|
||||||
|
|
||||||
|
respBytes, err := json.Marshal(result)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Join(processors.ErrSystem, err)
|
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/dto"
|
||||||
"tyapi-server/internal/domains/api/services/processors"
|
"tyapi-server/internal/domains/api/services/processors"
|
||||||
"tyapi-server/internal/infrastructure/external/zhicha"
|
"tyapi-server/internal/infrastructure/external/nuoer"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ProcessJRZQ5E9FRequest JRZQ5E9F API处理方法 - 借选指数
|
// ProcessJRZQ5E9FRequest JRZQ5E9F API处理方法 - 借选指数
|
||||||
@@ -21,39 +21,34 @@ func ProcessJRZQ5E9FRequest(ctx context.Context, params []byte, deps *processors
|
|||||||
return nil, errors.Join(processors.ErrInvalidParam, err)
|
return nil, errors.Join(processors.ErrInvalidParam, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
encryptedName, err := deps.ZhichaService.Encrypt(paramsDto.Name)
|
body := map[string]string{
|
||||||
if err != nil {
|
"name": paramsDto.Name,
|
||||||
return nil, errors.Join(processors.ErrSystem, err)
|
"idCard": paramsDto.IDCard,
|
||||||
|
"mobile": paramsDto.MobileNo,
|
||||||
}
|
}
|
||||||
|
|
||||||
encryptedIDCard, err := deps.ZhichaService.Encrypt(paramsDto.IDCard)
|
nuoerDoCheckAPIKey := "loanRiskTagV21"
|
||||||
if err != nil {
|
ApiPath := "/v1/doCheck"
|
||||||
return nil, errors.Join(processors.ErrSystem, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
encryptedMobileNo, err := deps.ZhichaService.Encrypt(paramsDto.MobileNo)
|
resp, err := deps.NuoerService.CallAPI(ctx, nuoerDoCheckAPIKey, ApiPath, body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Join(processors.ErrSystem, err)
|
if errors.Is(err, nuoer.ErrDatasource) {
|
||||||
}
|
|
||||||
|
|
||||||
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) {
|
|
||||||
return nil, errors.Join(processors.ErrDatasource, err)
|
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字节
|
rawData, ok := resp.Data.(map[string]interface{})
|
||||||
respBytes, err := json.Marshal(respData)
|
if !ok {
|
||||||
|
return nil, errors.Join(processors.ErrSystem, errors.New("响应格式错误"))
|
||||||
|
}
|
||||||
|
|
||||||
|
result := mapNuoerLoanRiskToResponse(rawData)
|
||||||
|
|
||||||
|
respBytes, err := json.Marshal(result)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Join(processors.ErrSystem, err)
|
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/dto"
|
||||||
"tyapi-server/internal/domains/api/services/processors"
|
"tyapi-server/internal/domains/api/services/processors"
|
||||||
"tyapi-server/internal/infrastructure/external/zhicha"
|
"tyapi-server/internal/infrastructure/external/nuoer"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ProcessJRZQ8A2DRequest JRZQ8A2D API处理方法 - 特殊名单验证
|
// ProcessJRZQ8A2DRequest JRZQ8A2D API处理方法 - 特殊名单验证
|
||||||
@@ -20,40 +20,55 @@ func ProcessJRZQ8A2DRequest(ctx context.Context, params []byte, deps *processors
|
|||||||
if err := deps.Validator.ValidateStruct(paramsDto); err != nil {
|
if err := deps.Validator.ValidateStruct(paramsDto); err != nil {
|
||||||
return nil, errors.Join(processors.ErrInvalidParam, err)
|
return nil, errors.Join(processors.ErrInvalidParam, err)
|
||||||
}
|
}
|
||||||
encryptedName, err := deps.ZhichaService.Encrypt(paramsDto.Name)
|
|
||||||
if err != nil {
|
body := map[string]string{
|
||||||
return nil, errors.Join(processors.ErrSystem, err)
|
"name": paramsDto.Name,
|
||||||
}
|
"idCard": paramsDto.IDCard,
|
||||||
encryptedIDCard, err := deps.ZhichaService.Encrypt(paramsDto.IDCard)
|
"mobile": paramsDto.MobileNo,
|
||||||
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{}{
|
nuoerDoCheckAPIKey := "loanRiskTagV12"
|
||||||
"name": encryptedName,
|
ApiPath := "/v1/doCheck"
|
||||||
"idCard": encryptedIDCard,
|
|
||||||
"phone": encryptedMobileNo,
|
|
||||||
"authorized": paramsDto.Authorized,
|
|
||||||
}
|
|
||||||
|
|
||||||
respData, err := deps.ZhichaService.CallAPI(ctx, "ZCI018", reqData)
|
resp, err := deps.NuoerService.CallAPI(ctx, nuoerDoCheckAPIKey, ApiPath, body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if errors.Is(err, zhicha.ErrDatasource) {
|
if errors.Is(err, nuoer.ErrDatasource) {
|
||||||
return nil, errors.Join(processors.ErrDatasource, err)
|
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字节
|
rawData, ok := resp.Data.(map[string]interface{})
|
||||||
respBytes, err := json.Marshal(respData)
|
if !ok {
|
||||||
|
return nil, errors.Join(processors.ErrSystem, errors.New("响应格式错误"))
|
||||||
|
}
|
||||||
|
|
||||||
|
result := mapNuoerSpecialListToResponse(rawData)
|
||||||
|
|
||||||
|
respBytes, err := json.Marshal(result)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Join(processors.ErrSystem, err)
|
return nil, errors.Join(processors.ErrSystem, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return respBytes, nil
|
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/dto"
|
||||||
"tyapi-server/internal/domains/api/services/processors"
|
"tyapi-server/internal/domains/api/services/processors"
|
||||||
"tyapi-server/internal/infrastructure/external/westdex"
|
"tyapi-server/internal/infrastructure/external/nuoer"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ProcessQYGL6F2DRequest QYGL6F2D API处理方法
|
// ProcessQYGL6F2DRequest QYGL6F2D API处理方法
|
||||||
@@ -20,26 +20,35 @@ func ProcessQYGL6F2DRequest(ctx context.Context, params []byte, deps *processors
|
|||||||
if err := deps.Validator.ValidateStruct(paramsDto); err != nil {
|
if err := deps.Validator.ValidateStruct(paramsDto); err != nil {
|
||||||
return nil, errors.Join(processors.ErrInvalidParam, err)
|
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 {
|
if err != nil {
|
||||||
return nil, errors.Join(processors.ErrSystem, err)
|
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
|
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)
|
nuoerErr := NewNuoerError(nuoerResp.Code, nuoerResp.Msg)
|
||||||
err = errors.Join(GetErrByPlatformCode(nuoerResp.Code), nuoerErr)
|
err = errors.Join(GetErrByPlatformCode(nuoerResp.Code), nuoerErr)
|
||||||
if s.logger != nil {
|
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
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -164,7 +164,7 @@ func (s *NuoerService) CallAPI(ctx context.Context, apiKey, apiPath string, body
|
|||||||
if nuoerResp.Data == nil {
|
if nuoerResp.Data == nil {
|
||||||
err = errors.Join(ErrSystem, errors.New("响应 data 为空"))
|
err = errors.Join(ErrSystem, errors.New("响应 data 为空"))
|
||||||
if s.logger != nil {
|
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
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -173,7 +173,7 @@ func (s *NuoerService) CallAPI(ctx context.Context, apiKey, apiPath string, body
|
|||||||
if !ok {
|
if !ok {
|
||||||
err = errors.Join(ErrSystem, errors.New("响应 data 无法解析 busiCode"))
|
err = errors.Join(ErrSystem, errors.New("响应 data 无法解析 busiCode"))
|
||||||
if s.logger != nil {
|
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
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -182,7 +182,7 @@ func (s *NuoerService) CallAPI(ctx context.Context, apiKey, apiPath string, body
|
|||||||
busiErr := NewNuoerBusiError(busiCode, busiMsg)
|
busiErr := NewNuoerBusiError(busiCode, busiMsg)
|
||||||
err = errors.Join(GetErrByBusiCode(busiCode), busiErr)
|
err = errors.Join(GetErrByBusiCode(busiCode), busiErr)
|
||||||
if s.logger != nil {
|
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
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -191,7 +191,7 @@ func (s *NuoerService) CallAPI(ctx context.Context, apiKey, apiPath string, body
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
err = errors.Join(ErrSystem, fmt.Errorf("响应 data 清理失败: %w", err))
|
err = errors.Join(ErrSystem, fmt.Errorf("响应 data 清理失败: %w", err))
|
||||||
if s.logger != nil {
|
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
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user