diff --git a/internal/domains/api/services/processors/ivyz/ivyz2a8b_processor.go b/internal/domains/api/services/processors/ivyz/ivyz2a8b_processor.go index b0d8d88..57b584e 100644 --- a/internal/domains/api/services/processors/ivyz/ivyz2a8b_processor.go +++ b/internal/domains/api/services/processors/ivyz/ivyz2a8b_processor.go @@ -38,24 +38,29 @@ func ProcessIVYZ2A8BRequest(ctx context.Context, params []byte, deps *processors "name": paramsDto.Name, } - //走政务接口 - 使用 app_id2 和 app_secret2 - deps.ShumaiService.UseGovernment() // 以表单方式调用数脉 API;参数在 CallAPIForm 内转为 application/x-www-form-urlencoded apiPath := "/v4/id_card/check" // 接口路径,根据数脉文档填写(如 v4/xxx) - respBytes, err := deps.ShumaiService.CallAPIForm(ctx, apiPath, reqFormData) + + // 先尝试使用政务接口(app_id2 和 app_secret2) + respBytes, err := deps.ShumaiService.CallAPIForm(ctx, apiPath, reqFormData, true) if err != nil { - if errors.Is(err, shumai.ErrNotFound) { - // 查无记录情况 - return nil, errors.Join(processors.ErrNotFound, err) - } else 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) + // 使用实时接口(app_id 和 app_secret)重试 + respBytes, err = deps.ShumaiService.CallAPIForm(ctx, apiPath, reqFormData, false) + // 如果重试后仍然失败,或者原本就是查无记录错误,返回错误 + if err != nil { + if errors.Is(err, shumai.ErrNotFound) { + // 查无记录情况 + return nil, errors.Join(processors.ErrNotFound, err) + } else 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) + } } } diff --git a/internal/domains/api/services/processors/ivyz/ivyzn2p8_processor.go b/internal/domains/api/services/processors/ivyz/ivyzn2p8_processor.go index 8e417c2..f15d56d 100644 --- a/internal/domains/api/services/processors/ivyz/ivyzn2p8_processor.go +++ b/internal/domains/api/services/processors/ivyz/ivyzn2p8_processor.go @@ -25,24 +25,29 @@ func ProcessIVYZN2P8Request(ctx context.Context, params []byte, deps *processors "name": paramsDto.Name, } - //走政务接口 - 使用 app_id2 和 app_secret2 - deps.ShumaiService.UseGovernment() // 以表单方式调用数脉 API;参数在 CallAPIForm 内转为 application/x-www-form-urlencoded apiPath := "/v4/id_card/check" // 接口路径,根据数脉文档填写(如 v4/xxx) - respBytes, err := deps.ShumaiService.CallAPIForm(ctx, apiPath, reqFormData) + + // 先尝试使用政务接口(app_id2 和 app_secret2) + respBytes, err := deps.ShumaiService.CallAPIForm(ctx, apiPath, reqFormData, true) if err != nil { - if errors.Is(err, shumai.ErrNotFound) { - // 查无记录情况 - return nil, errors.Join(processors.ErrNotFound, err) - } else 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) + // 使用实时接口(app_id 和 app_secret)重试 + respBytes, err = deps.ShumaiService.CallAPIForm(ctx, apiPath, reqFormData, false) + // 如果重试后仍然失败,返回错误 + if err != nil { + if errors.Is(err, shumai.ErrNotFound) { + // 查无记录情况 + return nil, errors.Join(processors.ErrNotFound, err) + } else 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) + } } } diff --git a/internal/domains/api/services/processors/yysy/yysy09cd_processor.go b/internal/domains/api/services/processors/yysy/yysy09cd_processor.go index 40f8922..e01923c 100644 --- a/internal/domains/api/services/processors/yysy/yysy09cd_processor.go +++ b/internal/domains/api/services/processors/yysy/yysy09cd_processor.go @@ -53,16 +53,22 @@ func ProcessYYSY09CDRequest(ctx context.Context, params []byte, deps *processors "mobile": paramsDto.MobileNo, } - deps.ShumaiService.UseGovernment() apiPath := "/v4/mobile_three/check" - respBytes, err := deps.ShumaiService.CallAPIForm(ctx, apiPath, reqFormData) + + // 先尝试使用政务接口(app_id2 和 app_secret2) + respBytes, err := deps.ShumaiService.CallAPIForm(ctx, apiPath, reqFormData, true) if err != nil { - 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) + // 使用实时接口(app_id 和 app_secret)重试 + respBytes, err = deps.ShumaiService.CallAPIForm(ctx, apiPath, reqFormData, false) + // 如果重试后仍然失败,返回错误 + if err != nil { + 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) + } } } diff --git a/internal/domains/api/services/processors/yysy/yysy9a1b_processor.go b/internal/domains/api/services/processors/yysy/yysy9a1b_processor.go index 4a0ba91..b4fcd52 100644 --- a/internal/domains/api/services/processors/yysy/yysy9a1b_processor.go +++ b/internal/domains/api/services/processors/yysy/yysy9a1b_processor.go @@ -42,16 +42,22 @@ func ProcessYYSY9A1BRequest(ctx context.Context, params []byte, deps *processors } // 以表单方式调用数脉 API;参数在 CallAPIForm 内转为 application/x-www-form-urlencoded - deps.ShumaiService.UseGovernment() apiPath := "/v4/mobile_three/check" - respBytes, err := deps.ShumaiService.CallAPIForm(ctx, apiPath, reqFormData) + + // 先尝试使用政务接口(app_id2 和 app_secret2) + respBytes, err := deps.ShumaiService.CallAPIForm(ctx, apiPath, reqFormData, true) if err != nil { - 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) + // 使用实时接口(app_id 和 app_secret)重试 + respBytes, err = deps.ShumaiService.CallAPIForm(ctx, apiPath, reqFormData, false) + // 如果重试后仍然失败,返回错误 + if err != nil { + 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) + } } } diff --git a/internal/domains/api/services/processors/yysy/yysybe08_processor.go b/internal/domains/api/services/processors/yysy/yysybe08_processor.go index 890acfb..fa12efb 100644 --- a/internal/domains/api/services/processors/yysy/yysybe08_processor.go +++ b/internal/domains/api/services/processors/yysy/yysybe08_processor.go @@ -25,30 +25,33 @@ func ProcessYYSYBE08Request(ctx context.Context, params []byte, deps *processors "name": paramsDto.Name, } - // 走政务接口 - 使用 app_id2 和 app_secret2 - deps.ShumaiService.UseGovernment() - // 以表单方式调用数脉 API;参数在 CallAPIForm 内转为 application/x-www-form-urlencoded apiPath := "/v4/id_card/check" - respBytes, err := deps.ShumaiService.CallAPIForm(ctx, apiPath, reqFormData) + + // 先尝试使用政务接口(app_id2 和 app_secret2) + respBytes, err := deps.ShumaiService.CallAPIForm(ctx, apiPath, reqFormData, true) if err != nil { - // 处理错误响应 - 转换为目标格式 - errorMsg := err.Error() - if errorMsg == "" { - errorMsg = "请求失败" - } - errorResponse := map[string]interface{}{ - "ctidRequest": map[string]interface{}{ - "ctidAuth": map[string]interface{}{ - "idCard": paramsDto.IDCard, - "name": paramsDto.Name, - "resultCode": "5XXX", - "resultMsg": errorMsg, - "verifyResult": "", + // 使用实时接口(app_id 和 app_secret)重试 + respBytes, err = deps.ShumaiService.CallAPIForm(ctx, apiPath, reqFormData, false) + // 如果重试后仍然失败,处理错误响应 - 转换为目标格式 + if err != nil { + errorMsg := err.Error() + if errorMsg == "" { + errorMsg = "请求失败" + } + errorResponse := map[string]interface{}{ + "ctidRequest": map[string]interface{}{ + "ctidAuth": map[string]interface{}{ + "idCard": paramsDto.IDCard, + "name": paramsDto.Name, + "resultCode": "5XXX", + "resultMsg": errorMsg, + "verifyResult": "", + }, }, - }, + } + return json.Marshal(errorResponse) } - return json.Marshal(errorResponse) } // 解析数脉 /v4/id_card/check 的 data 内容(CallAPIForm 返回的即 data 对象) diff --git a/internal/domains/api/services/processors/yysy/yysyh6d2_processor.go b/internal/domains/api/services/processors/yysy/yysyh6d2_processor.go index 22b8ec4..35136da 100644 --- a/internal/domains/api/services/processors/yysy/yysyh6d2_processor.go +++ b/internal/domains/api/services/processors/yysy/yysyh6d2_processor.go @@ -27,19 +27,25 @@ func ProcessYYSYH6D2Request(ctx context.Context, params []byte, deps *processors } // 以表单方式调用数脉 API;参数在 CallAPIForm 内转为 application/x-www-form-urlencoded - deps.ShumaiService.UseGovernment() apiPath := "/v4/mobile_three/check" // 接口路径,根据数脉文档填写(如 v4/xxx) - respBytes, err := deps.ShumaiService.CallAPIForm(ctx, apiPath, reqFormData) + + // 先尝试使用政务接口(app_id2 和 app_secret2) + respBytes, err := deps.ShumaiService.CallAPIForm(ctx, apiPath, reqFormData, true) if err != nil { - 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) + // 使用实时接口(app_id 和 app_secret)重试 + respBytes, err = deps.ShumaiService.CallAPIForm(ctx, apiPath, reqFormData, false) + // 如果重试后仍然失败,返回错误 + if err != nil { + 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) + } } } return respBytes, nil diff --git a/internal/infrastructure/external/shumai/shumai_service.go b/internal/infrastructure/external/shumai/shumai_service.go index 6b0e163..2235b29 100644 --- a/internal/infrastructure/external/shumai/shumai_service.go +++ b/internal/infrastructure/external/shumai/shumai_service.go @@ -79,6 +79,13 @@ func (s *ShumaiService) generateRequestID() string { return fmt.Sprintf("shumai_%x", hash[:8]) } +// generateRequestIDWithAppID 根据指定的 AppID 生成请求ID(用于不依赖全局状态的情况) +func (s *ShumaiService) generateRequestIDWithAppID(appID string) string { + timestamp := time.Now().UnixNano() + hash := md5.Sum([]byte(fmt.Sprintf("%d_%s", timestamp, appID))) + return fmt.Sprintf("shumai_%x", hash[:8]) +} + // getCurrentAppID 获取当前使用的 AppID func (s *ShumaiService) getCurrentAppID() string { if s.useGovernment && s.config.AppID2 != "" { @@ -118,12 +125,33 @@ func (s *ShumaiService) GetConfig() ShumaiConfig { // CallAPIForm 以表单方式调用数脉 API(application/x-www-form-urlencoded) // 在方法内部将 reqFormData 转为表单:先写入业务参数,再追加 appid、timestamp、sign。 // 签名算法:md5(appid×tamp&app_security),32 位小写,不足补 0。 -func (s *ShumaiService) CallAPIForm(ctx context.Context, apiPath string, reqFormData map[string]interface{}) ([]byte, error) { +// useGovernment 可选参数:true 表示使用政务接口(app_id2),false 表示使用实时接口(app_id) +// 如果未提供参数,则使用全局状态(通过 UseGovernment()/UseNormal() 设置) +func (s *ShumaiService) CallAPIForm(ctx context.Context, apiPath string, reqFormData map[string]interface{}, useGovernment ...bool) ([]byte, error) { + // 确定是否使用政务接口:如果提供了参数则使用参数值,否则使用全局状态 + var useGov bool + if len(useGovernment) > 0 { + useGov = useGovernment[0] + } else { + // 未提供参数时,使用全局状态以保持向后兼容 + useGov = s.useGovernment + } + startTime := time.Now() - requestID := s.generateRequestID() timestamp := strconv.FormatInt(time.Now().UnixMilli(), 10) - appID := s.getCurrentAppID() - appSecret := s.getCurrentAppSecret() + + // 根据参数选择使用的 AppID 和 AppSecret,而不是依赖全局状态 + var appID, appSecret string + if useGov && s.config.AppID2 != "" { + appID = s.config.AppID2 + appSecret = s.config.AppSecret2 + } else { + appID = s.config.AppID + appSecret = s.config.AppSecret + } + + // 使用指定的 AppID 生成请求ID + requestID := s.generateRequestIDWithAppID(appID) sign := GenerateSignForm(appID, timestamp, appSecret) var transactionID string