Merge branch 'main' of http://1.117.67.95:3000/team/tyapi-server
This commit is contained in:
@@ -255,28 +255,17 @@ func collectAPIData(ctx context.Context, params dto.DWBG8B4DReq, deps *processor
|
||||
return apiData
|
||||
}
|
||||
|
||||
// callProcessor 调用指定的处理器
|
||||
// callProcessor 调用指定的处理器(走注册表,含白名单包装)
|
||||
func callProcessor(ctx context.Context, apiCode string, params []byte, deps *processors.ProcessorDependencies) (interface{}, error) {
|
||||
// 通过CombService获取处理器
|
||||
if combSvc, ok := deps.CombService.(interface {
|
||||
GetProcessor(apiCode string) (processors.ProcessorFunc, bool)
|
||||
}); ok {
|
||||
processor, exists := combSvc.GetProcessor(apiCode)
|
||||
if !exists {
|
||||
return nil, fmt.Errorf("未找到处理器: %s", apiCode)
|
||||
}
|
||||
respBytes, err := processor(ctx, params, deps)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var data interface{}
|
||||
if err := json.Unmarshal(respBytes, &data); err != nil {
|
||||
return nil, fmt.Errorf("解析响应失败: %w", err)
|
||||
}
|
||||
return data, nil
|
||||
respBytes, err := processors.InvokeRegisteredProcessor(ctx, apiCode, params, deps)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf("无法获取处理器: %s,CombService不支持GetProcessor方法", apiCode)
|
||||
var data interface{}
|
||||
if err := json.Unmarshal(respBytes, &data); err != nil {
|
||||
return nil, fmt.Errorf("解析响应失败: %w", err)
|
||||
}
|
||||
return data, nil
|
||||
}
|
||||
|
||||
// exportAPIDataToJSON 将API数据导出为JSON文件,方便调试
|
||||
|
||||
32
internal/domains/api/services/processors/invoke.go
Normal file
32
internal/domains/api/services/processors/invoke.go
Normal file
@@ -0,0 +1,32 @@
|
||||
package processors
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// ProcessorRegistry 已注册处理器查询(由 CombService 实现)
|
||||
type ProcessorRegistry interface {
|
||||
GetProcessor(apiCode string) (ProcessorFunc, bool)
|
||||
}
|
||||
|
||||
// InvokeRegisteredProcessor 通过注册表调用处理器(含白名单包装),聚合处理器内部转接应使用此方法。
|
||||
func InvokeRegisteredProcessor(
|
||||
ctx context.Context,
|
||||
apiCode string,
|
||||
params []byte,
|
||||
deps *ProcessorDependencies,
|
||||
) ([]byte, error) {
|
||||
if deps == nil || deps.CombService == nil {
|
||||
return nil, fmt.Errorf("CombService 未配置,无法调用处理器: %s", apiCode)
|
||||
}
|
||||
registry, ok := deps.CombService.(ProcessorRegistry)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("CombService 不支持 GetProcessor,无法调用处理器: %s", apiCode)
|
||||
}
|
||||
processor, exists := registry.GetProcessor(apiCode)
|
||||
if !exists {
|
||||
return nil, fmt.Errorf("未找到处理器: %s", apiCode)
|
||||
}
|
||||
return processor(ctx, params, deps)
|
||||
}
|
||||
@@ -349,29 +349,17 @@ func collectAPIData(ctx context.Context, params dto.PDFG01GZReq, deps *processor
|
||||
return apiData
|
||||
}
|
||||
|
||||
// callProcessor 调用指定的处理器
|
||||
// callProcessor 调用指定的处理器(走注册表,含白名单包装)
|
||||
func callProcessor(ctx context.Context, apiCode string, params []byte, deps *processors.ProcessorDependencies) (interface{}, error) {
|
||||
// 通过CombService获取处理器
|
||||
if combSvc, ok := deps.CombService.(interface {
|
||||
GetProcessor(apiCode string) (processors.ProcessorFunc, bool)
|
||||
}); ok {
|
||||
processor, exists := combSvc.GetProcessor(apiCode)
|
||||
if !exists {
|
||||
return nil, fmt.Errorf("未找到处理器: %s", apiCode)
|
||||
}
|
||||
respBytes, err := processor(ctx, params, deps)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var data interface{}
|
||||
if err := json.Unmarshal(respBytes, &data); err != nil {
|
||||
return nil, fmt.Errorf("解析响应失败: %w", err)
|
||||
}
|
||||
return data, nil
|
||||
respBytes, err := processors.InvokeRegisteredProcessor(ctx, apiCode, params, deps)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 如果无法通过CombService获取,返回错误
|
||||
return nil, fmt.Errorf("无法获取处理器: %s,CombService不支持GetProcessor方法", apiCode)
|
||||
var data interface{}
|
||||
if err := json.Unmarshal(respBytes, &data); err != nil {
|
||||
return nil, fmt.Errorf("解析响应失败: %w", err)
|
||||
}
|
||||
return data, nil
|
||||
}
|
||||
|
||||
// formatDataForPDF 格式化数据为PDF生成服务需要的格式
|
||||
|
||||
@@ -25,7 +25,7 @@ func ProcessQCXG4D2ERequest(ctx context.Context, params []byte, deps *processors
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
|
||||
raw, err := ProcessQCXGM4CLRequest(ctx, m4clParams, deps)
|
||||
raw, err := processors.InvokeRegisteredProcessor(ctx, "QCXGM4CL", m4clParams, deps)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@ func ProcessQCXG5F3ARequest(ctx context.Context, params []byte, deps *processors
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
|
||||
raw, err := ProcessQCXGM4CLRequest(ctx, m4clParams, deps)
|
||||
raw, err := processors.InvokeRegisteredProcessor(ctx, "QCXGM4CL", m4clParams, deps)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@ func ProcessQCXG9P1CRequest(ctx context.Context, params []byte, deps *processors
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
|
||||
raw, err := ProcessQCXGM4CLRequest(ctx, m4clParams, deps)
|
||||
raw, err := processors.InvokeRegisteredProcessor(ctx, "QCXGM4CL", m4clParams, deps)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -50,7 +50,7 @@ func ProcessQYGL3F8ERequest(ctx context.Context, params []byte, deps *processors
|
||||
return nil, errors.Join(processors.ErrSystem, err)
|
||||
}
|
||||
|
||||
b4c0Response, err := ProcessQYGL6S1BRequest(ctx, b4c0ParamsBytes, deps)
|
||||
b4c0Response, err := processors.InvokeRegisteredProcessor(ctx, "QYGL6S1B", b4c0ParamsBytes, deps)
|
||||
if err != nil {
|
||||
log.Error("QYGL3F8E调用QYGL6S1B失败", zap.Error(err))
|
||||
return nil, err // 错误已经是处理器标准错误,直接返回
|
||||
@@ -620,25 +620,7 @@ func callProcessorSafely(ctx context.Context, processorType, entCode string, dep
|
||||
}
|
||||
|
||||
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:
|
||||
log.Warn("QYGL3F8E未知的处理器类型",
|
||||
zap.String("processor_type", processorType),
|
||||
)
|
||||
return map[string]interface{}{}
|
||||
}
|
||||
response, err = processors.InvokeRegisteredProcessor(ctx, processorType, paramsBytes, deps)
|
||||
|
||||
if err != nil {
|
||||
// 如果是查询为空错误,返回空对象
|
||||
@@ -681,7 +663,7 @@ func callQYGL5S1IProcessorSafely(ctx context.Context, entCode string, entName st
|
||||
if err != nil {
|
||||
return map[string]interface{}{}
|
||||
}
|
||||
response, err := ProcessQYGL5S1IRequest(ctx, paramsBytes, deps)
|
||||
response, err := processors.InvokeRegisteredProcessor(ctx, "QYGL5S1I", paramsBytes, deps)
|
||||
if err != nil {
|
||||
return map[string]interface{}{}
|
||||
}
|
||||
|
||||
@@ -39,7 +39,7 @@ func ProcessQYGLJ1U9Request(ctx context.Context, params []byte, deps *processors
|
||||
resultsCh := make(chan apiResult, 7)
|
||||
var wg sync.WaitGroup
|
||||
|
||||
call := func(key string, req interface{}, fn func(context.Context, []byte, *processors.ProcessorDependencies) ([]byte, error)) {
|
||||
call := func(key, apiCode string, req interface{}) {
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
@@ -48,7 +48,7 @@ func ProcessQYGLJ1U9Request(ctx context.Context, params []byte, deps *processors
|
||||
resultsCh <- apiResult{key: key, err: err}
|
||||
return
|
||||
}
|
||||
resp, err := fn(ctx, b, deps)
|
||||
resp, err := processors.InvokeRegisteredProcessor(ctx, apiCode, b, deps)
|
||||
if err != nil {
|
||||
resultsCh <- apiResult{key: key, err: err}
|
||||
return
|
||||
@@ -70,46 +70,46 @@ func ProcessQYGLJ1U9Request(ctx context.Context, params []byte, deps *processors
|
||||
}
|
||||
|
||||
// 企业全量信息核验V2(QYGLUY3S)
|
||||
call("jiguangFull", map[string]interface{}{
|
||||
call("jiguangFull", "QYGLUY3S", map[string]interface{}{
|
||||
"ent_name": p.EntName,
|
||||
"ent_code": p.EntCode,
|
||||
}, ProcessQYGLUY3SRequest)
|
||||
})
|
||||
|
||||
// 企业股权结构全景(QYGLJ0Q1)
|
||||
call("equityPanorama", map[string]interface{}{
|
||||
call("equityPanorama", "QYGLJ0Q1", map[string]interface{}{
|
||||
"ent_name": p.EntName,
|
||||
}, ProcessQYGLJ0Q1Request)
|
||||
})
|
||||
|
||||
// 企业司法涉诉V2(QYGL5S1I)
|
||||
call("judicialCertFull", map[string]interface{}{
|
||||
call("judicialCertFull", "QYGL5S1I", map[string]interface{}{
|
||||
"ent_name": p.EntName,
|
||||
"ent_code": p.EntCode,
|
||||
}, ProcessQYGL5S1IRequest)
|
||||
})
|
||||
|
||||
// 企业年报信息核验(QYGLDJ12)
|
||||
call("annualReport", map[string]interface{}{
|
||||
call("annualReport", "QYGLDJ12", map[string]interface{}{
|
||||
"ent_name": p.EntName,
|
||||
"ent_code": p.EntCode,
|
||||
}, ProcessQYGLDJ12Request)
|
||||
})
|
||||
|
||||
// 企业税收违法核查(QYGL8848)
|
||||
call("taxViolation", map[string]interface{}{
|
||||
call("taxViolation", "QYGL8848", map[string]interface{}{
|
||||
"ent_name": p.EntName,
|
||||
"ent_code": p.EntCode,
|
||||
}, ProcessQYGL8848Request)
|
||||
})
|
||||
|
||||
// 欠税公告(QYGL7D9A,天眼查 OwnTax,keyword 为统一社会信用代码)
|
||||
call("taxArrears", map[string]interface{}{
|
||||
call("taxArrears", "QYGL7D9A", map[string]interface{}{
|
||||
"ent_code": p.EntCode,
|
||||
"page_size": 20,
|
||||
"page_num": 1,
|
||||
}, ProcessQYGL7D9ARequest)
|
||||
})
|
||||
|
||||
// 企业进出口信用核查(QYGLDJ33)
|
||||
call("customsCredit", map[string]interface{}{
|
||||
call("customsCredit", "QYGLDJ33", map[string]interface{}{
|
||||
"ent_name": p.EntName,
|
||||
"ent_code": p.EntCode,
|
||||
}, ProcessQYGLDJ33Request)
|
||||
})
|
||||
|
||||
wg.Wait()
|
||||
close(resultsCh)
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
package processors
|
||||
|
||||
import "context"
|
||||
|
||||
type whitelistContextKey struct{}
|
||||
|
||||
// WhitelistMatch 请求级白名单命中项(身份匹配,不含当前顶层 api_code 过滤)
|
||||
type WhitelistMatch struct {
|
||||
ID string
|
||||
APICodes []string
|
||||
IsGlobal bool
|
||||
}
|
||||
|
||||
// WhitelistContext 写入 context 的白名单状态,供各处理器按 api_code 判断是否返回查询为空
|
||||
type WhitelistContext struct {
|
||||
Matches []WhitelistMatch
|
||||
}
|
||||
|
||||
// WithWhitelistContext 将白名单命中结果写入 context
|
||||
func WithWhitelistContext(ctx context.Context, matches []WhitelistMatch) context.Context {
|
||||
if len(matches) == 0 {
|
||||
return ctx
|
||||
}
|
||||
return context.WithValue(ctx, whitelistContextKey{}, &WhitelistContext{Matches: matches})
|
||||
}
|
||||
|
||||
// WhitelistFromContext 从 context 读取白名单状态
|
||||
func WhitelistFromContext(ctx context.Context) *WhitelistContext {
|
||||
wc, ok := ctx.Value(whitelistContextKey{}).(*WhitelistContext)
|
||||
if !ok || wc == nil {
|
||||
return nil
|
||||
}
|
||||
return wc
|
||||
}
|
||||
|
||||
// WhitelistShouldReturnEmpty 根据 context 中的白名单与当前 api_code 判断是否应返回查询为空。
|
||||
// 入参是否命中、命中哪些 api_code 由应用层 EnrichContext 写入;此处仅读 ctx。
|
||||
func WhitelistShouldReturnEmpty(ctx context.Context, apiCode string) bool {
|
||||
wc := WhitelistFromContext(ctx)
|
||||
if wc == nil {
|
||||
return false
|
||||
}
|
||||
for _, m := range wc.Matches {
|
||||
if matchesWhitelistAPICode(m.APICodes, apiCode) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func matchesWhitelistAPICode(apiCodes []string, apiCode string) bool {
|
||||
for _, code := range apiCodes {
|
||||
if code == "*" || code == apiCode {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package processors
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestWhitelistShouldReturnEmpty_PerAPICode(t *testing.T) {
|
||||
ctx := WithWhitelistContext(context.Background(), []WhitelistMatch{
|
||||
{ID: "1", APICodes: []string{"FLXG0V4B"}},
|
||||
})
|
||||
|
||||
if !WhitelistShouldReturnEmpty(ctx, "FLXG0V4B") {
|
||||
t.Fatal("FLXG0V4B should hit")
|
||||
}
|
||||
if WhitelistShouldReturnEmpty(ctx, "JRZQ8A2D") {
|
||||
t.Fatal("JRZQ8A2D should not hit entry scoped to FLXG0V4B")
|
||||
}
|
||||
}
|
||||
|
||||
func TestWhitelistShouldReturnEmpty_WildcardMatchesAnyAPICode(t *testing.T) {
|
||||
ctx := WithWhitelistContext(context.Background(), []WhitelistMatch{
|
||||
{ID: "1", APICodes: []string{"*"}},
|
||||
})
|
||||
|
||||
if !WhitelistShouldReturnEmpty(ctx, "QYGL8261") {
|
||||
t.Fatal("wildcard should match any api_code in ctx")
|
||||
}
|
||||
if !WhitelistShouldReturnEmpty(ctx, "YYSY8B1C") {
|
||||
t.Fatal("wildcard should match mobile-only api_code when in ctx")
|
||||
}
|
||||
}
|
||||
@@ -9,6 +9,6 @@ import (
|
||||
// ProcessYYSY8C2DRequest YYSY8C2D API处理方法 - 运营商三要素查询
|
||||
func ProcessYYSY8C2DRequest(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) {
|
||||
|
||||
return ProcessYYSY9A1BRequest(ctx, params, deps)
|
||||
return processors.InvokeRegisteredProcessor(ctx, "YYSY9A1B", params, deps)
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user