From b1f573c2302499e062c179f38ed979190f9d824b Mon Sep 17 00:00:00 2001 From: Mrx <18278715334@163.com> Date: Wed, 28 Jan 2026 12:21:21 +0800 Subject: [PATCH 1/5] f --- .../processors/qygl/qygl3f8e_processor.go | 348 +++++++++++++++++- .../external/shumai/shumai_service.go | 4 +- 2 files changed, 330 insertions(+), 22 deletions(-) diff --git a/internal/domains/api/services/processors/qygl/qygl3f8e_processor.go b/internal/domains/api/services/processors/qygl/qygl3f8e_processor.go index 507d91b..3f41b4c 100644 --- a/internal/domains/api/services/processors/qygl/qygl3f8e_processor.go +++ b/internal/domains/api/services/processors/qygl/qygl3f8e_processor.go @@ -15,18 +15,28 @@ import ( "tyapi-server/internal/domains/api/dto" "tyapi-server/internal/domains/api/services/processors" + "tyapi-server/internal/shared/logger" "github.com/tidwall/gjson" + "go.uber.org/zap" ) // ProcessQYGL3F8ERequest QYGL3F8E API处理方法 - 人企关系加强版 func ProcessQYGL3F8ERequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { + // 使用 zap.L() 获取全局日志器 + log := logger.L() + + // 记录请求开始 + log.Info("QYGL3F8E处理器开始处理请求") + var paramsDto dto.QYGL3F8EReq if err := json.Unmarshal(params, ¶msDto); err != nil { + log.Error("QYGL3F8E参数解析失败", zap.Error(err)) return nil, errors.Join(processors.ErrSystem, err) } if err := deps.Validator.ValidateStruct(paramsDto); err != nil { + log.Warn("QYGL3F8E参数验证失败", zap.Error(err)) return nil, errors.Join(processors.ErrInvalidParam, err) } @@ -40,22 +50,30 @@ func ProcessQYGL3F8ERequest(ctx context.Context, params []byte, deps *processors } b4c0ParamsBytes, err := json.Marshal(b4c0Params) if err != nil { + log.Error("QYGL3F8E构建QYGL6S1B参数失败", zap.Error(err)) return nil, errors.Join(processors.ErrSystem, err) } b4c0Response, err := ProcessQYGL6S1BRequest(ctx, b4c0ParamsBytes, deps) if err != nil { + log.Error("QYGL3F8E调用QYGL6S1B失败", zap.Error(err)) return nil, err // 错误已经是处理器标准错误,直接返回 } // 2. 解析QYGL6S1B的响应,获取企业列表 companies, err := parseCompaniesFrom6S1BResponse(b4c0Response) if err != nil { + log.Error("QYGL3F8E解析QYGL6S1B响应失败", zap.Error(err)) return nil, errors.Join(processors.ErrSystem, err) } + log.Info("QYGL3F8E解析企业列表完成", + zap.Int("total_companies", len(companies)), + ) + if len(companies) == 0 { // 没有关联企业,返回空的简化格式 + log.Info("QYGL3F8E未找到关联企业,返回空结果") emptyResponse := map[string]interface{}{ "items": []interface{}{}, "total": 0, @@ -78,15 +96,22 @@ func ProcessQYGL3F8ERequest(ctx context.Context, params []byte, deps *processors // 5. 并发调用其他处理器获取企业详细信息 enrichedCompanies, err := enrichCompaniesWithDetails(ctx, sortedCompanies[:processCount], userIDCard, deps) if err != nil { + log.Error("QYGL3F8E并发获取企业详细信息失败", zap.Error(err)) return nil, errors.Join(processors.ErrSystem, err) } // 6. 构建最终响应 finalResponse, err := buildFinalResponse(enrichedCompanies, sortedCompanies) if err != nil { + log.Error("QYGL3F8E构建最终响应失败", zap.Error(err)) return nil, errors.Join(processors.ErrSystem, err) } + log.Info("QYGL3F8E处理器处理完成", + zap.Int("response_size", len(finalResponse)), + zap.Int("total_companies", len(sortedCompanies)), + ) + return finalResponse, nil } @@ -288,6 +313,8 @@ type EnrichedCompanyInfo struct { // enrichCompaniesWithDetails 并发调用其他处理器获取企业详细信息 func enrichCompaniesWithDetails(ctx context.Context, companies []CompanyInfo, idCard string, deps *processors.ProcessorDependencies) ([]EnrichedCompanyInfo, error) { + log := logger.L() + var wg sync.WaitGroup results := make(chan struct { index int @@ -307,54 +334,210 @@ func enrichCompaniesWithDetails(ctx context.Context, companies []CompanyInfo, id // 并发调用多个处理器 var detailWg sync.WaitGroup + var detailMu sync.Mutex + + // 用于跟踪每个处理器的调用结果 + type processorResult struct { + processorType string + status string // "success", "empty", "error" + err error + hasData bool + } + processorResults := make([]processorResult, 0, 7) // 调用QYGL5A3C - 对外投资历史 detailWg.Add(1) go func() { defer detailWg.Done() - enriched.InvestHistory = callProcessorSafely(ctx, "QYGL5A3C", comp.CreditCode, deps) + result := callProcessorSafely(ctx, "QYGL5A3C", comp.CreditCode, deps) + + enriched.InvestHistory = result + hasData := false + if resultMap, ok := result.(map[string]interface{}); ok { + hasData = len(resultMap) > 0 + } else if resultArray, ok := result.([]interface{}); ok { + hasData = len(resultArray) > 0 + } + + detailMu.Lock() + status := "success" + if !hasData { + status = "empty" + } + processorResults = append(processorResults, processorResult{ + processorType: "QYGL5A3C", + status: status, + hasData: hasData, + }) + detailMu.Unlock() }() // 调用QYGL8B4D - 融资历史 detailWg.Add(1) go func() { defer detailWg.Done() - enriched.FinancingHistory = callProcessorSafely(ctx, "QYGL8B4D", comp.CreditCode, deps) + result := callProcessorSafely(ctx, "QYGL8B4D", comp.CreditCode, deps) + + enriched.FinancingHistory = result + hasData := false + if resultMap, ok := result.(map[string]interface{}); ok { + hasData = len(resultMap) > 0 + } else if resultArray, ok := result.([]interface{}); ok { + hasData = len(resultArray) > 0 + } + + detailMu.Lock() + status := "success" + if !hasData { + status = "empty" + } + processorResults = append(processorResults, processorResult{ + processorType: "QYGL8B4D", + status: status, + hasData: hasData, + }) + detailMu.Unlock() }() // 调用QYGL9E2F - 行政处罚 detailWg.Add(1) go func() { defer detailWg.Done() - enriched.PunishmentInfo = callProcessorSafely(ctx, "QYGL9E2F", comp.CreditCode, deps) + result := callProcessorSafely(ctx, "QYGL9E2F", comp.CreditCode, deps) + + enriched.PunishmentInfo = result + hasData := false + if resultMap, ok := result.(map[string]interface{}); ok { + hasData = len(resultMap) > 0 + } else if resultArray, ok := result.([]interface{}); ok { + hasData = len(resultArray) > 0 + } + + detailMu.Lock() + status := "success" + if !hasData { + status = "empty" + } + processorResults = append(processorResults, processorResult{ + processorType: "QYGL9E2F", + status: status, + hasData: hasData, + }) + detailMu.Unlock() }() // 调用QYGL7C1A - 经营异常 detailWg.Add(1) go func() { defer detailWg.Done() - enriched.AbnormalInfo = callProcessorSafely(ctx, "QYGL7C1A", comp.CreditCode, deps) + result := callProcessorSafely(ctx, "QYGL7C1A", comp.CreditCode, deps) + + enriched.AbnormalInfo = result + hasData := false + if resultMap, ok := result.(map[string]interface{}); ok { + hasData = len(resultMap) > 0 + } else if resultArray, ok := result.([]interface{}); ok { + hasData = len(resultArray) > 0 + } + + detailMu.Lock() + status := "success" + if !hasData { + status = "empty" + } + processorResults = append(processorResults, processorResult{ + processorType: "QYGL7C1A", + status: status, + hasData: hasData, + }) + detailMu.Unlock() }() // 调用QYGL66SL- 企业涉诉信息 - // detailWg.Add(1) - // go func() { - // defer detailWg.Done() - // enriched.LawsuitInfo = callQYGL66SLProcessorSafely(ctx, comp.CreditCode, comp.Name, deps) - // }() + detailWg.Add(1) + go func() { + defer detailWg.Done() + result := callQYGL66SLProcessorSafely(ctx, comp.CreditCode, comp.Name, deps) + + enriched.LawsuitInfo = result + // QYGL66SL返回的是特殊格式,需要检查是否有数据 + hasData := false + if resultMap, ok := result.(map[string]interface{}); ok { + for _, v := range resultMap { + if vMap, ok := v.(map[string]interface{}); ok { + if msg, ok := vMap["msg"].(string); ok && msg == "成功" { + hasData = true + break + } + } + } + } + + detailMu.Lock() + status := "success" + if !hasData { + status = "empty" + } + processorResults = append(processorResults, processorResult{ + processorType: "QYGL66SL", + status: status, + hasData: hasData, + }) + detailMu.Unlock() + }() // 调用QYGL7D9A - 欠税公告 detailWg.Add(1) go func() { defer detailWg.Done() - enriched.OwnTax = callProcessorSafely(ctx, "QYGL7D9A", comp.CreditCode, deps) + result := callProcessorSafely(ctx, "QYGL7D9A", comp.CreditCode, deps) + + enriched.OwnTax = result + hasData := false + if resultMap, ok := result.(map[string]interface{}); ok { + hasData = len(resultMap) > 0 + } else if resultArray, ok := result.([]interface{}); ok { + hasData = len(resultArray) > 0 + } + + detailMu.Lock() + status := "success" + if !hasData { + status = "empty" + } + processorResults = append(processorResults, processorResult{ + processorType: "QYGL7D9A", + status: status, + hasData: hasData, + }) + detailMu.Unlock() }() // 调用QYGL4B2E - 税收违法 detailWg.Add(1) go func() { defer detailWg.Done() - enriched.TaxContravention = callProcessorSafely(ctx, "QYGL4B2E", comp.CreditCode, deps) + result := callProcessorSafely(ctx, "QYGL4B2E", comp.CreditCode, deps) + + enriched.TaxContravention = result + hasData := false + if resultMap, ok := result.(map[string]interface{}); ok { + hasData = len(resultMap) > 0 + } else if resultArray, ok := result.([]interface{}); ok { + hasData = len(resultArray) > 0 + } + + detailMu.Lock() + status := "success" + if !hasData { + status = "empty" + } + processorResults = append(processorResults, processorResult{ + processorType: "QYGL4B2E", + status: status, + hasData: hasData, + }) + detailMu.Unlock() }() detailWg.Wait() @@ -377,6 +560,10 @@ func enrichCompaniesWithDetails(ctx context.Context, companies []CompanyInfo, id enrichedCompanies := make([]EnrichedCompanyInfo, len(companies)) for result := range results { if result.err != nil { + log.Error("QYGL3F8E企业处理失败", + zap.Int("index", result.index), + zap.Error(result.err), + ) return nil, result.err } enrichedCompanies[result.index] = result.data @@ -387,6 +574,8 @@ func enrichCompaniesWithDetails(ctx context.Context, companies []CompanyInfo, id // callProcessorSafely 安全调用处理器(处理可能的错误) func callProcessorSafely(ctx context.Context, processorType, entCode string, deps *processors.ProcessorDependencies) interface{} { + log := logger.L() + // 构建请求参数 params := map[string]interface{}{ "ent_code": entCode, @@ -396,6 +585,11 @@ func callProcessorSafely(ctx context.Context, processorType, entCode string, dep paramsBytes, err := json.Marshal(params) if err != nil { + log.Warn("QYGL3F8E构建处理器参数失败", + zap.String("processor_type", processorType), + zap.String("ent_code", entCode), + zap.Error(err), + ) return map[string]interface{}{} } @@ -414,21 +608,38 @@ func callProcessorSafely(ctx context.Context, processorType, entCode string, dep case "QYGL4B2E": response, err = ProcessQYGL4B2ERequest(ctx, paramsBytes, deps) default: + log.Warn("QYGL3F8E未知的处理器类型", + zap.String("processor_type", processorType), + ) return map[string]interface{}{} } if err != nil { // 如果是查询为空错误,返回空对象 if errors.Is(err, processors.ErrNotFound) { + log.Debug("QYGL3F8E子处理器查询结果为空(正常情况)", + zap.String("processor_type", processorType), + zap.String("ent_code", entCode), + ) return map[string]interface{}{} } // 其他错误也返回空对象,避免影响整体流程 + log.Warn("QYGL3F8E子处理器调用失败(已忽略错误)", + zap.String("processor_type", processorType), + zap.String("ent_code", entCode), + zap.Error(err), + ) return map[string]interface{}{} } // 解析响应 var result interface{} if err := json.Unmarshal(response, &result); err != nil { + log.Warn("QYGL3F8E子处理器响应解析失败", + zap.String("processor_type", processorType), + zap.String("ent_code", entCode), + zap.Error(err), + ) return map[string]interface{}{} } @@ -437,25 +648,99 @@ func callProcessorSafely(ctx context.Context, processorType, entCode string, dep // callProcessorSafely 安全调用处理器 func callQYGL66SLProcessorSafely(ctx context.Context, entCode string, entName string, deps *processors.ProcessorDependencies) interface{} { + // 使用 zap.L() 获取全局日志器,它会使用 zap.ReplaceGlobals 设置的日志器 + // 这样可以确保使用配置文件中的按级别分文件设置 + log := logger.L() + + // 参数验证:确保必填字段不为空 + if entName == "" { + log.Warn("QYGL66SL处理器调用失败:企业名称为空", + zap.String("ent_code", entCode), + ) + return buildEmptyQYGL66SLResponse() + } + + // 使用 QYGL66SLReq 的 json 键名:ent_code, ent_name, auth_date, auth_authorize_file_code + // 处理器内部会再映射为 API 的 orgName/uscc/inquiredAuth/authAuthorizeFileCode + authDate := generateAuthDateRange() + authFileCode := generateAuthAuthorizeFileCode() params := map[string]interface{}{ - "orgName": entName, - "inquiredAuth": "authed:" + generateAuthDateRange(), - "uscc": entCode, - "authAuthorizeFileCode": generateAuthAuthorizeFileCode(), + "ent_code": entCode, // 可选字段,可以为空 + "ent_name": entName, + "auth_date": authDate, + "auth_authorize_file_code": authFileCode, } + paramsBytes, err := json.Marshal(params) if err != nil { + log.Error("QYGL66SL处理器参数序列化失败", + zap.Error(err), + zap.String("ent_code", entCode), + zap.String("ent_name", entName), + zap.String("auth_date", authDate), + zap.String("auth_authorize_file_code", authFileCode), + ) return buildEmptyQYGL66SLResponse() } + response, err := ProcessQYGL66SLRequest(ctx, paramsBytes, deps) if err != nil { - return buildEmptyQYGL66SLResponse() + // 检查错误类型,区分不同的失败原因并记录详细日志 + if errors.Is(err, processors.ErrInvalidParam) { + log.Warn("QYGL66SL处理器参数验证失败", + zap.Error(err), + zap.String("ent_code", entCode), + zap.String("ent_name", entName), + zap.String("auth_date", authDate), + zap.String("auth_authorize_file_code", authFileCode), + zap.String("error_type", "ErrInvalidParam"), + zap.String("可能原因", "auth_date格式不符合要求或ent_name格式不正确"), + ) + return buildEmptyQYGL66SLResponse() + } else if errors.Is(err, processors.ErrNotFound) { + log.Error("QYGL66SL查询结果为空(正常业务情况)", + zap.String("ent_code", entCode), + zap.String("ent_name", entName), + zap.String("error_type", "ErrNotFound"), + ) + return buildEmptyQYGL66SLResponse() + } else if errors.Is(err, processors.ErrDatasource) { + log.Error("QYGL66SL数据源错误", + zap.Error(err), + zap.String("ent_code", entCode), + zap.String("ent_name", entName), + zap.String("error_type", "ErrDatasource"), + ) + return buildEmptyQYGL66SLResponse() + } else { + log.Error("QYGL66SL处理器调用失败(系统错误)", + zap.Error(err), + zap.String("ent_code", entCode), + zap.String("ent_name", entName), + zap.String("auth_date", authDate), + zap.String("error_type", "ErrSystem"), + zap.String("可能原因", "网络问题、超时、API调用失败等"), + ) + return buildEmptyQYGL66SLResponse() + } } // 解析响应 var result interface{} if err := json.Unmarshal(response, &result); err != nil { + // 只记录前200字符的响应预览 + responsePreview := string(response) + if len(responsePreview) > 200 { + responsePreview = responsePreview[:200] + "..." + } + log.Error("QYGL66SL响应解析失败", + zap.Error(err), + zap.String("ent_code", entCode), + zap.String("ent_name", entName), + zap.String("response_preview", responsePreview), + zap.String("可能原因", "API返回了非JSON格式的数据"), + ) return buildEmptyQYGL66SLResponse() } @@ -596,6 +881,19 @@ func cleanEntoutData(data map[string]interface{}) map[string]interface{} { "crc": cleanNumericValue, } + // 定义需要保留结构的字段(即使清理后为空也要保留) + structuralFields := map[string]bool{ + "cases_tree": true, + "civil": true, + "criminal": true, + "administrative": true, + "bankrupt": true, + "implement": true, + "preservation": true, + "count": true, + "crc": true, + } + // 处理所有字段,确保所有字段都被正确映射 for key, value := range data { if value == nil { @@ -608,11 +906,11 @@ func cleanEntoutData(data map[string]interface{}) map[string]interface{} { } else { // 对于其他字段(如 cases_tree, civil, implement 等),使用 cleanValue 处理 cleanedValue := cleanValue(value) - // 只有当清理后的值不为空时才添加 - if !isEmptyValue(cleanedValue) { + // 如果是结构字段,即使清理后为空也保留 + if structuralFields[key] { cleaned[key] = cleanedValue - } else if key == "cases_tree" { - // cases_tree 即使是空对象也保留,因为它是重要的结构字段 + } else if !isEmptyValue(cleanedValue) { + // 非结构字段,只有当清理后的值不为空时才添加 cleaned[key] = cleanedValue } } @@ -867,6 +1165,16 @@ func isEmptyMap(data map[string]interface{}) bool { // hasValidEntoutData 检查 entout 是否有有效数据 func hasValidEntoutData(data map[string]interface{}) bool { + // 如果数据中有任何结构字段存在,就认为有数据(即使清理后为空) + // 这样可以确保即使所有字段都是 "-",也能返回结构化的数据 + structuralFields := []string{"civil", "criminal", "administrative", "bankrupt", "implement", "preservation", "cases_tree", "count", "crc"} + + for _, field := range structuralFields { + if _, exists := data[field]; exists { + return true + } + } + // 检查各个案件类型是否有有效数据 caseTypes := []string{"civil", "criminal", "administrative", "bankrupt", "implement", "preservation"} diff --git a/internal/infrastructure/external/shumai/shumai_service.go b/internal/infrastructure/external/shumai/shumai_service.go index 2235b29..1fc8a54 100644 --- a/internal/infrastructure/external/shumai/shumai_service.go +++ b/internal/infrastructure/external/shumai/shumai_service.go @@ -139,7 +139,7 @@ func (s *ShumaiService) CallAPIForm(ctx context.Context, apiPath string, reqForm startTime := time.Now() timestamp := strconv.FormatInt(time.Now().UnixMilli(), 10) - + // 根据参数选择使用的 AppID 和 AppSecret,而不是依赖全局状态 var appID, appSecret string if useGov && s.config.AppID2 != "" { @@ -149,7 +149,7 @@ func (s *ShumaiService) CallAPIForm(ctx context.Context, apiPath string, reqForm appID = s.config.AppID appSecret = s.config.AppSecret } - + // 使用指定的 AppID 生成请求ID requestID := s.generateRequestIDWithAppID(appID) sign := GenerateSignForm(appID, timestamp, appSecret) From b2f0b478961afbe13b5e5b7823bac56730e4f6c8 Mon Sep 17 00:00:00 2001 From: Mrx <18278715334@163.com> Date: Wed, 28 Jan 2026 15:55:38 +0800 Subject: [PATCH 2/5] =?UTF-8?q?f=20=E5=8E=BB=E6=8E=8966sl?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../processors/qygl/qygl3f8e_processor.go | 58 +++++++++---------- .../processors/yysy/yysyf7db_processor.go | 2 +- 2 files changed, 30 insertions(+), 30 deletions(-) diff --git a/internal/domains/api/services/processors/qygl/qygl3f8e_processor.go b/internal/domains/api/services/processors/qygl/qygl3f8e_processor.go index 3f41b4c..0db5a7e 100644 --- a/internal/domains/api/services/processors/qygl/qygl3f8e_processor.go +++ b/internal/domains/api/services/processors/qygl/qygl3f8e_processor.go @@ -454,37 +454,37 @@ func enrichCompaniesWithDetails(ctx context.Context, companies []CompanyInfo, id }() // 调用QYGL66SL- 企业涉诉信息 - detailWg.Add(1) - go func() { - defer detailWg.Done() - result := callQYGL66SLProcessorSafely(ctx, comp.CreditCode, comp.Name, deps) + // detailWg.Add(1) + // go func() { + // defer detailWg.Done() + // result := callQYGL66SLProcessorSafely(ctx, comp.CreditCode, comp.Name, deps) - enriched.LawsuitInfo = result - // QYGL66SL返回的是特殊格式,需要检查是否有数据 - hasData := false - if resultMap, ok := result.(map[string]interface{}); ok { - for _, v := range resultMap { - if vMap, ok := v.(map[string]interface{}); ok { - if msg, ok := vMap["msg"].(string); ok && msg == "成功" { - hasData = true - break - } - } - } - } + // enriched.LawsuitInfo = result + // // QYGL66SL返回的是特殊格式,需要检查是否有数据 + // hasData := false + // if resultMap, ok := result.(map[string]interface{}); ok { + // for _, v := range resultMap { + // if vMap, ok := v.(map[string]interface{}); ok { + // if msg, ok := vMap["msg"].(string); ok && msg == "成功" { + // hasData = true + // break + // } + // } + // } + // } - detailMu.Lock() - status := "success" - if !hasData { - status = "empty" - } - processorResults = append(processorResults, processorResult{ - processorType: "QYGL66SL", - status: status, - hasData: hasData, - }) - detailMu.Unlock() - }() + // detailMu.Lock() + // status := "success" + // if !hasData { + // status = "empty" + // } + // processorResults = append(processorResults, processorResult{ + // processorType: "QYGL66SL", + // status: status, + // hasData: hasData, + // }) + // detailMu.Unlock() + // }() // 调用QYGL7D9A - 欠税公告 detailWg.Add(1) diff --git a/internal/domains/api/services/processors/yysy/yysyf7db_processor.go b/internal/domains/api/services/processors/yysy/yysyf7db_processor.go index 0cd6b03..61922aa 100644 --- a/internal/domains/api/services/processors/yysy/yysyf7db_processor.go +++ b/internal/domains/api/services/processors/yysy/yysyf7db_processor.go @@ -43,4 +43,4 @@ func ProcessYYSYF7DBRequest(ctx context.Context, params []byte, deps *processors } return respBytes, nil -} \ No newline at end of file +} From 482644a914525be99950c60b0494aabcbe9d6804 Mon Sep 17 00:00:00 2001 From: Mrx <18278715334@163.com> Date: Wed, 28 Jan 2026 16:21:57 +0800 Subject: [PATCH 3/5] f --- internal/domains/api/dto/api_request_dto.go | 5 ++ .../api/services/api_request_service.go | 1 + .../api/services/form_config_service.go | 3 +- .../processors/qygl/qygl5s1_processor.go | 56 +++++++++++++++++++ .../processors/yysy/yysyf7db_processor.go | 21 ++++++- 5 files changed, 84 insertions(+), 2 deletions(-) create mode 100644 internal/domains/api/services/processors/qygl/qygl5s1_processor.go diff --git a/internal/domains/api/dto/api_request_dto.go b/internal/domains/api/dto/api_request_dto.go index 37d3997..37f5e26 100644 --- a/internal/domains/api/dto/api_request_dto.go +++ b/internal/domains/api/dto/api_request_dto.go @@ -898,6 +898,11 @@ type YYSYF2T7Req struct { DateRange string `json:"date_range" validate:"required,validAuthDate" ` } +type QYGL5S1Req struct { + EntCode string `json:"ent_code" validate:"omitempty,validUSCI"` + EntName string `json:"ent_name" validate:"required,min=1,validEnterpriseName"` +} + // 数脉 API type IVYZ3M8SReq struct { Name string `json:"name" validate:"required,min=1,validName"` diff --git a/internal/domains/api/services/api_request_service.go b/internal/domains/api/services/api_request_service.go index fe9c8bb..13b192c 100644 --- a/internal/domains/api/services/api_request_service.go +++ b/internal/domains/api/services/api_request_service.go @@ -173,6 +173,7 @@ func registerAllProcessors(combService *comb.CombService) { "QYGL2NAO": qygl.ProcessQYGL2naoRequest, //股权变更 "QYGLNIO8": qygl.ProcessQYGLNIO8Request, //企业基本信息 "QYGLP0HT": qygl.ProcessQYGLP0HTRequest, //股权穿透 + "QYGL5S1": qygl.ProcessQYGL5S1Request, //企业司法涉诉V2 // YYSY系列处理器 "YYSYD50F": yysy.ProcessYYSYD50FRequest, diff --git a/internal/domains/api/services/form_config_service.go b/internal/domains/api/services/form_config_service.go index 81eeb1d..6072004 100644 --- a/internal/domains/api/services/form_config_service.go +++ b/internal/domains/api/services/form_config_service.go @@ -172,7 +172,7 @@ func (s *FormConfigServiceImpl) getDTOStruct(ctx context.Context, apiCode string "IVYZ6G7H": &dto.IVYZ6G7HReq{}, "IVYZ8I9J": &dto.IVYZ8I9JReq{}, "JRZQ0L85": &dto.JRZQ0L85Req{}, - "COMBHZY2": &dto.COMBHZY2Req{}, // 自此无imp11.28 + "COMBHZY2": &dto.COMBHZY2Req{}, // "QCXG8A3D": &dto.QCXG8A3DReq{}, "QCXG6B4E": &dto.QCXG6B4EReq{}, "QYGL2B5C": &dto.QYGL2B5CReq{}, @@ -243,6 +243,7 @@ func (s *FormConfigServiceImpl) getDTOStruct(ctx context.Context, apiCode string "YYSYH6F3": &dto.YYSYH6F3Req{}, //运营商三要素简版即时版查询 "IVYZX5Q2": &dto.IVYZX5Q2Req{}, //活体识别步骤二 "PDFG01GZ": &dto.PDFG01GZReq{}, // + "QYGL5S1": &dto.QYGL5S1Req{}, //企业司法涉诉V2 } // 优先返回已配置的DTO diff --git a/internal/domains/api/services/processors/qygl/qygl5s1_processor.go b/internal/domains/api/services/processors/qygl/qygl5s1_processor.go new file mode 100644 index 0000000..4c4df3c --- /dev/null +++ b/internal/domains/api/services/processors/qygl/qygl5s1_processor.go @@ -0,0 +1,56 @@ +package qygl + +import ( + "context" + "encoding/json" + "errors" + + "tyapi-server/internal/domains/api/dto" + "tyapi-server/internal/domains/api/services/processors" + "tyapi-server/internal/infrastructure/external/zhicha" +) + +// ProcessQYGL5S1Request QYGL5S1 API处理方法 - 企业司法涉诉V2 +func ProcessQYGL5S1Request(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { + + var paramsDto dto.QYGL5S1Req + 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) + } + + encryptedEntCode, err := deps.ZhichaService.Encrypt(paramsDto.EntCode) + if err != nil { + return nil, errors.Join(processors.ErrSystem, err) + } + + encryptedEntName, err := deps.ZhichaService.Encrypt(paramsDto.EntName) + if err != nil { + return nil, errors.Join(processors.ErrSystem, err) + } + + reqData := map[string]interface{}{ + "enterpriseNo": encryptedEntCode, + "enterpriseName": encryptedEntName, + } + + respData, err := deps.ZhichaService.CallAPI(ctx, "ZCI088", 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 +} diff --git a/internal/domains/api/services/processors/yysy/yysyf7db_processor.go b/internal/domains/api/services/processors/yysy/yysyf7db_processor.go index 61922aa..ae4be9c 100644 --- a/internal/domains/api/services/processors/yysy/yysyf7db_processor.go +++ b/internal/domains/api/services/processors/yysy/yysyf7db_processor.go @@ -10,6 +10,21 @@ import ( "tyapi-server/internal/infrastructure/external/westdex" ) +// YYSYF7DBResponse 手机二次卡查询成功响应 +type YYSYF7DBResponse struct { + Code string `json:"code"` + Data YYSYF7DBResponseData `json:"data"` +} + +// YYSYF7DBResponseData 手机二次卡 data 结构 +type YYSYF7DBResponseData struct { + Code int `json:"code"` + EncryptType string `json:"encryptType"` + Guid string `json:"guid"` + Msg string `json:"msg"` + PhoneType string `json:"phoneType"` +} + // ProcessYYSYF7DBRequest YYSYF7DB API处理方法 func ProcessYYSYF7DBRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { var paramsDto dto.YYSYF7DBReq @@ -42,5 +57,9 @@ func ProcessYYSYF7DBRequest(ctx context.Context, params []byte, deps *processors } } - return respBytes, nil + var mapped YYSYF7DBResponse + if err := json.Unmarshal(respBytes, &mapped); err != nil { + return nil, errors.Join(processors.ErrSystem, err) + } + return json.Marshal(mapped) } From 7e5a69ffaa2920abe0663188ea750c342fcca920 Mon Sep 17 00:00:00 2001 From: Mrx <18278715334@163.com> Date: Wed, 28 Jan 2026 16:25:40 +0800 Subject: [PATCH 4/5] f --- internal/domains/api/dto/api_request_dto.go | 2 +- internal/domains/api/services/api_request_service.go | 2 +- internal/domains/api/services/form_config_service.go | 2 +- .../qygl/{qygl5s1_processor.go => qygl5s1i_processor.go} | 6 +++--- 4 files changed, 6 insertions(+), 6 deletions(-) rename internal/domains/api/services/processors/qygl/{qygl5s1_processor.go => qygl5s1i_processor.go} (85%) diff --git a/internal/domains/api/dto/api_request_dto.go b/internal/domains/api/dto/api_request_dto.go index 37f5e26..cdb6046 100644 --- a/internal/domains/api/dto/api_request_dto.go +++ b/internal/domains/api/dto/api_request_dto.go @@ -898,7 +898,7 @@ type YYSYF2T7Req struct { DateRange string `json:"date_range" validate:"required,validAuthDate" ` } -type QYGL5S1Req struct { +type QYGL5S1IReq struct { EntCode string `json:"ent_code" validate:"omitempty,validUSCI"` EntName string `json:"ent_name" validate:"required,min=1,validEnterpriseName"` } diff --git a/internal/domains/api/services/api_request_service.go b/internal/domains/api/services/api_request_service.go index 13b192c..04a8b1d 100644 --- a/internal/domains/api/services/api_request_service.go +++ b/internal/domains/api/services/api_request_service.go @@ -173,7 +173,7 @@ func registerAllProcessors(combService *comb.CombService) { "QYGL2NAO": qygl.ProcessQYGL2naoRequest, //股权变更 "QYGLNIO8": qygl.ProcessQYGLNIO8Request, //企业基本信息 "QYGLP0HT": qygl.ProcessQYGLP0HTRequest, //股权穿透 - "QYGL5S1": qygl.ProcessQYGL5S1Request, //企业司法涉诉V2 + "QYGL5S1I": qygl.ProcessQYGL5S1IRequest, //企业司法涉诉I // YYSY系列处理器 "YYSYD50F": yysy.ProcessYYSYD50FRequest, diff --git a/internal/domains/api/services/form_config_service.go b/internal/domains/api/services/form_config_service.go index 6072004..4a4beda 100644 --- a/internal/domains/api/services/form_config_service.go +++ b/internal/domains/api/services/form_config_service.go @@ -243,7 +243,7 @@ func (s *FormConfigServiceImpl) getDTOStruct(ctx context.Context, apiCode string "YYSYH6F3": &dto.YYSYH6F3Req{}, //运营商三要素简版即时版查询 "IVYZX5Q2": &dto.IVYZX5Q2Req{}, //活体识别步骤二 "PDFG01GZ": &dto.PDFG01GZReq{}, // - "QYGL5S1": &dto.QYGL5S1Req{}, //企业司法涉诉V2 + "QYGL5S1I": &dto.QYGL5S1IReq{}, //企业司法涉诉V2 } // 优先返回已配置的DTO diff --git a/internal/domains/api/services/processors/qygl/qygl5s1_processor.go b/internal/domains/api/services/processors/qygl/qygl5s1i_processor.go similarity index 85% rename from internal/domains/api/services/processors/qygl/qygl5s1_processor.go rename to internal/domains/api/services/processors/qygl/qygl5s1i_processor.go index 4c4df3c..636a9da 100644 --- a/internal/domains/api/services/processors/qygl/qygl5s1_processor.go +++ b/internal/domains/api/services/processors/qygl/qygl5s1i_processor.go @@ -10,10 +10,10 @@ import ( "tyapi-server/internal/infrastructure/external/zhicha" ) -// ProcessQYGL5S1Request QYGL5S1 API处理方法 - 企业司法涉诉V2 -func ProcessQYGL5S1Request(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { +// ProcessQYGL5S1IReq QYGL5S1I API处理方法 - 企业司法涉诉V2 +func ProcessQYGL5S1IRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { - var paramsDto dto.QYGL5S1Req + var paramsDto dto.QYGL5S1IReq if err := json.Unmarshal(params, ¶msDto); err != nil { return nil, errors.Join(processors.ErrSystem, err) } From 4e359060e61985623842cf7f2a21129c506aef87 Mon Sep 17 00:00:00 2001 From: Mrx <18278715334@163.com> Date: Wed, 28 Jan 2026 16:58:57 +0800 Subject: [PATCH 5/5] =?UTF-8?q?=E6=97=A0=E7=BC=9D=E6=9B=BF=E6=8D=A2?= =?UTF-8?q?=E8=A5=BF=E9=83=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../api/services/form_config_service.go | 2 +- .../processors/yysy/yysyf7db_processor.go | 106 ++++++++++++++---- 2 files changed, 88 insertions(+), 20 deletions(-) diff --git a/internal/domains/api/services/form_config_service.go b/internal/domains/api/services/form_config_service.go index 4a4beda..fb3f091 100644 --- a/internal/domains/api/services/form_config_service.go +++ b/internal/domains/api/services/form_config_service.go @@ -424,7 +424,7 @@ func (s *FormConfigServiceImpl) generateFieldLabel(jsonTag string) string { "legal_person": "法人姓名", "ent_code": "企业代码", "auth_date": "授权日期", - "date_range": "数据范围", + "date_range": "日期范围", "time_range": "时间范围", "authorized": "是否授权", "authorization_url": "授权链接", diff --git a/internal/domains/api/services/processors/yysy/yysyf7db_processor.go b/internal/domains/api/services/processors/yysy/yysyf7db_processor.go index ae4be9c..d2f3b13 100644 --- a/internal/domains/api/services/processors/yysy/yysyf7db_processor.go +++ b/internal/domains/api/services/processors/yysy/yysyf7db_processor.go @@ -4,13 +4,23 @@ import ( "context" "encoding/json" "errors" + "strings" + "time" "tyapi-server/internal/domains/api/dto" "tyapi-server/internal/domains/api/services/processors" - "tyapi-server/internal/infrastructure/external/westdex" + "tyapi-server/internal/infrastructure/external/shumai" ) -// YYSYF7DBResponse 手机二次卡查询成功响应 +// westdexG19BJ02Resp 上游 G19BJ02 实际返回结构:order_no->guid, result->code, channel->phoneType, desc->msg +type westdexG19BJ02Resp struct { + Result int `json:"result"` // 0-是二次卡 1-不是二次卡 2-数据库中无信息(预留) + OrderNo string `json:"orderNo"` + Channel string `json:"channel"` // cmcc/cucc/ctcc + Desc string `json:"desc"` +} + +// YYSYF7DBResponse 手机二次卡查询成功响应(最终返回结构) type YYSYF7DBResponse struct { Code string `json:"code"` Data YYSYF7DBResponseData `json:"data"` @@ -20,9 +30,9 @@ type YYSYF7DBResponse struct { type YYSYF7DBResponseData struct { Code int `json:"code"` EncryptType string `json:"encryptType"` - Guid string `json:"guid"` - Msg string `json:"msg"` - PhoneType string `json:"phoneType"` + Guid string `json:"guid"` // 来自 order_no + Msg string `json:"msg"` // 来自 desc,按 result:0-是二次卡 1-不是二次卡 + PhoneType string `json:"phoneType"` // 来自 channel:cmcc->CMCC 等 } // ProcessYYSYF7DBRequest YYSYF7DB API处理方法 @@ -36,30 +46,88 @@ func ProcessYYSYF7DBRequest(ctx context.Context, params []byte, deps *processors return nil, errors.Join(processors.ErrInvalidParam, err) } - encryptedMobileNo, err := deps.WestDexService.Encrypt(paramsDto.MobileNo) - if err != nil { - return nil, errors.Join(processors.ErrSystem, err) + // 组装日期:开始日期 + 当前日期(YYYYMMDD-YYYYMMDD) + today := time.Now().Format("20060102") + dateRange := paramsDto.StartDate + "-" + today + + reqFormData := map[string]interface{}{ + "mobile": paramsDto.MobileNo, + "date": dateRange, } - reqData := map[string]interface{}{ - "data": map[string]interface{}{ - "phone": encryptedMobileNo, - "startDate": paramsDto.StartDate, // StartDate 有 encrypt:"false" 标签,不加密 - }, - } - - respBytes, err := deps.WestDexService.CallAPI(ctx, "G19BJ02", reqData) + // 以表单方式调用数脉 API;参数在 CallAPIForm 内转为 application/x-www-form-urlencoded + apiPath := "/v4/mobile_twice/check" // 接口路径,根据数脉文档填写( + respBytes, err := deps.ShumaiService.CallAPIForm(ctx, apiPath, reqFormData) if err != nil { - if errors.Is(err, westdex.ErrDatasource) { + if errors.Is(err, shumai.ErrDatasource) { + // 数据源错误 return nil, errors.Join(processors.ErrDatasource, err) + } else if errors.Is(err, shumai.ErrSystem) { + // 系统错误 + return nil, errors.Join(processors.ErrSystem, err) } else { + // 其他未知错误 return nil, errors.Join(processors.ErrSystem, err) } } - var mapped YYSYF7DBResponse - if err := json.Unmarshal(respBytes, &mapped); err != nil { + mapped, err := mapWestdexG19BJ02ToYYSYF7DB(respBytes) + if err != nil { return nil, errors.Join(processors.ErrSystem, err) } return json.Marshal(mapped) } + +// mapWestdexG19BJ02ToYYSYF7DB 将上游 result/orderNo/channel/desc 映射为最终 code/data 结构 +// result: 0->1025(是二次卡) 1->1026(不是二次卡) 2->1027(数据库中无信息);channel: cmcc->CMCC cucc->CUCC ctcc->CTCC +func mapWestdexG19BJ02ToYYSYF7DB(dataBytes []byte) (*YYSYF7DBResponse, error) { + var r westdexG19BJ02Resp + if err := json.Unmarshal(dataBytes, &r); err != nil { + return nil, err + } + + var codeStr string + var codeInt int + var msg string + switch r.Result { + case 0: + codeStr = "1025" + codeInt = 1025 + msg = "二次卡" + case 1: + codeStr = "1026" + codeInt = 1026 + msg = "不是二次卡" + default: + codeStr = "1027" + codeInt = 1027 + msg = "不是二次卡" + } + if r.Desc != "" { + msg = strings.TrimSpace(r.Desc) + } + + ch := strings.ToLower(strings.TrimSpace(r.Channel)) + var phoneType string + switch ch { + case "cmcc": + phoneType = "CMCC" + case "cucc": + phoneType = "CUCC" + case "ctcc": + phoneType = "CTCC" + default: + phoneType = "UNKNOWN" + } + + return &YYSYF7DBResponse{ + Code: codeStr, + Data: YYSYF7DBResponseData{ + Code: codeInt, + EncryptType: "MD5", + Guid: r.OrderNo, + Msg: msg, + PhoneType: phoneType, + }, + }, nil +}