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