This commit is contained in:
2026-01-25 14:35:50 +08:00
parent 168a7c7f5f
commit 32336e4ba0
7 changed files with 139 additions and 80 deletions

View File

@@ -38,24 +38,29 @@ func ProcessIVYZ2A8BRequest(ctx context.Context, params []byte, deps *processors
"name": paramsDto.Name, "name": paramsDto.Name,
} }
//走政务接口 - 使用 app_id2 和 app_secret2
deps.ShumaiService.UseGovernment()
// 以表单方式调用数脉 API参数在 CallAPIForm 内转为 application/x-www-form-urlencoded // 以表单方式调用数脉 API参数在 CallAPIForm 内转为 application/x-www-form-urlencoded
apiPath := "/v4/id_card/check" // 接口路径,根据数脉文档填写(如 v4/xxx 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 err != nil {
if errors.Is(err, shumai.ErrNotFound) { // 使用实时接口app_id 和 app_secret重试
// 查无记录情况 respBytes, err = deps.ShumaiService.CallAPIForm(ctx, apiPath, reqFormData, false)
return nil, errors.Join(processors.ErrNotFound, err) // 如果重试后仍然失败,或者原本就是查无记录错误,返回错误
} else if errors.Is(err, shumai.ErrDatasource) { if err != nil {
// 数据源错误 if errors.Is(err, shumai.ErrNotFound) {
return nil, errors.Join(processors.ErrDatasource, err) // 查无记录情况
} else if errors.Is(err, shumai.ErrSystem) { return nil, errors.Join(processors.ErrNotFound, err)
// 系统错误 } else if errors.Is(err, shumai.ErrDatasource) {
return nil, errors.Join(processors.ErrSystem, err) // 数据源错误
} else { return nil, errors.Join(processors.ErrDatasource, err)
// 其他未知错误 } else if errors.Is(err, shumai.ErrSystem) {
return nil, errors.Join(processors.ErrSystem, err) // 系统错误
return nil, errors.Join(processors.ErrSystem, err)
} else {
// 其他未知错误
return nil, errors.Join(processors.ErrSystem, err)
}
} }
} }

View File

@@ -25,24 +25,29 @@ func ProcessIVYZN2P8Request(ctx context.Context, params []byte, deps *processors
"name": paramsDto.Name, "name": paramsDto.Name,
} }
//走政务接口 - 使用 app_id2 和 app_secret2
deps.ShumaiService.UseGovernment()
// 以表单方式调用数脉 API参数在 CallAPIForm 内转为 application/x-www-form-urlencoded // 以表单方式调用数脉 API参数在 CallAPIForm 内转为 application/x-www-form-urlencoded
apiPath := "/v4/id_card/check" // 接口路径,根据数脉文档填写(如 v4/xxx 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 err != nil {
if errors.Is(err, shumai.ErrNotFound) { // 使用实时接口app_id 和 app_secret重试
// 查无记录情况 respBytes, err = deps.ShumaiService.CallAPIForm(ctx, apiPath, reqFormData, false)
return nil, errors.Join(processors.ErrNotFound, err) // 如果重试后仍然失败,返回错误
} else if errors.Is(err, shumai.ErrDatasource) { if err != nil {
// 数据源错误 if errors.Is(err, shumai.ErrNotFound) {
return nil, errors.Join(processors.ErrDatasource, err) // 查无记录情况
} else if errors.Is(err, shumai.ErrSystem) { return nil, errors.Join(processors.ErrNotFound, err)
// 系统错误 } else if errors.Is(err, shumai.ErrDatasource) {
return nil, errors.Join(processors.ErrSystem, err) // 数据源错误
} else { return nil, errors.Join(processors.ErrDatasource, err)
// 其他未知错误 } else if errors.Is(err, shumai.ErrSystem) {
return nil, errors.Join(processors.ErrSystem, err) // 系统错误
return nil, errors.Join(processors.ErrSystem, err)
} else {
// 其他未知错误
return nil, errors.Join(processors.ErrSystem, err)
}
} }
} }

View File

@@ -53,16 +53,22 @@ func ProcessYYSY09CDRequest(ctx context.Context, params []byte, deps *processors
"mobile": paramsDto.MobileNo, "mobile": paramsDto.MobileNo,
} }
deps.ShumaiService.UseGovernment()
apiPath := "/v4/mobile_three/check" 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 err != nil {
if errors.Is(err, shumai.ErrDatasource) { // 使用实时接口app_id 和 app_secret重试
return nil, errors.Join(processors.ErrDatasource, err) respBytes, err = deps.ShumaiService.CallAPIForm(ctx, apiPath, reqFormData, false)
} else if errors.Is(err, shumai.ErrSystem) { // 如果重试后仍然失败,返回错误
return nil, errors.Join(processors.ErrSystem, err) if err != nil {
} else { if errors.Is(err, shumai.ErrDatasource) {
return nil, errors.Join(processors.ErrSystem, err) 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)
}
} }
} }

View File

@@ -42,16 +42,22 @@ func ProcessYYSY9A1BRequest(ctx context.Context, params []byte, deps *processors
} }
// 以表单方式调用数脉 API参数在 CallAPIForm 内转为 application/x-www-form-urlencoded // 以表单方式调用数脉 API参数在 CallAPIForm 内转为 application/x-www-form-urlencoded
deps.ShumaiService.UseGovernment()
apiPath := "/v4/mobile_three/check" 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 err != nil {
if errors.Is(err, shumai.ErrDatasource) { // 使用实时接口app_id 和 app_secret重试
return nil, errors.Join(processors.ErrDatasource, err) respBytes, err = deps.ShumaiService.CallAPIForm(ctx, apiPath, reqFormData, false)
} else if errors.Is(err, shumai.ErrSystem) { // 如果重试后仍然失败,返回错误
return nil, errors.Join(processors.ErrSystem, err) if err != nil {
} else { if errors.Is(err, shumai.ErrDatasource) {
return nil, errors.Join(processors.ErrSystem, err) 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)
}
} }
} }

View File

@@ -25,30 +25,33 @@ func ProcessYYSYBE08Request(ctx context.Context, params []byte, deps *processors
"name": paramsDto.Name, "name": paramsDto.Name,
} }
// 走政务接口 - 使用 app_id2 和 app_secret2
deps.ShumaiService.UseGovernment()
// 以表单方式调用数脉 API参数在 CallAPIForm 内转为 application/x-www-form-urlencoded // 以表单方式调用数脉 API参数在 CallAPIForm 内转为 application/x-www-form-urlencoded
apiPath := "/v4/id_card/check" 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 { if err != nil {
// 处理错误响应 - 转换为目标格式 // 使用实时接口app_id 和 app_secret重试
errorMsg := err.Error() respBytes, err = deps.ShumaiService.CallAPIForm(ctx, apiPath, reqFormData, false)
if errorMsg == "" { // 如果重试后仍然失败,处理错误响应 - 转换为目标格式
errorMsg = "请求失败" if err != nil {
} errorMsg := err.Error()
errorResponse := map[string]interface{}{ if errorMsg == "" {
"ctidRequest": map[string]interface{}{ errorMsg = "请求失败"
"ctidAuth": map[string]interface{}{ }
"idCard": paramsDto.IDCard, errorResponse := map[string]interface{}{
"name": paramsDto.Name, "ctidRequest": map[string]interface{}{
"resultCode": "5XXX", "ctidAuth": map[string]interface{}{
"resultMsg": errorMsg, "idCard": paramsDto.IDCard,
"verifyResult": "", "name": paramsDto.Name,
"resultCode": "5XXX",
"resultMsg": errorMsg,
"verifyResult": "",
},
}, },
}, }
return json.Marshal(errorResponse)
} }
return json.Marshal(errorResponse)
} }
// 解析数脉 /v4/id_card/check 的 data 内容CallAPIForm 返回的即 data 对象) // 解析数脉 /v4/id_card/check 的 data 内容CallAPIForm 返回的即 data 对象)

View File

@@ -27,19 +27,25 @@ func ProcessYYSYH6D2Request(ctx context.Context, params []byte, deps *processors
} }
// 以表单方式调用数脉 API参数在 CallAPIForm 内转为 application/x-www-form-urlencoded // 以表单方式调用数脉 API参数在 CallAPIForm 内转为 application/x-www-form-urlencoded
deps.ShumaiService.UseGovernment()
apiPath := "/v4/mobile_three/check" // 接口路径,根据数脉文档填写(如 v4/xxx 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 err != nil {
if errors.Is(err, shumai.ErrDatasource) { // 使用实时接口app_id 和 app_secret重试
// 数据源错误 respBytes, err = deps.ShumaiService.CallAPIForm(ctx, apiPath, reqFormData, false)
return nil, errors.Join(processors.ErrDatasource, err) // 如果重试后仍然失败,返回错误
} else if errors.Is(err, shumai.ErrSystem) { if err != nil {
// 系统错误 if errors.Is(err, shumai.ErrDatasource) {
return nil, errors.Join(processors.ErrSystem, err) // 数据源错误
} else { return nil, errors.Join(processors.ErrDatasource, err)
// 其他未知错误 } else if errors.Is(err, shumai.ErrSystem) {
return nil, errors.Join(processors.ErrSystem, err) // 系统错误
return nil, errors.Join(processors.ErrSystem, err)
} else {
// 其他未知错误
return nil, errors.Join(processors.ErrSystem, err)
}
} }
} }
return respBytes, nil return respBytes, nil

View File

@@ -79,6 +79,13 @@ func (s *ShumaiService) generateRequestID() string {
return fmt.Sprintf("shumai_%x", hash[:8]) 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 // getCurrentAppID 获取当前使用的 AppID
func (s *ShumaiService) getCurrentAppID() string { func (s *ShumaiService) getCurrentAppID() string {
if s.useGovernment && s.config.AppID2 != "" { if s.useGovernment && s.config.AppID2 != "" {
@@ -118,12 +125,33 @@ func (s *ShumaiService) GetConfig() ShumaiConfig {
// CallAPIForm 以表单方式调用数脉 APIapplication/x-www-form-urlencoded // CallAPIForm 以表单方式调用数脉 APIapplication/x-www-form-urlencoded
// 在方法内部将 reqFormData 转为表单:先写入业务参数,再追加 appid、timestamp、sign。 // 在方法内部将 reqFormData 转为表单:先写入业务参数,再追加 appid、timestamp、sign。
// 签名算法md5(appid&timestamp&app_security)32 位小写,不足补 0。 // 签名算法md5(appid&timestamp&app_security)32 位小写,不足补 0。
func (s *ShumaiService) CallAPIForm(ctx context.Context, apiPath string, reqFormData map[string]interface{}) ([]byte, error) { // useGovernment 可选参数true 表示使用政务接口app_id2false 表示使用实时接口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() startTime := time.Now()
requestID := s.generateRequestID()
timestamp := strconv.FormatInt(time.Now().UnixMilli(), 10) 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) sign := GenerateSignForm(appID, timestamp, appSecret)
var transactionID string var transactionID string