fadd
This commit is contained in:
@@ -45,8 +45,8 @@ type RongxingService struct {
|
||||
logger *external_logger.ExternalServiceLogger
|
||||
client *http.Client
|
||||
|
||||
tokenMu sync.RWMutex
|
||||
cachedToken string
|
||||
// loginMu 避免并发登录打爆对方;不缓存 token,每次业务调用重新登录。
|
||||
loginMu sync.Mutex
|
||||
}
|
||||
|
||||
// apiResponse 戎行统一响应。code 可能是数字或字符串;扣费以 consumeFlag 为准。
|
||||
@@ -126,7 +126,7 @@ func (s *RongxingService) GetConfig() serviceConfig {
|
||||
|
||||
// CallAPI 通用业务接口调用。
|
||||
// apiPath 为相对路径(如 /third/loan/info360),reqData 为已组装好的请求体。
|
||||
// Token 获取与 Header 注入由服务内部处理;401/403 时自动刷新 Token 并重试一次。
|
||||
// 每次调用重新登录取 Token(不本地缓存);若业务码/HTTP 仍为 401/403,再登录重试一次。
|
||||
func (s *RongxingService) CallAPI(ctx context.Context, apiPath string, reqData map[string]interface{}) ([]byte, error) {
|
||||
apiKey := strings.Trim(apiPath, "/")
|
||||
|
||||
@@ -185,7 +185,6 @@ func (s *RongxingService) CallAPI(ctx context.Context, apiPath string, reqData m
|
||||
respStr := string(respBody)
|
||||
|
||||
if statusCode == http.StatusUnauthorized || statusCode == http.StatusForbidden {
|
||||
s.clearToken()
|
||||
if attempt == 0 {
|
||||
continue
|
||||
}
|
||||
@@ -208,6 +207,11 @@ func (s *RongxingService) CallAPI(ctx context.Context, apiPath string, reqData m
|
||||
}
|
||||
|
||||
code := resp.code()
|
||||
// 对方常以 HTTP 200 + body.code=401 表示 token 无效(非 HTTP 401)
|
||||
if isTokenInvalidCode(code) && attempt == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
payload := extractBusinessPayload(resp.Data)
|
||||
|
||||
// 扣费只看 consumeFlag:1 扣费(按成功返回),0 不扣费
|
||||
@@ -226,32 +230,20 @@ func (s *RongxingService) CallAPI(ctx context.Context, apiPath string, reqData m
|
||||
return nil, errors.Join(ErrDatasource, errors.New("请求失败"))
|
||||
}
|
||||
|
||||
// getToken 每次重新登录,不缓存 token。
|
||||
func (s *RongxingService) getToken(ctx context.Context, transactionID string) (string, error) {
|
||||
s.tokenMu.RLock()
|
||||
token := s.cachedToken
|
||||
s.tokenMu.RUnlock()
|
||||
if token != "" {
|
||||
return token, nil
|
||||
s.loginMu.Lock()
|
||||
defer s.loginMu.Unlock()
|
||||
return s.login(ctx, transactionID)
|
||||
}
|
||||
|
||||
s.tokenMu.Lock()
|
||||
defer s.tokenMu.Unlock()
|
||||
if s.cachedToken != "" {
|
||||
return s.cachedToken, nil
|
||||
func isTokenInvalidCode(code string) bool {
|
||||
switch strings.TrimSpace(code) {
|
||||
case "401", "403":
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
|
||||
token, err := s.login(ctx, transactionID)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
s.cachedToken = token
|
||||
return token, nil
|
||||
}
|
||||
|
||||
func (s *RongxingService) clearToken() {
|
||||
s.tokenMu.Lock()
|
||||
s.cachedToken = ""
|
||||
s.tokenMu.Unlock()
|
||||
}
|
||||
|
||||
func (s *RongxingService) login(ctx context.Context, transactionID string) (string, error) {
|
||||
@@ -407,7 +399,8 @@ func classifyTransportError(err error) string {
|
||||
if errors.As(err, &netErr) && netErr.Timeout() {
|
||||
return "网络超时"
|
||||
}
|
||||
return "其他网络错误(详见 cause)"
|
||||
// 完整原始错误在同一条日志的 error/cause 字段中,不在别的文件
|
||||
return "其他网络错误(见本条日志 error 全文)"
|
||||
}
|
||||
|
||||
func (s *RongxingService) validateConfig() error {
|
||||
|
||||
Reference in New Issue
Block a user