# 高度なエラー処理 HTTP レベルのエラーを理解する方法をご紹介します。 このページでは、次の 2 種類の高度なエラー処理に関するトピックについて説明します。 - [エラーを表す HTTP レスポンス](https://docs.stripe.com/error-low-level.md#errors-in-http) - [べき等と再試行](https://docs.stripe.com/error-low-level.md#idempotency) この情報が該当しない場合もあります。Stripe の公式の [SDK](https://docs.stripe.com/sdks.md) は、HTTP および再試行に関する情報を多く扱っています。クライアントライブラリを使用する場合は、こちらから開始できます。 - [エラー処理](https://docs.stripe.com/error-handling.md) - [エラーコード](https://docs.stripe.com/error-codes.md) ## HTTP のエラー API コールが失敗した場合でも、クライアントライブラリでは、[例外を発生させるか、エラーの値を返す](https://docs.stripe.com/error-handling.md)ことでエラー情報を提供します。しかし、クライアントライブラリを使用しない場合、または異常な状況が発生した場合は、HTTP レスポンスと送信のタイミングに関する低レベルの詳細が必要になることがあります。 HTTP の観点から、エラーは次の 3 つの主要なカテゴリーに分類されます。 - [コンテンツエラー](https://docs.stripe.com/error-low-level.md#content-errors): API リクエストに無効なコンテンツが存在する。 - [ネットワークエラー](https://docs.stripe.com/error-low-level.md#network-errors): クライアントとサーバー間に断続的な通信の問題が存在する。 - [サーバーエラー](https://docs.stripe.com/error-low-level.md#server-errors): Stripe のサーバー上の問題。 各タイプのエラーには、異なる対応とべき等のセマンティクスが必要になります。このページの最後には、[レスポンスコードの一覧](https://docs.stripe.com/error-low-level.md#status-codes)とその意味が示されています。 ### コンテンツエラー コンテンツエラーは、API リクエストのコンテンツが無効な場合に発生し、`4xx` の[レスポンスコード](https://docs.stripe.com/api/errors.md#errors-code)を含む HTTP レスポンスが返されます。たとえば、無効な API キーが指定された場合は API サーバーから `401` が返され、必須パラメーターが欠落している場合は `400` が返されます。システムは元のリクエストを修正して再試行する必要があります。ユーザーエラー (カードの支払い拒否など) のタイプによっては、プログラムで問題に対処できることがあります。この場合は、システムが適切に対処できるように `code` フィールドを含めてください。詳細については、[エラーコード](https://docs.stripe.com/error-codes.md)をご覧ください。 べき等キーを使用する `POST` 操作の場合、API メソッドが実行を開始している限り、リクエストの結果に関わらず Stripe の API サーバーは結果をキャッシュします。`400` を返すリクエストは、同じべき等キーを持つ新しいリクエストが続く場合、同じ `400` を送り返します。正常な結果を得るために元のリクエストを変更する際は、新しいべき等キーを生成してください。この操作にはいくつかの注意点があります。たとえば、`429` でレート制限されたリクエストは、API のべき等レイヤーの前にレートリミッタが実行されるため、同じべき等キーで別の結果になる可能性があります。API キーを省略した `401`、または無効なパラメータを送信したほとんどの `400` 番台についても同様です。それでも、`4xx` エラーに関する最も安全な戦略は、常に新しいべき等キーを生成することです。 ### ネットワークエラー ネットワークエラーは、クライアントとサーバー間の接続問題が原因で発生します。ソケットやタイムアウト例外など、低レベルのエラーとして返されます。たとえば、クライアントが Stripe サーバーからの読み取り時にタイムアウトする場合や、接続が途中で切断されるために API レスポンスがまったく返ってこない場合などが該当します。ネットワークエラーは、接続問題を解消すれば成功する可能性が高い *ように* 見えますが、間欠的な問題の裏に別のエラーが潜んでいる場合もあります。 このクラスのエラーは、べき等キーとリクエスト再試行の値が最も明白です。断続的な問題が発生すると、クライアントは通常、サーバーがリクエストを受信したかを確認できない状態になります。明確な回答を得るには、サーバーから結果を受信できるまで、同じべき等キーとパラメーターを使用してそのリクエストを再試行する必要があります。異なるパラメーターで同じべき等を送信すると、新しいリクエストが元のリクエストと一致しなかったことを示すエラーが発生します。 クライアントライブラリの多くは、べき等キーを生成してリクエストを自動的に再試行できますが、そのためには設定が必要です。クライアントライブラリは最初の失敗の直後に最初の再試行を実行しますが、その後の再試行は、単一の失敗はランダムに発生することが多く、同じ失敗が繰り返されるパターンは長期的な問題が発生しているという想定に基づいて、指数バックオフのスケジュールに従って実行されます。 #### Ruby ```ruby Stripe.max_network_retries = 2 ``` ### サーバーエラー サーバーエラーは、Stripe サーバーの問題により発生し、`5xx` エラーコードを含む HTTP レスポンスを返します。これらのエラーは処理が最も困難であり、Stripe は可能な限りこのエラーが発生しないように努めていますが、優れた組み込みではエラーが発生しても処理することができます。 ユーザーエラーと同様に、べき等レイヤーはサーバーエラー (具体的には内部サーバーエラーである `500`番台) を引き起こす `POST` ミューテーションの結果をキャッシュするため、同じべき等キーでそれらを再試行すると、通常同じ結果になります。クライアントは新しいべき等キーを使用してリクエストを再試行できますが、元のキーによって副次的効果が発生している可能性があるため、お勧めしません。 `500` リクエストの結果は不確定として扱う必要があります。発生する可能性が最も高いのは、本番環境でのインシデントであり、通常はインシデントの修復中に起こります。Stripe のエンジニアは失敗リクエストを検証し、`500` になるミューテーションの結果を適切に調整します。これらのリクエストに対してべき等にキャッシュされたレスポンスは変更されませんが、Stripe は、調整の一環として作成された新しいオブジェクトに対して [Webhook](https://docs.stripe.com/webhooks.md) の実行を試みます。システムの遡及的変更の正確な性質は、リクエストタイプに大きく依存します。たとえば、支払いの作成で `500` エラーが返されても、その情報が決済ネットワークに送信されたことが検出された場合、Stripe はその情報に対してロールフォワードを試みます。そうでない場合は、ロールバックを試行します。これで問題が解決しない場合は、ユーザーに表示される `500` エラーのリクエストがお客様にも表示される可能性があります。 > `500` エラーを返すリクエストは不確定なものとして扱います。Stripe はこの不完全な状態を最も適切な方法で照合し、また作成された新規オブジェクトに対する [Webhook](https://docs.stripe.com/webhooks.md) の実行を試みますが、常に最善の結果が得られるわけではありません。 最も広範囲の `500` 番台をシステムで処理するためには、通常の API レスポンスでは受信することがない Event オブジェクトを受信できるように Webhook ハンドラを設定します。このような新しいオブジェクトをシステムのローカル状態のデータと相互参照するための 1 つの手法は、API で新しいリソースを作成するときに、[Metadata (メタデータ)](https://docs.stripe.com/api/metadata.md)を持つローカル識別子を送信することです。その識別子は、Webhook が後で照合の一部として生成される場合でも、Webhook を介して送信されるオブジェクトのメタデータフィールドに表示されます。 ## べき等 [べき等](https://stripe.com/blog/idempotency)とは、同じ操作を何度繰り返しても、初回の試行と同じ結果が得られるという性質として定義された Web API 設計原理です。特に、最初のリクエストがネットワークエラーで応答を得られなかった場合などに、API リクエストの再試行を安全に行うことができます。一定量の断続的なエラーは想定されるため、クライアントには失敗したリクエストをサーバーと照合する方法が必要であり、べき等がそのメカニズムを提供します。 多くのクライアントライブラリは、べき等キーを生成してリクエストを自動的に再試行できますが、そのための設定を行う必要があります。再試行をより細かく制御するには、[べき等キー](https://docs.stripe.com/api/idempotent_requests.md)を生成して、再試行のための独自のロジックを作成します。 ### GET および DELETE リクエスト Stripe API では、`GET` および `DELETE` リクエストのべき等性を保証しているため、常に安全に再試行することができます。 ### POST リクエスト [べき等キー](https://docs.stripe.com/api/idempotent_requests.md)を含めると、`POST` リクエストがべき等性を持つようになり、API は重複操作を避けるために必要な記録の保持を行います。最初にキーを受け取ってから 24 時間以内に 2 回目のリクエストが発生していれば、クライアントはべき等キーを含むリクエストを安全に再試行できます (キーは 24 時間後に有効期限が切れます)。たとえば、オブジェクトを作成するリクエストがネットワーク接続エラーのために応答しない場合には、クライアントが同じべき等キーを使用してリクエストを再試行すれば、重複したオブジェクトが作成されることはありません。 ### べき等キーの送信 べき等キーは、`Idempotency-Key` ヘッダーで送信されます。これを Stripe API へのすべての `POST` リクエストで使用します。ほとんどの公式クライアントライブラリでは、再試行の送信が設定されていれば、自動的に送信できます。 [べき等キーを手動で送信](https://docs.stripe.com/api/idempotent_requests.md)する場合には、使用するトークンが十分に一意であり、過去 24 時間にわたってお客様のアカウント内で 1 つの操作を一義的に識別できるようにしてください。以下にべき等キーを生成する一般的な方法を 2 通り例示します。 - UUID v4 など、十分にランダムなトークンが生成されるアルゴリズムを使用する。 - ショッピングカートの ID など、ユーザーに関連付けられたオブジェクトからキーを派生させる。これは、重複した送信を回避するための比較的シンプルな方法です。 サーバーから再試行しようとしている、以前に実行されたレスポンスを識別するには、`Idempotent-Replayed: true` というヘッダーを探します。 ### Stripe-Should-Retry ヘッダー クライアントライブラリは、ステータスコードやレスポンス本文の内容だけでは、再試行すべきかどうかを判断でない場合があります。API はリクエストが再試行可能であるという追加情報を得た場合、`Stripe-Should-Retry` ヘッダーを指定してレスポンスを返します。 - `Stripe-Should-Retry` を `true` に設定している場合は、クライアントがリクエストを再試行する必要があります。ただしクライアントは、API に過度な負荷をかけないように、次のリクエストを行う前に (おそらく指数バックオフのスケジュールに従って決定される) 一定の時間待つ必要があります。 - `Stripe-Should-Retry` を `false` に設定している場合は、それ以上の効果がないためクライアントはリクエストを再試行「しないでください」。 - レスポンスに `Stripe-Should-Retry` が設定されていない場合は、API はリクエストを再試行できるかどうかを判断できません。クライアントは、レスポンスの他のプロパティ (ステータスコードなど) にフォールバックして判断する必要があります。 Stripe のクライアントライブラリに組み込まれている再試行メカニズムは、`Stripe-Should-Retry` を自動的に考慮します。これらのいずれかを使用している場合は、手動で処理する必要はありません。 ## HTTP ステータスコードリファレンス | | | | | 200 | OK | すべてが想定どおりに動作しました。 | | 400 | Bad Request | リクエストは受け入れられませんでした。多くの場合、必要なパラメーターが足りないことが理由として考えられます。 | | 401 | 無許可 | 有効な API キーが入力されていません。 | | 402 | Request Failed | パラメーターは有効でしたがリクエストが失敗しました。 | | 403 | Forbidden | API キーにリクエストを実行する権限がありません。 | | 409 | Conflict | リクエストが他のリクエストと競合しています (同じ[べき等](https://docs.stripe.com/error-low-level.md#idempotency)キーを使用していることが理由として考えられます)。 | | 424 | 外部の依存関係のエラー | Stripe 外部の依存関係でエラーが発生したため、リクエストを完了できませんでした。 | | 429 | Too Many Requests | 短時間での API へのリクエスト数が多すぎます。[リクエストの指数バックオフを推奨します](https://docs.stripe.com/error-low-level.md#should-retry)。 | | 500、502、503、504 | サーバーエラー | [Stripe 側で問題が発生しました。](https://docs.stripe.com/error-low-level.md#server-errors) |