f
This commit is contained in:
@@ -3,7 +3,6 @@ package nuoer
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
"crypto/md5"
|
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
@@ -17,6 +16,26 @@ import (
|
|||||||
|
|
||||||
const defaultRequestTimeout = 4 * time.Second
|
const defaultRequestTimeout = 4 * time.Second
|
||||||
|
|
||||||
|
// queryBillingAPIKeys 查询计费接口:数据未查得(busiCode=1000)仍按成功计费,返回空数据
|
||||||
|
var queryBillingAPIKeys = map[string]struct{}{
|
||||||
|
"idRiskTagV106": {}, // 身份风险V106
|
||||||
|
"personalLawsuit_cv2": {}, // 企业诉讼定制版
|
||||||
|
"personalLawsuit_cv1": {}, // 个人诉讼定制版
|
||||||
|
"loanRiskTagV11": {}, // 借贷意向查询
|
||||||
|
"loanRiskTagV5": {}, // 风险变量V5
|
||||||
|
"loanRiskTagV12": {}, // 特殊名单
|
||||||
|
"blackListV121_3_1": {}, // 债务逾期黑名单V3_1
|
||||||
|
"blackListV110": {}, // 特殊名单V110
|
||||||
|
"zhiTongModelG": {}, // 智瞳-通用版
|
||||||
|
"zhitong_ultra_v4_score": {}, // 智瞳分尊享版
|
||||||
|
"zhixiangScore": {}, // 智享分
|
||||||
|
}
|
||||||
|
|
||||||
|
func isQueryBillingAPIKey(apiKey string) bool {
|
||||||
|
_, ok := queryBillingAPIKeys[apiKey]
|
||||||
|
return ok
|
||||||
|
}
|
||||||
|
|
||||||
// nuoerResponse 诺尔智汇通用响应
|
// nuoerResponse 诺尔智汇通用响应
|
||||||
type nuoerResponse struct {
|
type nuoerResponse struct {
|
||||||
Code int `json:"code"`
|
Code int `json:"code"`
|
||||||
@@ -55,10 +74,18 @@ func NewNuoerService(url, appID, appSecret string, timeout time.Duration, logger
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *NuoerService) generateRequestID() string {
|
func (s *NuoerService) logResponse(transactionID, apiKey string, statusCode int, duration time.Duration, seqNo string) {
|
||||||
timestamp := time.Now().UnixNano()
|
if s.logger == nil {
|
||||||
hash := md5.Sum([]byte(fmt.Sprintf("%d_%s", timestamp, s.config.AppID)))
|
return
|
||||||
return fmt.Sprintf("nuoer_%x", hash[:8])
|
}
|
||||||
|
s.logger.LogResponse(seqNo, transactionID, apiKey, statusCode, duration)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *NuoerService) logError(transactionID, apiKey, seqNo string, err error, payload interface{}) {
|
||||||
|
if s.logger == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
s.logger.LogError(seqNo, transactionID, apiKey, err, payload)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *NuoerService) CallAPI(ctx context.Context, apiKey, apiPath string, body map[string]string) (*nuoerResponse, error) {
|
func (s *NuoerService) CallAPI(ctx context.Context, apiKey, apiPath string, body map[string]string) (*nuoerResponse, error) {
|
||||||
@@ -70,7 +97,6 @@ func (s *NuoerService) CallAPI(ctx context.Context, apiKey, apiPath string, body
|
|||||||
requestURL += apiPath
|
requestURL += apiPath
|
||||||
}
|
}
|
||||||
|
|
||||||
requestID := s.generateRequestID()
|
|
||||||
startTime := time.Now()
|
startTime := time.Now()
|
||||||
|
|
||||||
var transactionID string
|
var transactionID string
|
||||||
@@ -89,24 +115,20 @@ func (s *NuoerService) CallAPI(ctx context.Context, apiKey, apiPath string, body
|
|||||||
}
|
}
|
||||||
|
|
||||||
if s.logger != nil {
|
if s.logger != nil {
|
||||||
s.logger.LogRequest(requestID, transactionID, apiKey, requestURL)
|
s.logger.LogRequest("", transactionID, apiKey, requestURL)
|
||||||
}
|
}
|
||||||
|
|
||||||
bodyBytes, err := json.Marshal(requestPayload)
|
bodyBytes, err := json.Marshal(requestPayload)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err = errors.Join(ErrSystem, err)
|
err = errors.Join(ErrSystem, err)
|
||||||
if s.logger != nil {
|
s.logError(transactionID, apiKey, "", err, requestPayload)
|
||||||
s.logger.LogError(requestID, transactionID, apiKey, err, requestPayload)
|
|
||||||
}
|
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
req, err := http.NewRequestWithContext(ctx, http.MethodPost, requestURL, bytes.NewBuffer(bodyBytes))
|
req, err := http.NewRequestWithContext(ctx, http.MethodPost, requestURL, bytes.NewBuffer(bodyBytes))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err = errors.Join(ErrSystem, err)
|
err = errors.Join(ErrSystem, err)
|
||||||
if s.logger != nil {
|
s.logError(transactionID, apiKey, "", err, requestPayload)
|
||||||
s.logger.LogError(requestID, transactionID, apiKey, err, requestPayload)
|
|
||||||
}
|
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
req.Header.Set("Content-Type", "application/json")
|
req.Header.Set("Content-Type", "application/json")
|
||||||
@@ -115,9 +137,7 @@ func (s *NuoerService) CallAPI(ctx context.Context, apiKey, apiPath string, body
|
|||||||
resp, err := client.Do(req)
|
resp, err := client.Do(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err = wrapHTTPError(err)
|
err = wrapHTTPError(err)
|
||||||
if s.logger != nil {
|
s.logError(transactionID, apiKey, "", err, requestPayload)
|
||||||
s.logger.LogError(requestID, transactionID, apiKey, err, requestPayload)
|
|
||||||
}
|
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
@@ -125,78 +145,72 @@ func (s *NuoerService) CallAPI(ctx context.Context, apiKey, apiPath string, body
|
|||||||
respBody, err := io.ReadAll(resp.Body)
|
respBody, err := io.ReadAll(resp.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err = errors.Join(ErrSystem, err)
|
err = errors.Join(ErrSystem, err)
|
||||||
if s.logger != nil {
|
s.logError(transactionID, apiKey, "", err, requestPayload)
|
||||||
s.logger.LogError(requestID, transactionID, apiKey, err, requestPayload)
|
|
||||||
}
|
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if s.logger != nil {
|
duration := time.Since(startTime)
|
||||||
s.logger.LogResponse(requestID, transactionID, apiKey, resp.StatusCode, time.Since(startTime))
|
|
||||||
}
|
|
||||||
|
|
||||||
if resp.StatusCode != http.StatusOK {
|
if resp.StatusCode != http.StatusOK {
|
||||||
err = errors.Join(ErrDatasource, fmt.Errorf("HTTP状态码 %d", resp.StatusCode))
|
err = errors.Join(ErrDatasource, fmt.Errorf("HTTP状态码 %d", resp.StatusCode))
|
||||||
if s.logger != nil {
|
s.logError(transactionID, apiKey, "", err, requestPayload)
|
||||||
s.logger.LogError(requestID, transactionID, apiKey, err, requestPayload)
|
|
||||||
}
|
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
var nuoerResp nuoerResponse
|
var nuoerResp nuoerResponse
|
||||||
if err := json.Unmarshal(respBody, &nuoerResp); err != nil {
|
if err := json.Unmarshal(respBody, &nuoerResp); err != nil {
|
||||||
err = errors.Join(ErrSystem, fmt.Errorf("响应解析失败: %w", err))
|
err = errors.Join(ErrSystem, fmt.Errorf("响应解析失败: %w", err))
|
||||||
if s.logger != nil {
|
s.logError(transactionID, apiKey, "", err, requestPayload)
|
||||||
s.logger.LogError(requestID, transactionID, apiKey, err, requestPayload)
|
|
||||||
}
|
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if nuoerResp.Code != CodeSuccess {
|
if nuoerResp.Code != CodeSuccess {
|
||||||
|
if nuoerResp.Code == BusiCodeNotFound && isQueryBillingAPIKey(apiKey) {
|
||||||
|
nuoerResp.Data = map[string]interface{}{}
|
||||||
|
s.logResponse(transactionID, apiKey, resp.StatusCode, duration, nuoerResp.SeqNo)
|
||||||
|
return &nuoerResp, nil
|
||||||
|
}
|
||||||
nuoerErr := NewNuoerError(nuoerResp.Code, nuoerResp.Msg)
|
nuoerErr := NewNuoerError(nuoerResp.Code, nuoerResp.Msg)
|
||||||
err = errors.Join(GetErrByPlatformCode(nuoerResp.Code), nuoerErr)
|
err = errors.Join(GetErrByPlatformCode(nuoerResp.Code), nuoerErr)
|
||||||
if s.logger != nil {
|
s.logError(transactionID, apiKey, nuoerResp.SeqNo, nuoerErr, requestPayload)
|
||||||
s.logger.LogErrorWithResponseID(requestID, transactionID, apiKey, nuoerErr, requestPayload, nuoerResp.SeqNo)
|
|
||||||
}
|
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if nuoerResp.Data == nil {
|
if nuoerResp.Data == nil {
|
||||||
err = errors.Join(ErrSystem, errors.New("响应 data 为空"))
|
err = errors.Join(ErrSystem, errors.New("响应 data 为空"))
|
||||||
if s.logger != nil {
|
s.logError(transactionID, apiKey, nuoerResp.SeqNo, err, requestPayload)
|
||||||
s.logger.LogErrorWithResponseID(requestID, transactionID, apiKey, err, requestPayload, nuoerResp.SeqNo)
|
|
||||||
}
|
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
busiCode, busiMsg, ok := parseDataBusiInfo(nuoerResp.Data)
|
busiCode, busiMsg, ok := parseDataBusiInfo(nuoerResp.Data)
|
||||||
if !ok {
|
if !ok {
|
||||||
err = errors.Join(ErrSystem, errors.New("响应 data 无法解析 busiCode"))
|
err = errors.Join(ErrSystem, errors.New("响应 data 无法解析 busiCode"))
|
||||||
if s.logger != nil {
|
s.logError(transactionID, apiKey, nuoerResp.SeqNo, err, requestPayload)
|
||||||
s.logger.LogErrorWithResponseID(requestID, transactionID, apiKey, err, requestPayload, nuoerResp.SeqNo)
|
|
||||||
}
|
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if busiCode != BusiCodeSuccess {
|
if busiCode != BusiCodeSuccess {
|
||||||
|
if busiCode == BusiCodeNotFound && isQueryBillingAPIKey(apiKey) {
|
||||||
|
nuoerResp.Data = map[string]interface{}{}
|
||||||
|
s.logResponse(transactionID, apiKey, resp.StatusCode, duration, nuoerResp.SeqNo)
|
||||||
|
return &nuoerResp, nil
|
||||||
|
}
|
||||||
busiErr := NewNuoerBusiError(busiCode, busiMsg)
|
busiErr := NewNuoerBusiError(busiCode, busiMsg)
|
||||||
err = errors.Join(GetErrByBusiCode(busiCode), busiErr)
|
err = errors.Join(GetErrByBusiCode(busiCode), busiErr)
|
||||||
if s.logger != nil {
|
s.logError(transactionID, apiKey, nuoerResp.SeqNo, busiErr, requestPayload)
|
||||||
s.logger.LogErrorWithResponseID(requestID, transactionID, apiKey, busiErr, requestPayload, nuoerResp.SeqNo)
|
|
||||||
}
|
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
cleanedData, err := stripBusiMetaFromData(nuoerResp.Data)
|
cleanedData, err := stripBusiMetaFromData(nuoerResp.Data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err = errors.Join(ErrSystem, fmt.Errorf("响应 data 清理失败: %w", err))
|
err = errors.Join(ErrSystem, fmt.Errorf("响应 data 清理失败: %w", err))
|
||||||
if s.logger != nil {
|
s.logError(transactionID, apiKey, nuoerResp.SeqNo, err, requestPayload)
|
||||||
s.logger.LogErrorWithResponseID(requestID, transactionID, apiKey, err, requestPayload, nuoerResp.SeqNo)
|
|
||||||
}
|
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
nuoerResp.Data = cleanedData
|
nuoerResp.Data = cleanedData
|
||||||
|
|
||||||
|
s.logResponse(transactionID, apiKey, resp.StatusCode, duration, nuoerResp.SeqNo)
|
||||||
|
|
||||||
return &nuoerResp, nil
|
return &nuoerResp, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user