# Connect Webhook Connect で Webhook を使用して Stripe アクティビティの通知を受ける方法をご紹介します。 アカウントでイベントが発生すると、Stripe は *Webhook* (A webhook is a real-time push notification sent to your application as a JSON payload through HTTPS requests) を使用してアプリケーションに通知します。すべての *Connect* (Connect is Stripe's solution for multi-party businesses, such as marketplace or software platforms, to route payments between sellers, customers, and other recipients) の組み込みでは、[Webhook エンドポイント](https://dashboard.stripe.com/account/webhooks)を設定して、Connect イベントをリッスンする必要があります。 ## Connect Webhook Connect ユーザー向けの Webhook は、イベントのソースに応じて、異なるスコープでイベントをリッスンします。 - **Your account**: アカウント内に存在するリソースによってトリガーされるほとんどのイベント。API キーを使用し、[別の Stripe アカウントとして認証](https://docs.stripe.com/connect/authentication.md)せずに行われたほとんどのリクエストが含まれます。たとえば: - アカウント内の v2 `Accounts` に対する `v2.core.account.*` イベント - アカウント内の `Customers` に対するイベント - アカウントのダイレクト支払いに対するイベント - 連結アカウント向けの、アカウント上の *間接支払い* (A charge type where customers transact directly with your platform instead of with a connected account. Indirect charges include destination charges and separate charges and transfers) に対するイベント - **Connected accounts**: 連結アカウントに存在するリソース、およびアカウントに存在する一部のリソースによってトリガーされるイベント。たとえば: - 連結アカウントの顧客および受取人を表す v2 `Accounts` に対する `v2.core.account.*` イベント - 連結アカウントの顧客および受取人を表す v1 および v2 `Accounts` に対する v1 `account.updated` イベント - 連結アカウントの顧客に対する*ダイレクト支払い* (A charge type where customers transact directly with a connected account, which is always the merchant of record. With each payment, the connected account pays fees to Stripe and, optionally, to your platform) > #### 連結アカウントを表す v2 Accounts のイベントスコープ > > v2 `Account` オブジェクトは v1 と v2 の両方の `Events` をトリガーします。これらのイベントはスコープが異なる場合があります。連結アカウントによってトリガーされるイベントの場合、v2 `Events` は **Your account** スコープを使用し、v1 `Events` は **Connected accounts** スコープを使用します。これは同じ v2 `Account` によってトリガーされた場合でも同様です。 [ワークベンチ](https://dashboard.stripe.com/workbench/webhooks)で Webhook を作成する場合は、 **Events from** を **Your account** または **Connected accounts** に設定してスコープを割り当てます。API を使用して Webhook を作成する場合は、[connect](https://docs.stripe.com/api/webhook_endpoints/create.md#create_webhook_endpoint-connect) パラメーターを false (**Your account**) または true (**Connected accounts**) に設定してスコープを割り当てます。 Connect Webhook の場合、開発環境の Webhook URL はテスト用 Webhook のみを受信しますが、本番環境の Webhook URL は本番環境とテスト環境の両方の Webhook を受信します。これは、本番環境アプリケーションでは本番環境の取引とテスト取引の両方を実行できるためです。イベントの Webhook を受信したら `livemode` の値を確認して、ユーザーによる対応が必要かどうかを判断することをお勧めします。 [サンドボックス](https://docs.stripe.com/sandboxes.md)アカウントのイベントを受信するには、そのアカウント用に個別の Webhook エンドポイントを定義する必要があります。 連結アカウントの各イベントには、連結アカウントを識別する最上位の `account` プロパティが含まれます。連結アカウントは[イベントをトリガーしたオブジェクト](https://docs.stripe.com/api/events/object.md#event_object-data-object)を所有しているため、[連結アカウントとして](https://docs.stripe.com/connect/authentication.md)、そのオブジェクトに対して API リクエストを行う必要があります。 ```json { "id": ""{{EVENT_ID}}"", "livemode": true, "object": "event", "type": "customer.created", "account": ""{{CONNECTED_ACCOUNT_ID}}"", "pending_webhooks": 2, "created": 1349654313, "data": {...} } ``` 次の表は、連結アカウントに関連する最も一般的で重要なイベントのいくつかについて説明したものです。 | イベント | data.object 型 | 説明 | | ---------------------------------- | ------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `account.application.deauthorized` | `application` | 連結アカウントがプラットフォームへの連結を解除すると発生します。これを使用して、サーバーでクリーンアップをトリガーできます。Stripe ダッシュボードにアクセスできる連結アカウント ([Standard アカウント](https://docs.stripe.com/connect/standard-accounts.md)を含む) で利用できます。 | | `account.external_account.updated` | `card` や `bank_account` などの外部口座 | [連結アカウントに関連付けられた銀行口座またはデビットカードが更新された](https://docs.stripe.com/connect/payouts-bank-accounts.md)場合に発生し、入金に影響することがあります。プラットフォームが管理する連結アカウントに適用されます。これには、Custom アカウントと Express アカウント、および[プラットフォーム管理](https://docs.stripe.com/connect/platform-controls-for-stripe-dashboard-accounts.md)が有効な Standard アカウントが含まれます。 | | `account.updated` | `account` | 連結アカウントの要件の変化やステータスの変化を監視できます。すべての連結アカウントで利用可能です。 | | `balance.available` | `balance` | お客様の Stripe 残高が更新されたときに発生します。例えば、[銀行口座から追加した資金](https://docs.stripe.com/connect/top-ups.md)が連結アカウントに送金できるようになったときなどです。 | | `payment_intent.succeeded` | `payment_intent` | 支払いインテントで支払いが成功した場合に発生します。[デスティネーション支払い](https://docs.stripe.com/connect/destination-charges.md)と[ダイレクト支払い](https://docs.stripe.com/connect/direct-charges.md)を含むすべての支払いで利用可能です。 | | `payout.failed` | `payout` | [入金が失敗した](https://docs.stripe.com/connect/payouts-connected-accounts.md#webhooks)場合に発生します。入金が失敗すると、関連する外部口座は無効になり、外部口座が更新されるまで自動でも手動でも入金を行うことはできません。 | | `person.updated` | `person` | `Account` に関連付けられている `Person` が更新されたときに発生します。[Persons API を利用して確認要件に対処する](https://docs.stripe.com/connect/handling-api-verification.md#verification-process)場合は、個人の要件の変化やステータスの変化を監視します。プラットフォームが管理する連結アカウントに適用されます。これには、Custom アカウントと Express アカウント、および[プラットフォーム管理](https://docs.stripe.com/connect/platform-controls-for-stripe-dashboard-accounts.md)が有効な Standard アカウントが含まれます。 | #### イベント - account.application.deauthorized #### Ruby ```ruby # Using Sinatra. require 'sinatra' require 'stripe' set :port, 4242 # 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('<>') # If you're testing your webhook locally with the Stripe CLI, you # can find the endpoint's secret by running `stripe listen` # Otherwise, find your endpoint's secret in your webhook settings in # the Developer Dashboard endpoint_secret = 'whsec_...' post '/webhook' do payload = request.body.read sig_header = request.env['HTTP_STRIPE_SIGNATURE'] event = nil # Verify webhook signature and extract the event. # See https://stripe.com/docs/webhooks#verify-events for more information. begin event = Stripe::Webhook.construct_event( payload, sig_header, endpoint_secret ) rescue JSON::ParserError => e # Invalid payload. status 400 return rescue Stripe::SignatureVerificationError => e # Invalid Signature. status 400 return end if event['type'] == 'account.application.deauthorized' application = event['data']['object'] connected_account_id = event['account'] handle_deauthorization(connected_account_id, application) end status 200 end def handle_deauthorization(connected_account_id, application) # Clean up account state. puts 'Connected account ID: ' + connected_account_id puts application.to_s end ``` #### イベント - account.updated #### Ruby ```ruby # Using Sinatra. require 'sinatra' require 'stripe' set :port, 4242 # 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('<>') # If you're testing your webhook locally with the Stripe CLI, you # can find the endpoint's secret by running `stripe listen` # Otherwise, find your endpoint's secret in your webhook settings in # the Developer Dashboard endpoint_secret = 'whsec_...' post '/webhook' do payload = request.body.read sig_header = request.env['HTTP_STRIPE_SIGNATURE'] event = nil # Verify webhook signature and extract the event. # See https://stripe.com/docs/webhooks#verify-events for more information. begin event = Stripe::Webhook.construct_event( payload, sig_header, endpoint_secret ) rescue JSON::ParserError => e # Invalid payload. status 400 return rescue Stripe::SignatureVerificationError => e # Invalid Signature. status 400 return end if event['type'] == 'account.updated' account = event['data']['object'] handle_account_update(account) end status 200 end def handle_account_update(account) # Collect more required information puts account.to_s end ``` #### イベント - person.updated #### Ruby ```ruby # Using Sinatra. require 'sinatra' require 'stripe' set :port, 4242 # 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('<>') # If you're testing your webhook locally with the Stripe CLI, you # can find the endpoint's secret by running `stripe listen` # Otherwise, find your endpoint's secret in your webhook settings in # the Developer Dashboard endpoint_secret = 'whsec_...' post '/webhook' do payload = request.body.read sig_header = request.env['HTTP_STRIPE_SIGNATURE'] event = nil # Verify webhook signature and extract the event. # See https://stripe.com/docs/webhooks#verify-events for more information. begin event = Stripe::Webhook.construct_event( payload, sig_header, endpoint_secret ) rescue JSON::ParserError => e # Invalid payload. status 400 return rescue Stripe::SignatureVerificationError => e # Invalid Signature. status 400 return end if event['type'] == 'person.updated' person = event['data']['object'] connected_account_id = event['account'] handle_person_update(connected_account_id, person) end status 200 end def handle_person_update(connected_account_id, person) # Collect more required information puts 'Connected account ID: ' + connected_account_id puts person.to_s end ``` #### イベント - payment_intent.succeeded、ダイレクト支払い #### Ruby ```ruby # Using Sinatra. require 'sinatra' require 'stripe' set :port, 4242 # 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('<>') # If you are testing your webhook locally with the Stripe CLI you # can find the endpoint's secret by running `stripe listen` # Otherwise, find your endpoint's secret in your webhook settings in # the Developer Dashboard endpoint_secret = 'whsec_...' post '/webhook' do payload = request.body.read sig_header = request.env['HTTP_STRIPE_SIGNATURE'] event = nil # Verify webhook signature and extract the event. # See https://stripe.com/docs/webhooks#verify-events for more information. begin event = Stripe::Webhook.construct_event( payload, sig_header, endpoint_secret ) rescue JSON::ParserError => e # Invalid payload. status 400 return rescue Stripe::SignatureVerificationError => e # Invalid Signature. status 400 return end if event['type'] == 'payment_intent.succeeded' payment_intent = event['data']['object'] connected_account_id = event['account'] handle_successful_payment_intent(connected_account_id, payment_intent) end status 200 end def handle_successful_payment_intent(connected_account_id, payment_intent) # Fulfill the purchase puts 'Connected account ID: ' + connected_account_id puts payment_intent.to_s end ``` #### イベント - payment_intent.succeeded、ダイレクト支払い以外 #### Ruby ```ruby # Using Sinatra. require 'sinatra' require 'stripe' set :port, 4242 # 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('<>') # If you are testing your webhook locally with the Stripe CLI you # can find the endpoint's secret by running `stripe listen` # Otherwise, find your endpoint's secret in your webhook settings in # the Developer Dashboard endpoint_secret = 'whsec_...' post '/webhook' do payload = request.body.read sig_header = request.env['HTTP_STRIPE_SIGNATURE'] event = nil # Verify webhook signature and extract the event. # See https://stripe.com/docs/webhooks#verify-events for more information. begin event = Stripe::Webhook.construct_event( payload, sig_header, endpoint_secret ) rescue JSON::ParserError => e # Invalid payload. status 400 return rescue Stripe::SignatureVerificationError => e # Invalid Signature. status 400 return end if event['type'] == 'payment_intent.succeeded' payment_intent = event['data']['object'] handle_successful_payment_intent(payment_intent) end status 200 end def handle_successful_payment_intent(payment_intent) # Fulfill the purchase puts payment_intent.to_s end ``` #### イベント - balance.available #### Ruby ```ruby # Using Sinatra. require 'sinatra' require 'stripe' set :port, 4242 # 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('<>') # If you're testing your webhook locally with the Stripe CLI, you # can find the endpoint's secret by running `stripe listen` # Otherwise, find your endpoint's secret in your webhook settings in # the Developer Dashboard endpoint_secret = 'whsec_...' post '/webhook' do payload = request.body.read sig_header = request.env['HTTP_STRIPE_SIGNATURE'] event = nil # Verify webhook signature and extract the event. # See https://stripe.com/docs/webhooks#verify-events for more information. begin event = Stripe::Webhook.construct_event( payload, sig_header, endpoint_secret ) rescue JSON::ParserError => e # Invalid payload. status 400 return rescue Stripe::SignatureVerificationError => e # Invalid Signature. status 400 return end if event['type'] == 'balance.available' balance = event['data']['object'] handle_available_balance(balance) end status 200 end def handle_available_balance(balance) # Transfer funds to a connected account puts balance.to_s end ``` #### イベント - account.external_account.updated #### Ruby ```ruby # Using Sinatra. require 'sinatra' require 'stripe' set :port, 4242 # 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('<>') # If you're testing your webhook locally with the Stripe CLI, you # can find the endpoint's secret by running `stripe listen` # Otherwise, find your endpoint's secret in your webhook settings in # the Developer Dashboard endpoint_secret = 'whsec_...' post '/webhook' do payload = request.body.read sig_header = request.env['HTTP_STRIPE_SIGNATURE'] event = nil # Verify webhook signature and extract the event. # See https://stripe.com/docs/webhooks#verify-events for more information. begin event = Stripe::Webhook.construct_event( payload, sig_header, endpoint_secret ) rescue JSON::ParserError => e # Invalid payload. status 400 return rescue Stripe::SignatureVerificationError => e # Invalid Signature. status 400 return end if event['type'] == 'account.external_account.updated' external_account = event['data']['object'] connected_account_id = event['account'] handle_external_account_update(connected_account_id, external_account) end status 200 end def handle_external_account_update(connected_account_id, external_account) # Transfer funds to a connected account puts 'Connected account ID: ' + connected_account_id puts external_account.to_s end ``` #### イベント - payout.failed #### Ruby ```ruby # Using Sinatra. require 'sinatra' require 'stripe' set :port, 4242 # 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('<>') # If you're testing your webhook locally with the Stripe CLI, you # can find the endpoint's secret by running `stripe listen` # Otherwise, find your endpoint's secret in your webhook settings in # the Developer Dashboard endpoint_secret = 'whsec_...' post '/webhook' do payload = request.body.read sig_header = request.env['HTTP_STRIPE_SIGNATURE'] event = nil # Verify webhook signature and extract the event. # See https://stripe.com/docs/webhooks#verify-events for more information. begin event = Stripe::Webhook.construct_event( payload, sig_header, endpoint_secret ) rescue JSON::ParserError => e # Invalid payload. status 400 return rescue Stripe::SignatureVerificationError => e # Invalid Signature. status 400 return end if event['type'] == 'payout.failed' payout = event['data']['object'] connected_account_id = event['account'] handle_failed_payout(connected_account_id, payout) end status 200 end def handle_failed_payout(connected_account_id, payout) # Re-collect bank account required information puts 'Connected account ID: ' + connected_account_id puts payout.to_s end ``` ## Webhook をローカルでテストする Stripe CLI を使用してイベント Webhook をローカルでテストするには: 1. まだインストールしていない場合は、[Stripe CLI をマシンにインストール](https://docs.stripe.com/stripe-cli/install.md)してください。 1. Stripe アカウントにログインし、コマンドラインで `stripe login` を実行して CLI を設定します。 1. イベントのスコープに応じて [stripe listen](https://docs.stripe.com/cli/listen) を実行し、ローカルホストがシミュレートされたイベントを受信できるようにします。 - **Connected accounts**: `stripe listen --forward-connect-to localhost:{{PORT}}/{{CONNECT_WEBHOOK_ENDPOINT}}` - **Your account**: `stripe listen --forward-to localhost:{{PORT}}/{{WEBHOOK_ENDPOINT}}` 1. 別の端末ウィンドウで、イベントのスコープに応じて [stripe trigger](https://docs.stripe.com/cli/trigger) を実行し、シミュレートされたイベントをトリガーします。 - **Connected accounts**: `stripe trigger --stripe-account {{CONNECTED_ACCOUNT_ID}} {{EVENT_NAME}}` - **Your account**: `stripe trigger {{EVENT_NAME}}` ## See also - [Webhook に関するドキュメント](https://docs.stripe.com/webhooks.md) - [Event オブジェクトのリファレンス](https://docs.stripe.com/api.md#events)