This commit is contained in:
2025-09-30 12:03:51 +08:00
parent 1b931cb816
commit 532b92713b
17 changed files with 734 additions and 46 deletions

View File

@@ -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"`

View File

@@ -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系列处理器

View File

@@ -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{},

View File

@@ -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 {

View File

@@ -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 {

View File

@@ -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)
}

View File

@@ -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调用是否成功

View File

@@ -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, &paramsDto); 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)
}

View File

@@ -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, &paramsDto); 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
}

View File

@@ -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调用是否成功

View File

@@ -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调用是否成功

View File

@@ -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, &paramsDto); 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
}

View File

@@ -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调用是否成功

View File

@@ -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调用是否成功

View File

@@ -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)

View File

@@ -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,

View File

@@ -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)
}