fix
This commit is contained in:
@@ -302,6 +302,10 @@ type QYGL7C1AReq struct {
|
||||
PageNum int `json:"page_num" validate:"omitempty,min=1"`
|
||||
}
|
||||
|
||||
type QYGL3F8EReq struct {
|
||||
IDCard string `json:"id_card" validate:"required,validIDCard"`
|
||||
}
|
||||
|
||||
type YYSY4F2EReq struct {
|
||||
MobileNo string `json:"mobile_no" validate:"required,min=11,max=11,validMobileNo"`
|
||||
IDCard string `json:"id_card" validate:"required,validIDCard"`
|
||||
|
||||
@@ -124,6 +124,9 @@ func registerAllProcessors(combService *comb.CombService) {
|
||||
"QYGL8B4D": qygl.ProcessQYGL8B4DRequest, // 融资历史
|
||||
"QYGL9E2F": qygl.ProcessQYGL9E2FRequest, // 行政处罚
|
||||
"QYGL7C1A": qygl.ProcessQYGL7C1ARequest, // 经营异常
|
||||
"QYGL3F8E": qygl.ProcessQYGL3F8ERequest, // 人企关系加强版
|
||||
"QYGL7D9A": qygl.ProcessQYGL7D9ARequest, // 欠税公告
|
||||
"QYGL4B2E": qygl.ProcessQYGL4B2ERequest, // 税收违法
|
||||
"COMENT01": qygl.ProcessCOMENT01Request, // 企业风险报告
|
||||
|
||||
// YYSY系列处理器
|
||||
|
||||
@@ -92,6 +92,7 @@ func (s *FormConfigServiceImpl) getDTOStruct(apiCode string) interface{} {
|
||||
"QYGL8B4D": &dto.QYGL8B4DReq{},
|
||||
"QYGL9E2F": &dto.QYGL9E2FReq{},
|
||||
"QYGL7C1A": &dto.QYGL7C1AReq{},
|
||||
"QYGL3F8E": &dto.QYGL3F8EReq{},
|
||||
"YYSY4B37": &dto.YYSY4B37Req{},
|
||||
"YYSY4B21": &dto.YYSY4B21Req{},
|
||||
"YYSY6F2E": &dto.YYSY6F2EReq{},
|
||||
|
||||
@@ -50,6 +50,13 @@ func ProcessDWBG6A2CRequest(ctx context.Context, params []byte, deps *processors
|
||||
}
|
||||
}
|
||||
|
||||
// 过滤响应数据,删除指定字段
|
||||
if respMap, ok := respData.(map[string]interface{}); ok {
|
||||
delete(respMap, "reportUrl")
|
||||
delete(respMap, "multCourtInfo")
|
||||
delete(respMap, "judiciaRiskInfos")
|
||||
}
|
||||
|
||||
// 将响应数据转换为JSON字节
|
||||
respBytes, err := json.Marshal(respData)
|
||||
if err != nil {
|
||||
|
||||
@@ -50,6 +50,13 @@ func ProcessDWBG8B4DRequest(ctx context.Context, params []byte, deps *processors
|
||||
}
|
||||
}
|
||||
|
||||
// 过滤响应数据,删除指定字段
|
||||
if respMap, ok := respData.(map[string]interface{}); ok {
|
||||
delete(respMap, "reportUrl")
|
||||
delete(respMap, "multCourtInfo")
|
||||
delete(respMap, "judiciaRiskInfos")
|
||||
}
|
||||
|
||||
// 将响应数据转换为JSON字节
|
||||
respBytes, err := json.Marshal(respData)
|
||||
if err != nil {
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
package qygl
|
||||
|
||||
import (
|
||||
"errors"
|
||||
|
||||
"tyapi-server/internal/domains/api/services/processors"
|
||||
"tyapi-server/internal/infrastructure/external/tianyancha"
|
||||
)
|
||||
|
||||
// convertTianYanChaError 将天眼查服务的错误转换为处理器层的标准错误
|
||||
func convertTianYanChaError(err error) error {
|
||||
if err == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
// 检查天眼查服务的错误类型,转换为处理器层的标准错误
|
||||
if errors.Is(err, tianyancha.ErrNotFound) {
|
||||
return errors.Join(processors.ErrNotFound, err)
|
||||
}
|
||||
if errors.Is(err, tianyancha.ErrDatasource) {
|
||||
return errors.Join(processors.ErrDatasource, err)
|
||||
}
|
||||
if errors.Is(err, tianyancha.ErrInvalidParam) {
|
||||
return errors.Join(processors.ErrInvalidParam, err)
|
||||
}
|
||||
// 默认作为系统错误处理
|
||||
return errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
@@ -33,11 +33,7 @@ func ProcessQYGL23T7Request(ctx context.Context, params []byte, deps *processors
|
||||
// 调用天眼查API - 使用通用的CallAPI方法
|
||||
response, err := deps.TianYanChaService.CallAPI(ctx, "VerifyThreeElements", apiParams)
|
||||
if err != nil {
|
||||
if err.Error() == "数据源异常" { // Specific error handling for data source issues
|
||||
return nil, errors.Join(processors.ErrDatasource, err)
|
||||
} else {
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
return nil, convertTianYanChaError(err)
|
||||
}
|
||||
|
||||
// 检查天眼查API调用是否成功
|
||||
|
||||
@@ -0,0 +1,542 @@
|
||||
package qygl
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"sort"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"tyapi-server/internal/domains/api/dto"
|
||||
"tyapi-server/internal/domains/api/services/processors"
|
||||
|
||||
"github.com/tidwall/gjson"
|
||||
)
|
||||
|
||||
// ProcessQYGL3F8ERequest QYGL3F8E API处理方法 - 人企关系加强版
|
||||
func ProcessQYGL3F8ERequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) {
|
||||
var paramsDto dto.QYGL3F8EReq
|
||||
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)
|
||||
}
|
||||
|
||||
// 设置最大处理企业数量
|
||||
maxProcessCount := 3
|
||||
|
||||
// 1. 首先调用QYGLB4C0获取个人关联的企业信息
|
||||
b4c0Params := dto.QYGLB4C0Req{
|
||||
IDCard: paramsDto.IDCard,
|
||||
}
|
||||
b4c0ParamsBytes, err := json.Marshal(b4c0Params)
|
||||
if err != nil {
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
|
||||
b4c0Response, err := ProcessQYGLB4C0Request(ctx, b4c0ParamsBytes, deps)
|
||||
if err != nil {
|
||||
return nil, err // 错误已经是处理器标准错误,直接返回
|
||||
}
|
||||
|
||||
// 2. 解析QYGLB4C0的响应,获取企业列表
|
||||
companies, err := parseCompaniesFromB4C0Response(b4c0Response)
|
||||
if err != nil {
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
|
||||
if len(companies) == 0 {
|
||||
// 没有关联企业,返回空的简化格式
|
||||
emptyResponse := map[string]interface{}{
|
||||
"items": []interface{}{},
|
||||
"total": 0,
|
||||
}
|
||||
return json.Marshal(emptyResponse)
|
||||
}
|
||||
|
||||
// 3. 对企业进行优先级排序
|
||||
sortedCompanies := sortCompaniesByPriority(companies)
|
||||
|
||||
// 4. 限制处理数量
|
||||
processCount := len(sortedCompanies)
|
||||
if processCount > maxProcessCount {
|
||||
processCount = maxProcessCount
|
||||
}
|
||||
|
||||
// 5. 并发调用其他处理器获取企业详细信息
|
||||
enrichedCompanies, err := enrichCompaniesWithDetails(ctx, sortedCompanies[:processCount], deps)
|
||||
if err != nil {
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
|
||||
// 6. 构建最终响应
|
||||
finalResponse, err := buildFinalResponse(b4c0Response, enrichedCompanies, sortedCompanies[:processCount])
|
||||
if err != nil {
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
|
||||
return finalResponse, nil
|
||||
}
|
||||
|
||||
// CompanyInfo 企业信息结构
|
||||
type CompanyInfo struct {
|
||||
Index int
|
||||
Data gjson.Result
|
||||
Name string
|
||||
CreditCode string
|
||||
RelationshipVal int // 关系权重值
|
||||
RelationCount int // 关系数量
|
||||
AdminPenalty int // 行政处罚数量
|
||||
Executed int // 被执行人数量
|
||||
Dishonest int // 失信被执行人数量
|
||||
}
|
||||
|
||||
// parseCompaniesFromB4C0Response 从QYGLB4C0响应中解析企业列表
|
||||
func parseCompaniesFromB4C0Response(response []byte) ([]CompanyInfo, error) {
|
||||
// 解析响应数据
|
||||
dataResult := gjson.GetBytes(response, "data")
|
||||
if !dataResult.Exists() {
|
||||
return nil, fmt.Errorf("响应中缺少data字段")
|
||||
}
|
||||
|
||||
datalistResult := gjson.Get(dataResult.Raw, "datalist")
|
||||
if !datalistResult.Exists() {
|
||||
return nil, fmt.Errorf("datalist字段不存在")
|
||||
}
|
||||
|
||||
companiesArray := datalistResult.Array()
|
||||
companies := make([]CompanyInfo, 0, len(companiesArray))
|
||||
|
||||
for i, companyJson := range companiesArray {
|
||||
// 获取企业基本信息
|
||||
name := companyJson.Get("basicInfo.name").String()
|
||||
creditCode := companyJson.Get("basicInfo.creditCode").String()
|
||||
|
||||
if name == "" || creditCode == "" {
|
||||
continue // 跳过无效企业
|
||||
}
|
||||
|
||||
// 计算各种统计数据
|
||||
adminPenalty := 0
|
||||
executed := 0
|
||||
dishonest := 0
|
||||
|
||||
// 统计行政处罚
|
||||
if adminPenaltyResult := companyJson.Get("adminPenalty"); adminPenaltyResult.Exists() && adminPenaltyResult.IsArray() {
|
||||
adminPenalty = len(adminPenaltyResult.Array())
|
||||
}
|
||||
|
||||
// 统计被执行人
|
||||
if executedPersonResult := companyJson.Get("executedPerson"); executedPersonResult.Exists() && executedPersonResult.IsArray() {
|
||||
executed = len(executedPersonResult.Array())
|
||||
}
|
||||
|
||||
// 统计失信被执行人
|
||||
if dishonestResult := companyJson.Get("dishonestExecutedPerson"); dishonestResult.Exists() && dishonestResult.IsArray() {
|
||||
dishonest = len(dishonestResult.Array())
|
||||
}
|
||||
|
||||
// 计算关系权重
|
||||
relationshipVal, relationCount := calculateRelationshipPriority(companyJson)
|
||||
|
||||
companies = append(companies, CompanyInfo{
|
||||
Index: i,
|
||||
Data: companyJson,
|
||||
Name: name,
|
||||
CreditCode: creditCode,
|
||||
RelationshipVal: relationshipVal,
|
||||
RelationCount: relationCount,
|
||||
AdminPenalty: adminPenalty,
|
||||
Executed: executed,
|
||||
Dishonest: dishonest,
|
||||
})
|
||||
}
|
||||
|
||||
return companies, nil
|
||||
}
|
||||
|
||||
// calculateRelationshipPriority 计算关系优先级
|
||||
func calculateRelationshipPriority(companyJson gjson.Result) (int, int) {
|
||||
relationshipVal := 0
|
||||
relationCount := 0
|
||||
|
||||
relationshipResult := companyJson.Get("relationship")
|
||||
if !relationshipResult.Exists() || !relationshipResult.IsArray() {
|
||||
return relationshipVal, relationCount
|
||||
}
|
||||
|
||||
relationships := relationshipResult.Array()
|
||||
for _, rel := range relationships {
|
||||
relationCount++
|
||||
relStr := rel.String()
|
||||
|
||||
// 根据关系类型设置权重:股东(6) > 历史股东(5) > 法人(4) > 历史法人(3) > 高管(2) > 历史高管(1)
|
||||
switch relStr {
|
||||
case "sh": // 股东
|
||||
if relationshipVal < 6 {
|
||||
relationshipVal = 6
|
||||
}
|
||||
case "his_sh": // 历史股东
|
||||
if relationshipVal < 5 {
|
||||
relationshipVal = 5
|
||||
}
|
||||
case "lp": // 法人
|
||||
if relationshipVal < 4 {
|
||||
relationshipVal = 4
|
||||
}
|
||||
case "his_lp": // 历史法人
|
||||
if relationshipVal < 3 {
|
||||
relationshipVal = 3
|
||||
}
|
||||
case "tm": // 高管
|
||||
if relationshipVal < 2 {
|
||||
relationshipVal = 2
|
||||
}
|
||||
case "his_tm": // 历史高管
|
||||
if relationshipVal < 1 {
|
||||
relationshipVal = 1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return relationshipVal, relationCount
|
||||
}
|
||||
|
||||
// sortCompaniesByPriority 按优先级对企业进行排序
|
||||
func sortCompaniesByPriority(companies []CompanyInfo) []CompanyInfo {
|
||||
// 创建副本进行排序
|
||||
sorted := make([]CompanyInfo, len(companies))
|
||||
copy(sorted, companies)
|
||||
|
||||
sort.Slice(sorted, func(i, j int) bool {
|
||||
// 首先根据失信被执行人数量排序
|
||||
if sorted[i].Dishonest != sorted[j].Dishonest {
|
||||
return sorted[i].Dishonest > sorted[j].Dishonest
|
||||
}
|
||||
|
||||
// 然后根据被执行人数量排序
|
||||
if sorted[i].Executed != sorted[j].Executed {
|
||||
return sorted[i].Executed > sorted[j].Executed
|
||||
}
|
||||
|
||||
// 然后根据行政处罚数量排序
|
||||
if sorted[i].AdminPenalty != sorted[j].AdminPenalty {
|
||||
return sorted[i].AdminPenalty > sorted[j].AdminPenalty
|
||||
}
|
||||
|
||||
// 然后按关系权重排序
|
||||
if sorted[i].RelationshipVal != sorted[j].RelationshipVal {
|
||||
return sorted[i].RelationshipVal > sorted[j].RelationshipVal
|
||||
}
|
||||
|
||||
// 最后按关系数量排序
|
||||
return sorted[i].RelationCount > sorted[j].RelationCount
|
||||
})
|
||||
|
||||
return sorted
|
||||
}
|
||||
|
||||
// EnrichedCompanyInfo 增强的企业信息
|
||||
type EnrichedCompanyInfo struct {
|
||||
CompanyInfo
|
||||
InvestHistory interface{} `json:"invest_history"` // 对外投资历史
|
||||
FinancingHistory interface{} `json:"financing_history"` // 融资历史
|
||||
PunishmentInfo interface{} `json:"punishment_info"` // 行政处罚
|
||||
AbnormalInfo interface{} `json:"abnormal_info"` // 经营异常
|
||||
LawsuitInfo interface{} `json:"lawsuit_info"` // 涉诉信息
|
||||
OwnTax interface{} `json:"own_tax"` // 欠税公告
|
||||
TaxContravention interface{} `json:"tax_contravention"` // 税收违法
|
||||
}
|
||||
|
||||
// enrichCompaniesWithDetails 并发调用其他处理器获取企业详细信息
|
||||
func enrichCompaniesWithDetails(ctx context.Context, companies []CompanyInfo, deps *processors.ProcessorDependencies) ([]EnrichedCompanyInfo, error) {
|
||||
var wg sync.WaitGroup
|
||||
results := make(chan struct {
|
||||
index int
|
||||
data EnrichedCompanyInfo
|
||||
err error
|
||||
}, len(companies))
|
||||
|
||||
// 并发处理每个企业
|
||||
for i, company := range companies {
|
||||
wg.Add(1)
|
||||
go func(index int, comp CompanyInfo) {
|
||||
defer wg.Done()
|
||||
|
||||
enriched := EnrichedCompanyInfo{
|
||||
CompanyInfo: comp,
|
||||
}
|
||||
|
||||
// 并发调用多个处理器
|
||||
var detailWg sync.WaitGroup
|
||||
|
||||
// 调用QYGL5A3C - 对外投资历史
|
||||
detailWg.Add(1)
|
||||
go func() {
|
||||
defer detailWg.Done()
|
||||
enriched.InvestHistory = callProcessorSafely(ctx, "QYGL5A3C", comp.CreditCode, deps)
|
||||
}()
|
||||
|
||||
// 调用QYGL8B4D - 融资历史
|
||||
detailWg.Add(1)
|
||||
go func() {
|
||||
defer detailWg.Done()
|
||||
enriched.FinancingHistory = callProcessorSafely(ctx, "QYGL8B4D", comp.CreditCode, deps)
|
||||
}()
|
||||
|
||||
// 调用QYGL9E2F - 行政处罚
|
||||
detailWg.Add(1)
|
||||
go func() {
|
||||
defer detailWg.Done()
|
||||
enriched.PunishmentInfo = callProcessorSafely(ctx, "QYGL9E2F", comp.CreditCode, deps)
|
||||
}()
|
||||
|
||||
// 调用QYGL7C1A - 经营异常
|
||||
detailWg.Add(1)
|
||||
go func() {
|
||||
defer detailWg.Done()
|
||||
enriched.AbnormalInfo = callProcessorSafely(ctx, "QYGL7C1A", comp.CreditCode, deps)
|
||||
}()
|
||||
|
||||
// 调用QYGL8271 - 涉诉信息
|
||||
detailWg.Add(1)
|
||||
go func() {
|
||||
defer detailWg.Done()
|
||||
enriched.LawsuitInfo = callQYGL8271Safely(ctx, comp.Name, comp.CreditCode, deps)
|
||||
}()
|
||||
|
||||
// 调用QYGL7D9A - 欠税公告
|
||||
detailWg.Add(1)
|
||||
go func() {
|
||||
defer detailWg.Done()
|
||||
enriched.OwnTax = callProcessorSafely(ctx, "QYGL7D9A", comp.CreditCode, deps)
|
||||
}()
|
||||
|
||||
// 调用QYGL4B2E - 税收违法
|
||||
detailWg.Add(1)
|
||||
go func() {
|
||||
defer detailWg.Done()
|
||||
enriched.TaxContravention = callProcessorSafely(ctx, "QYGL4B2E", comp.CreditCode, deps)
|
||||
}()
|
||||
|
||||
detailWg.Wait()
|
||||
|
||||
results <- struct {
|
||||
index int
|
||||
data EnrichedCompanyInfo
|
||||
err error
|
||||
}{index, enriched, nil}
|
||||
}(i, company)
|
||||
}
|
||||
|
||||
// 等待所有goroutine完成
|
||||
go func() {
|
||||
wg.Wait()
|
||||
close(results)
|
||||
}()
|
||||
|
||||
// 收集结果
|
||||
enrichedCompanies := make([]EnrichedCompanyInfo, len(companies))
|
||||
for result := range results {
|
||||
if result.err != nil {
|
||||
return nil, result.err
|
||||
}
|
||||
enrichedCompanies[result.index] = result.data
|
||||
}
|
||||
|
||||
return enrichedCompanies, nil
|
||||
}
|
||||
|
||||
// callProcessorSafely 安全调用处理器(处理可能的错误)
|
||||
func callProcessorSafely(ctx context.Context, processorType, entCode string, deps *processors.ProcessorDependencies) interface{} {
|
||||
// 构建请求参数
|
||||
params := map[string]interface{}{
|
||||
"ent_code": entCode,
|
||||
"page_size": 20,
|
||||
"page_num": 1,
|
||||
}
|
||||
|
||||
paramsBytes, err := json.Marshal(params)
|
||||
if err != nil {
|
||||
return map[string]interface{}{}
|
||||
}
|
||||
|
||||
var response []byte
|
||||
switch processorType {
|
||||
case "QYGL5A3C":
|
||||
response, err = ProcessQYGL5A3CRequest(ctx, paramsBytes, deps)
|
||||
case "QYGL8B4D":
|
||||
response, err = ProcessQYGL8B4DRequest(ctx, paramsBytes, deps)
|
||||
case "QYGL9E2F":
|
||||
response, err = ProcessQYGL9E2FRequest(ctx, paramsBytes, deps)
|
||||
case "QYGL7C1A":
|
||||
response, err = ProcessQYGL7C1ARequest(ctx, paramsBytes, deps)
|
||||
case "QYGL7D9A":
|
||||
response, err = ProcessQYGL7D9ARequest(ctx, paramsBytes, deps)
|
||||
case "QYGL4B2E":
|
||||
response, err = ProcessQYGL4B2ERequest(ctx, paramsBytes, deps)
|
||||
default:
|
||||
return map[string]interface{}{}
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
// 如果是查询为空错误,返回空对象
|
||||
if errors.Is(err, processors.ErrNotFound) {
|
||||
return map[string]interface{}{}
|
||||
}
|
||||
// 其他错误也返回空对象,避免影响整体流程
|
||||
return map[string]interface{}{}
|
||||
}
|
||||
|
||||
// 解析响应
|
||||
var result interface{}
|
||||
if err := json.Unmarshal(response, &result); err != nil {
|
||||
return map[string]interface{}{}
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
// callQYGL8271Safely 安全调用QYGL8271处理器
|
||||
func callQYGL8271Safely(ctx context.Context, entName, entCode string, deps *processors.ProcessorDependencies) interface{} {
|
||||
// 构建请求参数
|
||||
params := map[string]interface{}{
|
||||
"ent_name": entName,
|
||||
"ent_code": entCode,
|
||||
"auth_date": generateAuthDateRange(),
|
||||
}
|
||||
|
||||
paramsBytes, err := json.Marshal(params)
|
||||
if err != nil {
|
||||
return map[string]interface{}{}
|
||||
}
|
||||
|
||||
response, err := ProcessQYGL8271Request(ctx, paramsBytes, deps)
|
||||
if err != nil {
|
||||
// 如果是查询为空错误,返回空对象
|
||||
if errors.Is(err, processors.ErrNotFound) {
|
||||
return map[string]interface{}{}
|
||||
}
|
||||
// 其他错误也返回空对象
|
||||
return map[string]interface{}{}
|
||||
}
|
||||
|
||||
// 解析响应
|
||||
var result interface{}
|
||||
if err := json.Unmarshal(response, &result); err != nil {
|
||||
return map[string]interface{}{}
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
func generateAuthDateRange() string {
|
||||
now := time.Now()
|
||||
start := now.AddDate(0, 0, -2).Format("20060102")
|
||||
end := now.AddDate(0, 0, 2).Format("20060102")
|
||||
return fmt.Sprintf("%s-%s", start, end)
|
||||
}
|
||||
|
||||
// buildFinalResponse 构建最终响应
|
||||
func buildFinalResponse(originalResponse []byte, enrichedCompanies []EnrichedCompanyInfo, processedCompanies []CompanyInfo) ([]byte, error) {
|
||||
// 解析原始响应
|
||||
var originalData map[string]interface{}
|
||||
if err := json.Unmarshal(originalResponse, &originalData); err != nil {
|
||||
return nil, fmt.Errorf("解析原始响应失败: %v", err)
|
||||
}
|
||||
|
||||
// 获取总数,默认为0
|
||||
total := 0
|
||||
var originalDatalist []interface{}
|
||||
|
||||
// 安全地获取数据,防止字段不存在的情况
|
||||
if dataField, ok := originalData["data"].(map[string]interface{}); ok {
|
||||
// 获取total字段
|
||||
if totalField, exists := dataField["total"]; exists {
|
||||
switch t := totalField.(type) {
|
||||
case float64:
|
||||
total = int(t)
|
||||
case int:
|
||||
total = t
|
||||
case string:
|
||||
// 如果total是字符串,尝试转换为整数
|
||||
if parsedTotal, err := json.Number(t).Int64(); err == nil {
|
||||
total = int(parsedTotal)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 获取datalist字段
|
||||
if datalist, exists := dataField["datalist"].([]interface{}); exists {
|
||||
originalDatalist = datalist
|
||||
}
|
||||
}
|
||||
|
||||
// 如果没有企业数据,返回空列表
|
||||
if len(originalDatalist) == 0 {
|
||||
finalResponse := map[string]interface{}{
|
||||
"items": []interface{}{},
|
||||
"total": 0,
|
||||
}
|
||||
return json.Marshal(finalResponse)
|
||||
}
|
||||
|
||||
// 创建增强后的企业列表
|
||||
enhancedDatalist := make([]interface{}, len(originalDatalist))
|
||||
|
||||
// 创建已处理企业的映射
|
||||
processedMap := make(map[int]EnrichedCompanyInfo)
|
||||
for i, enriched := range enrichedCompanies {
|
||||
if i < len(processedCompanies) {
|
||||
processedMap[processedCompanies[i].Index] = enriched
|
||||
}
|
||||
}
|
||||
|
||||
// 更新企业列表
|
||||
for i, company := range originalDatalist {
|
||||
if enriched, exists := processedMap[i]; exists {
|
||||
// 已处理的企业,添加详细信息
|
||||
companyMap, ok := company.(map[string]interface{})
|
||||
if ok {
|
||||
companyMap["invest_history"] = enriched.InvestHistory
|
||||
companyMap["financing_history"] = enriched.FinancingHistory
|
||||
companyMap["punishment_info"] = enriched.PunishmentInfo
|
||||
companyMap["abnormal_info"] = enriched.AbnormalInfo
|
||||
companyMap["lawsuit_info"] = enriched.LawsuitInfo
|
||||
companyMap["own_tax"] = enriched.OwnTax
|
||||
companyMap["tax_contravention"] = enriched.TaxContravention
|
||||
enhancedDatalist[i] = companyMap
|
||||
} else {
|
||||
enhancedDatalist[i] = company
|
||||
}
|
||||
} else {
|
||||
// 未处理的企业,添加空的详细信息
|
||||
companyMap, ok := company.(map[string]interface{})
|
||||
if ok {
|
||||
companyMap["invest_history"] = map[string]interface{}{}
|
||||
companyMap["financing_history"] = map[string]interface{}{}
|
||||
companyMap["punishment_info"] = map[string]interface{}{}
|
||||
companyMap["abnormal_info"] = map[string]interface{}{}
|
||||
companyMap["lawsuit_info"] = map[string]interface{}{}
|
||||
companyMap["own_tax"] = map[string]interface{}{}
|
||||
companyMap["tax_contravention"] = map[string]interface{}{}
|
||||
enhancedDatalist[i] = companyMap
|
||||
} else {
|
||||
enhancedDatalist[i] = company
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 构建最终的简化响应格式
|
||||
finalResponse := map[string]interface{}{
|
||||
"items": enhancedDatalist,
|
||||
"total": total,
|
||||
}
|
||||
|
||||
// 序列化最终结果
|
||||
return json.Marshal(finalResponse)
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
package qygl
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"strconv"
|
||||
|
||||
"tyapi-server/internal/domains/api/dto"
|
||||
"tyapi-server/internal/domains/api/services/processors"
|
||||
)
|
||||
|
||||
// ProcessQYGL4B2ERequest QYGL4B2E API处理方法 - 税收违法
|
||||
func ProcessQYGL4B2ERequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) {
|
||||
var paramsDto dto.QYGL5A3CReq
|
||||
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)
|
||||
}
|
||||
|
||||
// 设置默认值
|
||||
pageSize := paramsDto.PageSize
|
||||
if pageSize == 0 {
|
||||
pageSize = 20
|
||||
}
|
||||
pageNum := paramsDto.PageNum
|
||||
if pageNum == 0 {
|
||||
pageNum = 1
|
||||
}
|
||||
|
||||
// 构建API调用参数
|
||||
apiParams := map[string]string{
|
||||
"keyword": paramsDto.EntCode,
|
||||
"pageSize": strconv.Itoa(pageSize),
|
||||
"pageNum": strconv.Itoa(pageNum),
|
||||
}
|
||||
|
||||
// 调用天眼查API - 税收违法
|
||||
response, err := deps.TianYanChaService.CallAPI(ctx, "TaxContravention", apiParams)
|
||||
if err != nil {
|
||||
return nil, convertTianYanChaError(err)
|
||||
}
|
||||
|
||||
// 检查天眼查API调用是否成功
|
||||
if !response.Success {
|
||||
return nil, errors.Join(processors.ErrDatasource, errors.New(response.Message))
|
||||
}
|
||||
|
||||
// 返回天眼查响应数据
|
||||
respBytes, err := json.Marshal(response.Data)
|
||||
if err != nil {
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
|
||||
return respBytes, nil
|
||||
}
|
||||
@@ -41,11 +41,7 @@ func ProcessQYGL5A3CRequest(ctx context.Context, params []byte, deps *processors
|
||||
// 调用天眼查API - 对外投资历史
|
||||
response, err := deps.TianYanChaService.CallAPI(ctx, "InvestHistory", apiParams)
|
||||
if err != nil {
|
||||
if err.Error() == "数据源异常" {
|
||||
return nil, errors.Join(processors.ErrDatasource, err)
|
||||
} else {
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
return nil, convertTianYanChaError(err)
|
||||
}
|
||||
|
||||
// 检查天眼查API调用是否成功
|
||||
|
||||
@@ -41,11 +41,7 @@ func ProcessQYGL7C1ARequest(ctx context.Context, params []byte, deps *processors
|
||||
// 调用天眼查API - 经营异常
|
||||
response, err := deps.TianYanChaService.CallAPI(ctx, "AbnormalInfo", apiParams)
|
||||
if err != nil {
|
||||
if err.Error() == "数据源异常" {
|
||||
return nil, errors.Join(processors.ErrDatasource, err)
|
||||
} else {
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
return nil, convertTianYanChaError(err)
|
||||
}
|
||||
|
||||
// 检查天眼查API调用是否成功
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
package qygl
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"strconv"
|
||||
|
||||
"tyapi-server/internal/domains/api/dto"
|
||||
"tyapi-server/internal/domains/api/services/processors"
|
||||
)
|
||||
|
||||
// ProcessQYGL7D9ARequest QYGL7D9A API处理方法 - 欠税公告
|
||||
func ProcessQYGL7D9ARequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) {
|
||||
var paramsDto dto.QYGL5A3CReq
|
||||
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)
|
||||
}
|
||||
|
||||
// 设置默认值
|
||||
pageSize := paramsDto.PageSize
|
||||
if pageSize == 0 {
|
||||
pageSize = 20
|
||||
}
|
||||
pageNum := paramsDto.PageNum
|
||||
if pageNum == 0 {
|
||||
pageNum = 1
|
||||
}
|
||||
|
||||
// 构建API调用参数
|
||||
apiParams := map[string]string{
|
||||
"keyword": paramsDto.EntCode,
|
||||
"pageSize": strconv.Itoa(pageSize),
|
||||
"pageNum": strconv.Itoa(pageNum),
|
||||
}
|
||||
|
||||
// 调用天眼查API - 欠税公告
|
||||
response, err := deps.TianYanChaService.CallAPI(ctx, "OwnTax", apiParams)
|
||||
if err != nil {
|
||||
return nil, convertTianYanChaError(err)
|
||||
}
|
||||
|
||||
// 检查天眼查API调用是否成功
|
||||
if !response.Success {
|
||||
return nil, errors.Join(processors.ErrDatasource, errors.New(response.Message))
|
||||
}
|
||||
|
||||
// 返回天眼查响应数据
|
||||
respBytes, err := json.Marshal(response.Data)
|
||||
if err != nil {
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
|
||||
return respBytes, nil
|
||||
}
|
||||
@@ -41,11 +41,7 @@ func ProcessQYGL8B4DRequest(ctx context.Context, params []byte, deps *processors
|
||||
// 调用天眼查API - 融资历史
|
||||
response, err := deps.TianYanChaService.CallAPI(ctx, "FinancingHistory", apiParams)
|
||||
if err != nil {
|
||||
if err.Error() == "数据源异常" {
|
||||
return nil, errors.Join(processors.ErrDatasource, err)
|
||||
} else {
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
return nil, convertTianYanChaError(err)
|
||||
}
|
||||
|
||||
// 检查天眼查API调用是否成功
|
||||
|
||||
@@ -41,11 +41,7 @@ func ProcessQYGL9E2FRequest(ctx context.Context, params []byte, deps *processors
|
||||
// 调用天眼查API - 行政处罚
|
||||
response, err := deps.TianYanChaService.CallAPI(ctx, "PunishmentInfo", apiParams)
|
||||
if err != nil {
|
||||
if err.Error() == "数据源异常" {
|
||||
return nil, errors.Join(processors.ErrDatasource, err)
|
||||
} else {
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
return nil, convertTianYanChaError(err)
|
||||
}
|
||||
|
||||
// 检查天眼查API调用是否成功
|
||||
|
||||
@@ -4,7 +4,6 @@ import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"tyapi-server/internal/domains/api/dto"
|
||||
"tyapi-server/internal/domains/api/services/processors"
|
||||
@@ -34,18 +33,9 @@ func ProcessQYGLB4C0Request(ctx context.Context, params []byte, deps *processors
|
||||
if err != nil {
|
||||
// 数据源错误
|
||||
if errors.Is(err, westdex.ErrDatasource) {
|
||||
// 如果有返回内容,优先解析返回内容
|
||||
if respBytes != nil {
|
||||
var westData map[string]interface{}
|
||||
if err := json.Unmarshal(respBytes, &westData); err == nil {
|
||||
if code, ok := westData["code"].(string); ok && code == "1404" {
|
||||
return nil, fmt.Errorf("%s: %w", processors.ErrNotFound, err)
|
||||
}
|
||||
}
|
||||
return respBytes, errors.Join(processors.ErrDatasource, err)
|
||||
}
|
||||
// 没有返回内容,直接返回数据源错误
|
||||
return nil, errors.Join(processors.ErrDatasource, err)
|
||||
}else if errors.Is(err, westdex.ErrNotFound) {
|
||||
return nil, errors.Join(processors.ErrNotFound, err)
|
||||
}
|
||||
// 其他系统错误
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
|
||||
@@ -26,6 +26,8 @@ var APIEndpoints = map[string]string{
|
||||
"FinancingHistory": "/open/cd/findHistoryRongzi/2.0", // 融资历史
|
||||
"PunishmentInfo": "/open/mr/punishmentInfo/3.0", // 行政处罚
|
||||
"AbnormalInfo": "/open/mr/abnormal/2.0", // 经营异常
|
||||
"OwnTax": "/open/mr/ownTax", // 欠税公告
|
||||
"TaxContravention": "/open/mr/taxContravention", // 税收违法
|
||||
}
|
||||
|
||||
// TianYanChaConfig 天眼查配置
|
||||
@@ -74,7 +76,7 @@ func (t *TianYanChaService) CallAPI(ctx context.Context, apiCode string, params
|
||||
// 从映射中获取 API 端点
|
||||
endpoint, exists := APIEndpoints[apiCode]
|
||||
if !exists {
|
||||
return nil, fmt.Errorf("%w: 未找到 API 代码对应的端点: %s", ErrInvalidParam, apiCode)
|
||||
return nil, errors.Join(ErrInvalidParam, fmt.Errorf("未找到 API 代码对应的端点: %s", apiCode))
|
||||
}
|
||||
|
||||
// 构建完整 URL
|
||||
@@ -82,7 +84,7 @@ func (t *TianYanChaService) CallAPI(ctx context.Context, apiCode string, params
|
||||
|
||||
// 检查 Token 是否配置
|
||||
if t.config.Token == "" {
|
||||
return nil, fmt.Errorf("%w: 天眼查 API Token 未配置", ErrSystem)
|
||||
return nil, errors.Join(ErrSystem, fmt.Errorf("天眼查 API Token 未配置"))
|
||||
}
|
||||
|
||||
// 构建查询参数
|
||||
@@ -100,7 +102,7 @@ func (t *TianYanChaService) CallAPI(ctx context.Context, apiCode string, params
|
||||
// 创建请求
|
||||
req, err := http.NewRequestWithContext(ctx, "GET", requestURL, nil)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w: 创建请求失败: %v", ErrSystem, err)
|
||||
return nil, errors.Join(ErrSystem, fmt.Errorf("创建请求失败: %v", err))
|
||||
}
|
||||
|
||||
// 设置请求头
|
||||
@@ -110,29 +112,34 @@ func (t *TianYanChaService) CallAPI(ctx context.Context, apiCode string, params
|
||||
client := &http.Client{Timeout: t.config.Timeout}
|
||||
resp, err := client.Do(req)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w: API 请求异常: %v", ErrDatasource, err)
|
||||
return nil, errors.Join(ErrDatasource, fmt.Errorf("API 请求异常: %v", err))
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
// 检查 HTTP 状态码
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
return nil, fmt.Errorf("%w: API 请求失败,状态码: %d", ErrDatasource, resp.StatusCode)
|
||||
return nil, errors.Join(ErrDatasource, fmt.Errorf("API 请求失败,状态码: %d", resp.StatusCode))
|
||||
}
|
||||
|
||||
// 读取响应体
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%w: 读取响应体失败: %v", ErrSystem, err)
|
||||
return nil, errors.Join(ErrSystem, fmt.Errorf("读取响应体失败: %v", err))
|
||||
}
|
||||
|
||||
// 解析 JSON 响应
|
||||
var tianYanChaResp TianYanChaResponse
|
||||
if err := json.Unmarshal(body, &tianYanChaResp); err != nil {
|
||||
return nil, fmt.Errorf("%w: 解析响应 JSON 失败: %v", ErrSystem, err)
|
||||
return nil, errors.Join(ErrSystem, fmt.Errorf("解析响应 JSON 失败: %v", err))
|
||||
}
|
||||
|
||||
// 检查天眼查业务状态码
|
||||
if tianYanChaResp.ErrorCode != 0 {
|
||||
// 特殊处理:ErrorCode 300000 表示查询为空,返回ErrNotFound
|
||||
if tianYanChaResp.ErrorCode == 300000 {
|
||||
return nil, errors.Join(ErrNotFound, fmt.Errorf("天眼查查询为空: %s", tianYanChaResp.Reason))
|
||||
}
|
||||
|
||||
return &APIResponse{
|
||||
Success: false,
|
||||
Code: tianYanChaResp.ErrorCode,
|
||||
|
||||
@@ -19,6 +19,7 @@ import (
|
||||
var (
|
||||
ErrDatasource = errors.New("数据源异常")
|
||||
ErrSystem = errors.New("系统异常")
|
||||
ErrNotFound = errors.New("查询为空")
|
||||
)
|
||||
|
||||
type WestResp struct {
|
||||
@@ -321,8 +322,8 @@ func (w *WestDexService) G05HZ01CallAPI(ctx context.Context, code string, reqDat
|
||||
}
|
||||
|
||||
if westDexResp.Code != "0000" {
|
||||
if westDexResp.Data == nil {
|
||||
err = errors.Join(ErrSystem, fmt.Errorf(westDexResp.Message))
|
||||
if westDexResp.Data == nil || westDexResp.Code == "1404" {
|
||||
err = errors.Join(ErrNotFound, fmt.Errorf(westDexResp.Message))
|
||||
if w.logger != nil {
|
||||
w.logger.LogErrorWithResponseID(requestID, transactionID, code, err, reqData, westDexResp.ID)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user