This commit is contained in:
2026-06-18 14:01:06 +08:00
parent 20c8e707a5
commit 172b35eef0

View File

@@ -2,7 +2,6 @@ package shujubao
import ( import (
"context" "context"
"crypto/md5"
"encoding/json" "encoding/json"
"errors" "errors"
"fmt" "fmt"
@@ -66,6 +65,7 @@ type ShujubaoResp struct {
Code string `json:"code"` Code string `json:"code"`
Message string `json:"message"` Message string `json:"message"`
Data interface{} `json:"data"` Data interface{} `json:"data"`
SeqNo string `json:"seqNo"`
Success bool `json:"success"` Success bool `json:"success"`
} }
@@ -102,11 +102,15 @@ func NewShujubaoService(url, appSecret string, signMethod SignMethod, timeout ti
} }
} }
// generateRequestID 生成请求 ID // extractSeqNoFromBody 从响应体中提取数据宝返回的 seqNo用于日志 request_id
func (s *ShujubaoService) generateRequestID() string { func extractSeqNoFromBody(respBody []byte) string {
timestamp := time.Now().UnixNano() var partial struct {
hash := md5.Sum([]byte(fmt.Sprintf("%d_%s", timestamp, s.config.AppSecret))) SeqNo string `json:"seqNo"`
return fmt.Sprintf("shujubao_%x", hash[:8]) }
if err := json.Unmarshal(respBody, &partial); err != nil {
return ""
}
return partial.SeqNo
} }
// buildSortedParamStr 将入参按 key 的 ASCII 排序组合为 key1=value1&key2=value2&... // buildSortedParamStr 将入参按 key 的 ASCII 排序组合为 key1=value1&key2=value2&...
@@ -203,7 +207,6 @@ func (s *ShujubaoService) buildRequestURL(apiPath string) string {
// CallAPI 调用数据宝 APIPOST。最终请求地址 = url + 拼接接口地址值body 为业务参数sign、timestamp 按原样传 header。 // CallAPI 调用数据宝 APIPOST。最终请求地址 = url + 拼接接口地址值body 为业务参数sign、timestamp 按原样传 header。
func (s *ShujubaoService) CallAPI(ctx context.Context, apiPath string, params map[string]interface{}) (data interface{}, err error) { func (s *ShujubaoService) CallAPI(ctx context.Context, apiPath string, params map[string]interface{}) (data interface{}, err error) {
startTime := time.Now() startTime := time.Now()
requestID := s.generateRequestID()
timestamp := strconv.FormatInt(time.Now().Unix(), 10) timestamp := strconv.FormatInt(time.Now().Unix(), 10)
// 最终请求 URL = https://api.chinadatapay.com/communication + 拼接接口地址值,如 /personal/197 // 最终请求 URL = https://api.chinadatapay.com/communication + 拼接接口地址值,如 /personal/197
@@ -215,7 +218,7 @@ func (s *ShujubaoService) CallAPI(ctx context.Context, apiPath string, params ma
} }
if s.logger != nil { if s.logger != nil {
s.logger.LogRequest(requestID, transactionID, apiPath, requestURL) s.logger.LogRequest("", transactionID, apiPath, requestURL)
} }
// 使用 application/x-www-form-urlencoded贵司接口暂不支持 JSON 入参 // 使用 application/x-www-form-urlencoded贵司接口暂不支持 JSON 入参
@@ -225,7 +228,7 @@ func (s *ShujubaoService) CallAPI(ctx context.Context, apiPath string, params ma
if err != nil { if err != nil {
err = errors.Join(ErrSystem, err) err = errors.Join(ErrSystem, err)
if s.logger != nil { if s.logger != nil {
s.logger.LogError(requestID, transactionID, apiPath, err, paramsForLog(params)) s.logger.LogError("", transactionID, apiPath, err, paramsForLog(params))
} }
return nil, err return nil, err
} }
@@ -254,7 +257,7 @@ func (s *ShujubaoService) CallAPI(ctx context.Context, apiPath string, params ma
err = errors.Join(ErrSystem, err) err = errors.Join(ErrSystem, err)
} }
if s.logger != nil { if s.logger != nil {
s.logger.LogError(requestID, transactionID, apiPath, err, paramsForLog(params)) s.logger.LogError("", transactionID, apiPath, err, paramsForLog(params))
} }
return nil, err return nil, err
} }
@@ -264,20 +267,21 @@ func (s *ShujubaoService) CallAPI(ctx context.Context, apiPath string, params ma
if err != nil { if err != nil {
err = errors.Join(ErrSystem, err) err = errors.Join(ErrSystem, err)
if s.logger != nil { if s.logger != nil {
s.logger.LogError(requestID, transactionID, apiPath, err, paramsForLog(params)) s.logger.LogError("", transactionID, apiPath, err, paramsForLog(params))
} }
return nil, err return nil, err
} }
if s.logger != nil { seqNo := extractSeqNoFromBody(respBody)
duration := time.Since(startTime) duration := time.Since(startTime)
s.logger.LogResponse(requestID, transactionID, apiPath, response.StatusCode, duration) if s.logger != nil {
s.logger.LogResponse(seqNo, transactionID, apiPath, response.StatusCode, duration)
} }
if response.StatusCode != http.StatusOK { if response.StatusCode != http.StatusOK {
err = errors.Join(ErrDatasource, fmt.Errorf("HTTP状态码 %d", response.StatusCode)) err = errors.Join(ErrDatasource, fmt.Errorf("HTTP状态码 %d", response.StatusCode))
if s.logger != nil { if s.logger != nil {
s.logger.LogError(requestID, transactionID, apiPath, err, paramsForLog(params)) s.logger.LogError(seqNo, transactionID, apiPath, err, paramsForLog(params))
} }
return nil, err return nil, err
} }
@@ -286,10 +290,13 @@ func (s *ShujubaoService) CallAPI(ctx context.Context, apiPath string, params ma
if err := json.Unmarshal(respBody, &shujubaoResp); err != nil { if err := json.Unmarshal(respBody, &shujubaoResp); err != nil {
err = errors.Join(ErrSystem, fmt.Errorf("响应解析失败: %w", err)) err = errors.Join(ErrSystem, fmt.Errorf("响应解析失败: %w", err))
if s.logger != nil { if s.logger != nil {
s.logger.LogError(requestID, transactionID, apiPath, err, paramsForLog(params)) s.logger.LogError(seqNo, transactionID, apiPath, err, paramsForLog(params))
} }
return nil, err return nil, err
} }
if shujubaoResp.SeqNo != "" {
seqNo = shujubaoResp.SeqNo
}
code := shujubaoResp.Code code := shujubaoResp.Code
@@ -299,12 +306,12 @@ func (s *ShujubaoService) CallAPI(ctx context.Context, apiPath string, params ma
if queryEmptyErr := GetQueryEmptyErrByCode(code); queryEmptyErr != nil { if queryEmptyErr := GetQueryEmptyErrByCode(code); queryEmptyErr != nil {
err = errors.Join(queryEmptyErr, shujubaoErr) err = errors.Join(queryEmptyErr, shujubaoErr)
if s.logger != nil { if s.logger != nil {
s.logger.LogError(requestID, transactionID, apiPath, err, paramsForLog(params)) s.logger.LogError(seqNo, transactionID, apiPath, err, paramsForLog(params))
} }
return nil, err return nil, err
} }
if s.logger != nil { if s.logger != nil {
s.logger.LogError(requestID, transactionID, apiPath, shujubaoErr, paramsForLog(params)) s.logger.LogError(seqNo, transactionID, apiPath, shujubaoErr, paramsForLog(params))
} }
return nil, errors.Join(ErrDatasource, shujubaoErr) return nil, errors.Join(ErrDatasource, shujubaoErr)
} }