diff --git a/internal/domains/api/services/processors/ivyz/ivyzx5q2_processor.go b/internal/domains/api/services/processors/ivyz/ivyzx5q2_processor.go index ebd67cc..f9dc425 100644 --- a/internal/domains/api/services/processors/ivyz/ivyzx5q2_processor.go +++ b/internal/domains/api/services/processors/ivyz/ivyzx5q2_processor.go @@ -10,6 +10,20 @@ import ( "tyapi-server/internal/infrastructure/external/shumai" ) +// 数脉 H5 活体结果查询中,以下 msg 表示检测不通过但属于正常业务响应,需返回 result=1 并扣费。 +var ivyzX5Q2BillableFailMsgs = map[string]struct{}{ + "动作中检测不到人脸": {}, + "用户拒绝打开摄像头": {}, + "未检测到人脸": {}, +} + +type ivyzX5Q2Resp struct { + OrderNo string `json:"order_no,omitempty"` + Result int `json:"result"` + CodeDesc string `json:"codeDesc"` + FaceUrl string `json:"faceUrl,omitempty"` +} + // ProcessIVYZX5Q2Request IVYZX5Q2 活体识别步骤二API处理方法 func ProcessIVYZX5Q2Request(ctx context.Context, params []byte, deps *processors.ProcessorDependencies) ([]byte, error) { var paramsDto dto.IVYZX5Q2Req @@ -29,6 +43,15 @@ func ProcessIVYZX5Q2Request(ctx context.Context, params []byte, deps *processors apiPath := "/v4/liveness/h5/v4/result" // 接口路径,根据数脉文档填写(如 v4/xxx) respBytes, err := deps.ShumaiService.CallAPIForm(ctx, apiPath, reqFormData) if err != nil { + if shumaiErr := shumai.GetShumaiError(err); shumaiErr != nil && shumaiErr.IsParamError() { + if _, ok := ivyzX5Q2BillableFailMsgs[shumaiErr.Message]; ok { + resp, marshalErr := buildIVYZX5Q2FailResponse(ctx, shumaiErr.Message) + if marshalErr != nil { + return nil, errors.Join(processors.ErrSystem, marshalErr) + } + return resp, nil + } + } if errors.Is(err, shumai.ErrNotFound) { // 查无记录情况 return nil, errors.Join(processors.ErrNotFound, err) @@ -55,3 +78,14 @@ func ProcessIVYZX5Q2Request(ctx context.Context, params []byte, deps *processors return respBytes, nil } + +func buildIVYZX5Q2FailResponse(ctx context.Context, codeDesc string) ([]byte, error) { + resp := ivyzX5Q2Resp{ + Result: 1, + CodeDesc: codeDesc, + } + if orderNo, ok := ctx.Value("transaction_id").(string); ok && orderNo != "" { + resp.OrderNo = orderNo + } + return json.Marshal(resp) +} diff --git a/internal/infrastructure/external/shumai/shumai_errors.go b/internal/infrastructure/external/shumai/shumai_errors.go index 96e1494..9c24cb0 100644 --- a/internal/infrastructure/external/shumai/shumai_errors.go +++ b/internal/infrastructure/external/shumai/shumai_errors.go @@ -1,6 +1,7 @@ package shumai import ( + "errors" "fmt" ) @@ -99,10 +100,23 @@ func IsShumaiError(err error) bool { return ok } -// GetShumaiError 获取数脉错误 +// GetShumaiError 获取数脉错误(支持 errors.Join 包装) func GetShumaiError(err error) *ShumaiError { + if err == nil { + return nil + } + type unwrapMulti interface { + Unwrap() []error + } + if u, ok := err.(unwrapMulti); ok { + for _, e := range u.Unwrap() { + if se := GetShumaiError(e); se != nil { + return se + } + } + } if e, ok := err.(*ShumaiError); ok { return e } - return nil + return GetShumaiError(errors.Unwrap(err)) } diff --git a/internal/infrastructure/external/shumai/shumai_service.go b/internal/infrastructure/external/shumai/shumai_service.go index 7d2ed48..177f16e 100644 --- a/internal/infrastructure/external/shumai/shumai_service.go +++ b/internal/infrastructure/external/shumai/shumai_service.go @@ -308,7 +308,7 @@ func (s *ShumaiService) CallAPIForm(ctx context.Context, apiPath string, reqForm shumaiErr := NewShumaiErrorFromCode(codeStr) if !shumaiErr.IsSuccess() { - if shumaiErr.Message == "未知错误" && msg != "" { + if msg != "" { shumaiErr = NewShumaiError(codeStr, msg) } if s.logger != nil {