> ## Documentation Index
> Fetch the complete documentation index at: https://developers.zangsho.com/llms.txt
> Use this file to discover all available pages before exploring further.

# 錯誤處理

> 帳獸 API 錯誤格式、HTTP 狀態碼與處理最佳實踐

## 錯誤格式

當 API 請求發生錯誤時，回應會包含 `message` 欄位說明錯誤原因：

```json theme={null}
{
  "message": "The given data was invalid.",
  "errors": {
    "email": ["The email field is required."],
    "name": ["The name must be a string."]
  }
}
```

* `message`：錯誤的概要描述
* `errors`：（僅驗證錯誤時出現）各欄位的詳細錯誤訊息，以欄位名稱為 key、錯誤訊息陣列為 value

## HTTP 狀態碼

### 成功回應

| 狀態碼              | 說明         |
| ---------------- | ---------- |
| `200 OK`         | 請求成功，回傳資料  |
| `201 Created`    | 資源建立成功     |
| `204 No Content` | 刪除成功，無回傳內容 |

### 錯誤回應

| 狀態碼                         | 說明     | 常見原因                |
| --------------------------- | ------ | ------------------- |
| `401 Unauthorized`          | 認證失敗   | Token 無效、未提供或已撤銷    |
| `403 Forbidden`             | 權限不足   | Token 沒有對應的 ability |
| `404 Not Found`             | 資源不存在  | ID 或路徑錯誤，或資源屬於其他商家  |
| `422 Unprocessable Entity`  | 驗證錯誤   | 請求資料不符合規則           |
| `429 Too Many Requests`     | 超過頻率限制 | 請求次數超過額度            |
| `500 Internal Server Error` | 伺服器錯誤  | 系統異常，請稍後重試          |

## 驗證錯誤（422）

驗證錯誤是最常見的錯誤類型。`errors` 物件會列出每個有問題的欄位：

```json theme={null}
{
  "message": "The given data was invalid.",
  "errors": {
    "email": [
      "The email field is required."
    ],
    "amount": [
      "The amount must be a number.",
      "The amount must be greater than 0."
    ]
  }
}
```

### 常見驗證錯誤

| 欄位              | 錯誤訊息                                     | 說明                  |
| --------------- | ---------------------------------------- | ------------------- |
| `email`         | `The email has already been taken.`      | 該商家下已存在相同 email 的客戶 |
| `order_no`      | `The order no has already been taken.`   | 該商家下已存在相同訂單編號       |
| `amount`        | `The amount must be at least 0.`         | 金額不可為負數             |
| `status`        | `The selected status is invalid.`        | 狀態值不在允許的選項中         |
| `billing_cycle` | `The selected billing cycle is invalid.` | 不是有效的計費週期           |

## 錯誤處理範例

<CodeGroup>
  ```javascript Node.js theme={null}
  async function createCustomer(data) {
    const response = await fetch('https://api.zangsho.com/v1/customers', {
      method: 'POST',
      headers: {
        'Authorization': 'Bearer YOUR_API_TOKEN',
        'Content-Type': 'application/json'
      },
      body: JSON.stringify(data)
    });

    if (!response.ok) {
      const error = await response.json();

      switch (response.status) {
        case 401:
          console.error('認證失敗，請檢查 API Token');
          break;
        case 422:
          console.error('驗證錯誤:', error.errors);
          // 處理各欄位的錯誤訊息
          for (const [field, messages] of Object.entries(error.errors)) {
            console.error(`  ${field}: ${messages.join(', ')}`);
          }
          break;
        case 429:
          const retryAfter = response.headers.get('Retry-After');
          console.error(`超過頻率限制，請在 ${retryAfter} 秒後重試`);
          break;
        default:
          console.error('發生錯誤:', error.message);
      }

      return null;
    }

    return await response.json();
  }
  ```

  ```php PHP (Laravel) theme={null}
  $response = Http::withToken('YOUR_API_TOKEN')
      ->post('https://api.zangsho.com/v1/customers', $data);

  if ($response->failed()) {
      match ($response->status()) {
          401 => Log::error('認證失敗，請檢查 API Token'),
          422 => Log::error('驗證錯誤', $response->json('errors')),
          429 => Log::warning('超過頻率限制', [
              'retry_after' => $response->header('Retry-After'),
          ]),
          default => Log::error('發生錯誤', [
              'status' => $response->status(),
              'message' => $response->json('message'),
          ]),
      };
  }
  ```
</CodeGroup>

## 最佳實踐

<AccordionGroup>
  <Accordion title="總是檢查 HTTP 狀態碼">
    不要只依賴回應內容來判斷成功或失敗，務必檢查 HTTP 狀態碼。2xx 代表成功，4xx 代表客戶端錯誤，5xx 代表伺服器錯誤。
  </Accordion>

  <Accordion title="妥善處理 422 驗證錯誤">
    當收到 422 錯誤時，解析 `errors` 物件並針對各欄位顯示對應的錯誤訊息。這能幫助使用者快速修正問題。
  </Accordion>

  <Accordion title="實作指數退避重試">
    對於 429（頻率限制）和 5xx（伺服器錯誤），建議實作指數退避重試策略。讀取 `Retry-After` 標頭來決定等待時間。
  </Accordion>

  <Accordion title="記錄錯誤日誌">
    將 API 錯誤回應記錄到日誌中，包含請求路徑、狀態碼與錯誤訊息，方便日後排查問題。
  </Accordion>
</AccordionGroup>
