.NET

Xử lý lỗi

Hệ thống exception và cách xử lý lỗi trong .NET SDK

SDK sử dụng hệ thống exception phân cấp, tất cả kế thừa từ SsiException (và System.Exception).

Danh sách exception

ExceptionKế thừaMô tả
SsiExceptionExceptionException cơ sở. Có Code, StatusCode, ResponseBody, Headers
AuthenticationExceptionSsiExceptionXác thực thất bại (sai credentials, token hết hạn, lỗi chữ ký)
SmartOtpPendingExceptionAuthenticationExceptionSmart OTP chưa được duyệt (HTTP 202, code 401114), hoặc hết số lần poll mà chưa duyệt
SmartOtpRejectedExceptionAuthenticationExceptionSmart OTP bị từ chối hoặc không hợp lệ (401113, 401115, 401116). Kết thúc, không poll tiếp.
ReauthenticationRequiredExceptionAuthenticationExceptionToken đã hết hạn, không refresh được và không có otp/transactionId mới: cần xác thực lại
ApiExceptionSsiExceptionAPI trả về lỗi. Có Code, StatusCode, ResponseBody
DuplicateRequestExceptionApiExceptionYêu cầu trùng lặp (HTTP 409, code mặc định "409")
WebSocketExceptionSsiExceptionLỗi kết nối hoặc giao tiếp WebSocket
TradingWsErrorWebSocketExceptionTrading WebSocket: server từ chối socket hoặc một lệnh. Có Status, ErrorCode, ServerMessage
ValidationExceptionSsiExceptionLỗi validate input, phát hiện ở client, chưa gửi gì
RateLimitExceptionSsiExceptionVượt giới hạn request (HTTP 429). Mã mặc định "RATE_LIMITED"

Chuỗi kế thừa

Exception → SsiException → AuthenticationException → SmartOtpPendingException
                                                   → SmartOtpRejectedException
                                                   → ReauthenticationRequiredException
                         → ApiException → DuplicateRequestException
                         → WebSocketException → TradingWsError
                         → ValidationException
                         → RateLimitException

Thuộc tính exception cơ sở

public class SsiException : Exception
{
    public string Code { get; }                              // mã lỗi của server (ví dụ "401114"), nếu không có thì HTTP status hoặc mã SDK
    public int StatusCode { get; }
    public Dictionary<string, JsonElement>? ResponseBody { get; }   // body đã che thông tin nhạy cảm
    public IReadOnlyDictionary<string, string> Headers { get; }     // header phản hồi (rate limit, Retry-After...), không gồm Authorization
}

RateLimitException bổ sung thêm:

public long? RetryAfterMs { get; }   // mili-giây server yêu cầu chờ (Retry-After), nếu có
public int? Limit { get; }
public int? Remaining { get; }
public double? Reset { get; }

TradingWsError bổ sung int Status, string ErrorCode, string ServerMessage. Thông báo của nó không bao giờ chứa params đã ký.

Mã lỗi của server: ServerErrorCode và HttpStatus

ServerErrorCode là lớp tĩnh chứa các mã số mà server trả trong trường code (ví dụ PushApprovalPending = 401114, SignatureMissing = 401006, SignatureBodyEmpty = 401008, SignatureMismatch = 401013, ReplayWindowExceeded = 400111, OtpVerificationFailed = 401100, NoScopeGranted = 403100), cùng ServerErrorCode.IsKnown(int code). Danh sách đầy đủ xem trong mã nguồn SDK và Mã lỗi. HttpStatus có các hàm phân loại IsAuthError, IsRateLimit, IsClientError, IsServerError.

Sử dụng cơ bản

using SsiSdk;

try
{
    await auth.AuthenticateAsync("YOUR_OTP");
}
catch (SsiException ex)
{
    Console.WriteLine($"Lỗi: {ex.Message} (code: {ex.Code})");
}

Xử lý chi tiết theo loại lỗi

Kiểm soát đã áp dụng: tài khoản là placeholder, catch đi từ exception đặc thù đến tổng quát, không retry tự động với lệnh (SDK không gửi lại POST), không in ResponseBody hay token ra log.

using SsiSdk;

try
{
    var result = await trading.Trading.PlaceLimitOrderAsync(
        "YOUR_ACCOUNT_NO", "SSI", OrderSide.Buy, 100, 68000m);
}
catch (SmartOtpRejectedException)
{
    Console.WriteLine("Smart OTP bị từ chối, cần yêu cầu OTP mới");
}
catch (SmartOtpPendingException)
{
    Console.WriteLine("Smart OTP chưa được duyệt");
}
catch (ReauthenticationRequiredException)
{
    Console.WriteLine("Token hết hạn, cần xác thực lại");
}
catch (AuthenticationException)
{
    Console.WriteLine("Cần xác thực lại");
}
catch (RateLimitException ex)
{
    Console.WriteLine($"Rate limited, retry sau {ex.RetryAfterMs} ms");
}
catch (DuplicateRequestException ex)
{
    // Phải catch trước ApiException
    Console.WriteLine($"Yêu cầu trùng lặp (409): {ex.Message}");
}
catch (ApiException ex)
{
    Console.WriteLine($"API error {ex.StatusCode}: {ex.Message}");
}
catch (ValidationException ex)
{
    Console.WriteLine($"Validation: {ex.Message}");
}
catch (TradingWsError ex)
{
    Console.WriteLine($"Trading WS bị từ chối: {ex.Status} {ex.ErrorCode}");
}
catch (WebSocketException ex)
{
    Console.WriteLine($"WebSocket: {ex.Message}");
}
catch (SsiException ex)
{
    Console.WriteLine($"SDK error: {ex.Message}");
}

Ví dụ trên gộp cả lỗi REST và WebSocket để liệt kê thứ tự catch; trong thực tế một lời gọi chỉ ném một số loại trong đó (TradingWsError chỉ đến từ Trading WebSocket).

Gợi ý xử lý

  • Bắt exception cụ thể trước, SsiException sau cùng làm fallback (theo thứ tự catch từ đặc thù đến tổng quát). SmartOtp*/ReauthenticationRequiredException phải đứng trước AuthenticationException, DuplicateRequestException trước ApiException, TradingWsError trước WebSocketException.
  • Bắt AuthenticationException khi cần refresh token hoặc yêu cầu OTP mới. Với Smart OTP, SmartOtpPendingException nghĩa là chưa duyệt (có thể thử lại), còn SmartOtpRejectedException là kết thúc: xin OTP mới.
  • Bắt RateLimitException và tôn trọng RetryAfterMs (mili-giây) để backoff. SDK chỉ tự chờ 429 với GET; POST/PUT/DELETE không bao giờ được gửi lại.
  • Bắt ApiException để xử lý lỗi nghiệp vụ từ server (Code, StatusCode, ResponseBody).
  • Bắt WebSocketException khi xử lý streaming. Sau timeout của một lệnh, kết quả là không xác định: kiểm tra sổ lệnh trước khi gửi lại.
  • Bắt ValidationException khi input không hợp lệ trước khi gọi API (SDK tự validate ở client; không có request nào được gửi).

Trên trang này