# 未配信の Webhook イベントを処理する 未配信の Webhook イベントを手動で処理する方法をご紹介します。 Webhook エンドポイントが一時的にイベントを処理できない場合、Stripe は配信されなかったイベントを最大 3 日間エンドポイントに[自動的に再送信](https://docs.stripe.com/webhooks.md#automatic-retries)します。そのため、Webhook エンドポイントがすべてのイベントを受信して処理するまでの時間が長くなります。 このガイドでは、未配信のイベントを手動で処理してプロセスをスピードアップする方法について説明します。 ## Webhook イベントを一覧表示する 以下のパラメーターを使用して [List Events (イベントの一覧表示)](https://docs.stripe.com/api/events/list.md) API を呼び出します。 - `ending_before`: Webhook エンドポイントが使用できなくなる直前に送信されたイベント ID を指定します。 - `types`: 取得するイベントタイプのリストを指定します。 - `delivery_success`: `false` に設定すると、Webhook エンドポイントの 1 つ以上に配信できなかったイベントを取得します。 Stripe は、過去 30 日間に作成されたイベントのみを返します。 ```curl curl -G https://api.stripe.com/v1/events \ -u "<>:" \ -d ending_before=evt_001 \ -d "types[]=payment_intent.succeeded" \ -d "types[]=payment_intent.payment_failed" \ -d delivery_success=false ``` デフォルトでは、レスポンスで最大 10 件のイベントが返されます。すべてのイベントを取得するには、結果を取得した後に[自動ページ分割](https://docs.stripe.com/api/pagination/auto.md)を使用します。 #### Ruby ```ruby # Don't put any keys in code. See https://docs.stripe.com/keys-best-practices. # Find your keys at https://dashboard.stripe.com/apikeys. client = Stripe::StripeClient.new('<>') events = client.v1.events.list({ ending_before: 'evt_001', types: ['payment_intent.succeeded', 'payment_intent.payment_failed'], delivery_success: false, }) events.auto_paging_each do |event| # This function is defined in the next section process_event(event) end ``` 自動ページ分割で `ending_before` を使用すると、イベントが時系列で返されます。そのため、作成された順序でイベントを処理できます。 ## イベントを処理する お客様固有のロジックに従って、処理に失敗したイベントのみを処理し、次のように 1 つのイベントが複数回処理されないようにします。 - スクリプトを 2 回連続して誤って実行した - Stripe が未処理のイベントを自動的に再送信するのと同時にスクリプトを実行する #### Ruby ```ruby def process_event(event) if is_processing_or_processed(event) puts "skipping event #{event.id}" else puts "processing event #{event.id}" mark_as_processing(event) # Process the event # ... mark_as_processed(event) end end ``` 処理の重複を防ぐ以下の関数を定義します。 - `is_processing_or_processed`: データベース内のイベントのステータスを確認します。 - `mark_as_processing`: データベースを更新して、イベントを処理中としてマークします。 - `mark_as_processed`: データベースを更新して、イベントを処理済みとしてマークします。 ## 自動再試行に応答する Stripe では引き続き、お客様が手動で処理されたイベントを未送信と見なし、自動的に再試行を行います。 Webhook エンドポイントがすでに処理されたイベントを受信した場合は、そのイベントを無視して成功レスポンスを返し、以降の再試行を停止します。 #### Ruby ```ruby require 'json' require 'stripe' client = Stripe::StripeClient.new(ENV.fetch('STRIPE_API_KEY')) # Using Sinatra post '/webhook' do payload = request.body.read event = nil begin event = Stripe::Event.construct_from( JSON.parse(payload, symbolize_names: true) ) rescue JSON::ParserError => e # Invalid payload status 400 return end if is_processing_or_processed(event) puts "skipping event #{event.id}" else puts "processing event #{event.id}" mark_as_processing(event) # Process the event # ... mark_as_processed(event) end status 200 end ```