From 40b50a5a5c02b7a195eff6fcef45a8af04d380b1 Mon Sep 17 00:00:00 2001 From: liangzai <2440983361@qq.com> Date: Mon, 29 Jun 2026 11:25:32 +0800 Subject: [PATCH] f --- .../api/api_application_service.go | 26 ++++++++++++++++--- internal/application/api/errors.go | 2 ++ .../domains/api/services/processors/errors.go | 19 ++++++++++---- .../processors/ivyz/ivyzx5q2_processor.go | 14 +++------- 4 files changed, 42 insertions(+), 19 deletions(-) diff --git a/internal/application/api/api_application_service.go b/internal/application/api/api_application_service.go index 976e207..c30506c 100644 --- a/internal/application/api/api_application_service.go +++ b/internal/application/api/api_application_service.go @@ -171,6 +171,16 @@ func (s *ApiApplicationServiceImpl) CallApi(ctx context.Context, cmd *commands.A go s.asyncProcessDeduction(context.Background(), apiCall, validationResult) return transactionId, "", ErrQueryEmpty } + if errors.Is(err, ErrSuccessNoBill) { + encryptedResponse, encErr := crypto.AesEncrypt([]byte(response), validationResult.GetSecretKey()) + if encErr != nil { + s.logger.Error("加密响应失败", zap.Error(encErr)) + go s.asyncRecordFailure(context.Background(), apiCall, encErr) + return "", "", ErrSystem + } + go s.asyncSaveApiCall(context.Background(), apiCall, validationResult, response, decimal.Zero) + return transactionId, string(encryptedResponse), nil + } if err != nil { // 异步记录失败状态 go s.asyncRecordFailure(context.Background(), apiCall, err) @@ -405,6 +415,11 @@ func (s *ApiApplicationServiceImpl) callExternalApi(ctx context.Context, cmd *co callContext) if err != nil { + var successNoBill *processors.SuccessNoBillError + if errors.As(err, &successNoBill) { + return string(successNoBill.Response), ErrSuccessNoBill + } + // 数据宝 10001/10006:查空但计费,由 CallApi 统一处理 if errors.Is(err, shujubao.ErrQueryEmpty) { return "", ErrQueryEmptyBillable @@ -440,10 +455,13 @@ func (s *ApiApplicationServiceImpl) callExternalApi(ctx context.Context, cmd *co return string(response), nil } -// asyncSaveApiCall 异步保存API调用记录 -func (s *ApiApplicationServiceImpl) asyncSaveApiCall(ctx context.Context, apiCall *entities.ApiCall, validation *dto.ApiCallValidationResult, response string) { - // 标记为成功 - apiCall.MarkSuccess(validation.GetAmount()) +// asyncSaveApiCall 异步保存API调用记录;可选 cost 覆盖扣费金额(如成功但不扣费场景传 decimal.Zero) +func (s *ApiApplicationServiceImpl) asyncSaveApiCall(ctx context.Context, apiCall *entities.ApiCall, validation *dto.ApiCallValidationResult, response string, cost ...decimal.Decimal) { + chargeAmount := validation.GetAmount() + if len(cost) > 0 { + chargeAmount = cost[0] + } + apiCall.MarkSuccess(chargeAmount) // 检查TransactionID是否已存在,避免重复创建 existingCall, err := s.apiCallRepository.FindByTransactionId(ctx, apiCall.TransactionId) diff --git a/internal/application/api/errors.go b/internal/application/api/errors.go index c60330f..eedac63 100644 --- a/internal/application/api/errors.go +++ b/internal/application/api/errors.go @@ -7,6 +7,8 @@ var ( ErrQueryEmpty = errors.New("查询为空") // ErrQueryEmptyBillable 数据宝查空(10001/10006):对外返回查询为空,但仍正常扣费 ErrQueryEmptyBillable = errors.New("查询为空") + // ErrSuccessNoBill 对外返回正常业务响应,但不扣费 + ErrSuccessNoBill = errors.New("成功不扣费") ErrQueryFailed = errors.New("查询失败") ErrSystem = errors.New("接口异常") ErrDecryptFail = errors.New("解密失败") diff --git a/internal/domains/api/services/processors/errors.go b/internal/domains/api/services/processors/errors.go index 7830f69..ae1070f 100644 --- a/internal/domains/api/services/processors/errors.go +++ b/internal/domains/api/services/processors/errors.go @@ -4,9 +4,18 @@ import "errors" // 处理器相关错误类型 var ( - ErrDatasource = errors.New("数据源异常") - ErrSystem = errors.New("系统异常") - ErrInvalidParam = errors.New("参数校验不正确") - ErrNotFound = errors.New("查询为空") - ErrContactBusiness = errors.New("请联系商务咨询") + ErrDatasource = errors.New("数据源异常") + ErrSystem = errors.New("系统异常") + ErrInvalidParam = errors.New("参数校验不正确") + ErrNotFound = errors.New("查询为空") + ErrContactBusiness = errors.New("请联系商务咨询") ) + +// SuccessNoBillError 携带成功响应但不扣费(如活体检测 result=2) +type SuccessNoBillError struct { + Response []byte +} + +func (e *SuccessNoBillError) Error() string { + return "成功不扣费" +} diff --git a/internal/domains/api/services/processors/ivyz/ivyzx5q2_processor.go b/internal/domains/api/services/processors/ivyz/ivyzx5q2_processor.go index 118a318..ebd67cc 100644 --- a/internal/domains/api/services/processors/ivyz/ivyzx5q2_processor.go +++ b/internal/domains/api/services/processors/ivyz/ivyzx5q2_processor.go @@ -8,9 +8,6 @@ import ( "tyapi-server/internal/domains/api/dto" "tyapi-server/internal/domains/api/services/processors" "tyapi-server/internal/infrastructure/external/shumai" - "tyapi-server/internal/shared/logger" - - "go.uber.org/zap" ) // ProcessIVYZX5Q2Request IVYZX5Q2 活体识别步骤二API处理方法 @@ -47,16 +44,13 @@ func ProcessIVYZX5Q2Request(ctx context.Context, params []byte, deps *processors } } - // result==2 时手动抛出错误(不通过/无记录,不返回正常响应) + // result: 0-通过 1-不通过(0/1 正常返回并扣费);2-未找到结果(返回 codeDesc,不扣费) var body struct { - Result int `json:"result"` + Result int `json:"result"` + CodeDesc string `json:"codeDesc"` } if err := json.Unmarshal(respBytes, &body); err == nil && body.Result == 2 { - log := logger.GetGlobalLogger() - log.Warn("IVYZX5Q2 活体检测 result=2 无记录或不通过,返回错误", - zap.Int("result", body.Result), - zap.ByteString("response", respBytes)) - return nil, errors.Join(processors.ErrNotFound, errors.New("活体检测 result=2 无记录或不通过")) + return nil, &processors.SuccessNoBillError{Response: respBytes} } return respBytes, nil