API Response Contract

文件狀態:已對 legacy migration 實務
最後驗證:2026-05-14
來源:quote_bids/change_status/reviews migration response shape 修正

這份文件回答什麼

這份文件規範 legacy API 搬到 new API 時,response 格式要如何比對與保護。

重點不是「成功或失敗語意看起來一樣」就算完成,而是 response shape 也要一致。欄位是否存在、欄位名稱、大小寫、型別、空值、錯誤碼與 message 都是 API contract。

不回答什麼

  • 不整理單支 API 的完整 business rule。
  • 不取代 repo 內的 migration detail 文件。
  • 不定義新 API 的全域 response 標準。

核心規則

Legacy-compatible endpoint 必須以 legacy response 為準。

如果 legacy 成功只回:

{
  "status": "Success"
}

new API 就不能自行加成:

{
  "status": "Success",
  "error": 0
}

即使 error: 0 在其他 endpoint 或其他 filter 很常見,也不能拿來推論這支 API 可以新增。

為什麼新增欄位也算破壞相容

新增欄位看似 harmless,但前端、App、SDK 或測試可能有以下行為:

  • 嚴格比對 response JSON。
  • error 是否存在判斷錯誤流程,而不是只看值。
  • status 當唯一成功欄位。
  • 對不同 filter 做不同 fallback。
  • 把 response 原樣傳給其他流程或分析工具。

所以 migration 時不能把「多一個欄位通常沒差」當假設。

必查項目

搬移 legacy endpoint 前,至少要確認:

  1. 成功 response 是否有 error 欄位。
  2. 成功 response 的 status 值與大小寫。
  3. 失敗 response 的 error 型別與 code。
  4. 失敗 response 的 message 欄位名稱,例如 status / message / error_message
  5. 特定成功情境是否有額外欄位,例如 completed_onclosed_onbank_result_code
  6. 空 request / guard fail 是否 early return,且 response 是否比一般 catch 少欄位。

實作規則

  • 不要用其他 API 的 response pattern 猜這支 API。
  • 不要因為 controller helper 常見 error=0 就補上。
  • 不要把 PHPUnit 寫成期待「新標準」,測試應該鎖 legacy response。
  • 若要刻意改善 response 格式,必須明確標記為 breaking / product decision,不能混在 migration commit。
  • migration docs 的 curl 範例必須跟實際 legacy response shape 一致。

測試規則

成功 response 如果 legacy 沒有 error,測試要明確寫:

$this->assertSame('Success', $response['status']);
$this->assertArrayNotHasKey('error', $response);

不要寫:

$this->assertSame(0, (int)$response['error']);

這會把不存在的欄位誤改成新 contract。

反例:reviews migration

/quote_bids/change_status/reviews/{quote_bid_id}.json 的 legacy 一般成功 response 是:

{
  "status": "Success"
}

不能回:

{
  "status": "Success",
  "error": 0
}

雖然同一支 legacy controller 的其他 change_status filter 可能會回 error: 0,但 reviews 分支一般成功只設定 status,最後直接輸出 $gen_bids

Review Checklist

送出 migration commit 前,逐項確認:

  • legacy code 中該 filter / action 的最後 response 寫法已讀過。
  • 專案 migration detail 有列成功與失敗 response 範例。
  • PHPUnit 有鎖 response shape,不只鎖 side effect。
  • 實測 curl response 與 legacy shape 一致。
  • 若 response shape 與 legacy 不同,commit message 和文件有明確說明原因。

相關文件