diff --git a/client.go b/client.go index 3520fbc..764911b 100644 --- a/client.go +++ b/client.go @@ -30,11 +30,12 @@ const ( // - NewBearerClient: 管理端(使用已有的 Bearer Token) // - NewUserTokenClient: 发送端(X-SMS-Token + 请求签名,仅可调用发送接口) type Client struct { - baseURL string - mode authMode - bearer string - userToken string - httpClient *http.Client + baseURL string + mode authMode + bearer string + serviceToken string + userToken string + httpClient *http.Client } // Option 用于在构造 Client 时传入可选配置。 @@ -65,6 +66,7 @@ func NewServiceClient(baseURL, serviceToken string, opts ...Option) (*Client, er o(c) } + c.serviceToken = serviceToken token, err := c.serviceTokenLogin(context.Background(), serviceToken) if err != nil { return nil, fmt.Errorf("service token login: %w", err) @@ -197,6 +199,10 @@ func structToMap(v interface{}) (map[string]interface{}, error) { } func doRequest[T any](c *Client, ctx context.Context, method, path string, body interface{}, query url.Values) (T, error) { + return doRequestRetry[T](c, ctx, method, path, body, query, false) +} + +func doRequestRetry[T any](c *Client, ctx context.Context, method, path string, body interface{}, query url.Values, retried bool) (T, error) { var zero T var bodyReader io.Reader @@ -252,6 +258,15 @@ func doRequest[T any](c *Client, ctx context.Context, method, path string, body return zero, fmt.Errorf("unmarshal response (status %d): %w\nbody: %s", resp.StatusCode, err, string(respBody)) } + if apiResp.Code == 401 && c.serviceToken != "" && !retried { + newToken, loginErr := c.serviceTokenLogin(ctx, c.serviceToken) + if loginErr != nil { + return zero, &APIError{Code: 401, Message: apiResp.Message} + } + c.bearer = newToken + return doRequestRetry[T](c, ctx, method, path, body, query, true) + } + if apiResp.Code != 200 { return zero, &APIError{Code: apiResp.Code, Message: apiResp.Message} }