# Webhooks de Connect Aprende a usar webhooks con Connect para recibir notificaciones de la actividad de Stripe. Stripe utiliza *webhooks* (A webhook is a real-time push notification sent to your application as a JSON payload through HTTPS requests) para notificar a tu aplicación cuando hay algún evento en tu cuenta. Todas las integraciones de *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) deben establecer un [punto de conexión de webhooks](https://dashboard.stripe.com/account/webhooks) para escuchar los eventos de Connect. ## Webhooks de Connect Los webhooks para usuarios de Connect escuchan eventos en diferentes alcances, según el origen del evento: - **Tu cuenta**: la mayoría de los eventos que activan los recursos que existen en tu cuenta. Esto incluye la mayoría de las solicitudes realizadas con tus claves de API y sin [autenticarte como otra cuenta de Stripe](https://docs.stripe.com/connect/authentication.md), como los siguientes: - Eventos `v2.core.account.*` para `Accounts` v2 en tu cuenta - Eventos para `Clientes` en tu cuenta - Eventos para cargos Direct en tu cuenta - Eventos para *cargos indirectos* (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) en tu cuenta para tus cuentas conectadas - **Cuentas conectadas**: eventos que activan los recursos que existen en cuentas conectadas y algunos recursos que existen en tu cuenta, como los siguientes: - Eventos `v2.core.account.*` para `Accounts` v2 que representan clientes y destinatarios de tus cuentas conectadas - Eventos `account.updated` v1 para `Accounts` v1 y v2 que representan clientes y destinatarios de tus cuentas conectadas - *Cargos Direct* (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) para clientes de tus cuentas conectadas > #### Alcances de eventos para Accounts v2 que representan cuentas conectadas > > Los objetos `Account` v2 activan `Events` v1 y v2, que pueden tener diferentes alcances. Para los eventos activados por cuentas conectadas, los `Events` v2 usan el alcance **Tu cuenta**, mientras que los `Events` v1 usan el alcance **Cuentas conectadas**, incluso cuando los activa el mismo `Account` v2. Cuando creas un webhook en [Workbench](https://dashboard.stripe.com/workbench/webhooks), asigna el alcance mediante la configuración de **Eventos de** como **Tu cuenta** o **Cuentas conectadas**. Cuando creas un webhook con la API, asigna el alcance mediante la configuración del parámetro [connect](https://docs.stripe.com/api/webhook_endpoints/create.md#create_webhook_endpoint-connect) en false (para **Tu cuenta**) o en true (para **Cuentas conectadas**). En el caso de los webhooks Connect, las URL de webhooks de desarrollo solo reciben webhooks de prueba, pero las URL de webhooks de producción reciben webhooks activos y de prueba. Esto se debe a que puedes realizar transacciones en vivo y de prueba en una aplicación de producción. Te recomendamos que verifiques el valor `livemode` cuando recibas un webhook de evento para determinar si los usuarios deben realizar alguna acción. Debes definir puntos de conexión webhook independientes para tus cuentas del [entorno de prueba](https://docs.stripe.com/sandboxes.md) a fin de recibir los eventos de dichas cuentas. Cada evento de una cuenta conectada contiene una propiedad `account` de nivel superior que identifica a la cuenta conectada. Debido a que la cuenta conectada es titular del [objeto que activó el evento](https://docs.stripe.com/api/events/object.md#event_object-data-object), debes realizar solicitudes API para ese objeto [como cuenta conectada](https://docs.stripe.com/connect/authentication.md). ```json { "id": ""{{EVENT_ID}}"", "livemode": true, "object": "event", "type": "customer.created", "account": ""{{CONNECTED_ACCOUNT_ID}}"", "pending_webhooks": 2, "created": 1349654313, "data": {...} } ``` En la siguiente tabla se describen algunos de los eventos más comunes e importantes relacionados con las cuentas conectadas: | Evento | tipo data.object | Descripción | | ---------------------------------- | ------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `account.application.deauthorized` | `application` | Ocurre cuando una cuenta conectada se desconecta de tu plataforma. Puedes usarlo para activar la limpieza en tu servidor. Disponible para cuentas conectadas con acceso al Dashboard de Stripe, que incluye [cuentas Standard](https://docs.stripe.com/connect/standard-accounts.md). | | `account.external_account.updated` | AUna cuenta externa, como `card` o `bank_account` | Tiene lugar cuando [se actualiza una cuenta bancaria o tarjeta de débito asociada a una cuenta conectada](https://docs.stripe.com/connect/payouts-bank-accounts.md), lo que puede influir en las transferencias a cuentas bancarias. Disponible para las cuentas conectadas que tu plataforma controla, que incluye cuentas Custom y Express, y cuentas Standard con [controles de plataforma](https://docs.stripe.com/connect/platform-controls-for-stripe-dashboard-accounts.md) habilitados. | | `account.updated` | `account` | Te permite monitorear los cambios en los requisitos de la cuenta conectada y los cambios de estado. Disponible para todas las cuentas conectadas. | | `balance.available` | `balance` | Se produce cuando se actualiza tu saldo de Stripe. Por ejemplo, cuando los [fondos que agregaste desde tu cuenta bancaria](https://docs.stripe.com/connect/top-ups.md) están disponibles para transferir a tu cuenta conectada. | | `payment_intent.succeeded` | `payment_intent` | Tiene lugar cuando un intento de pago se convierte en un cargo efectuado correctamente. Disponible para todos los pagos, incluidos los cargos a un [destino](https://docs.stripe.com/connect/destination-charges.md) y [Direct](https://docs.stripe.com/connect/direct-charges.md). | | `payout.failed` | `payout` | Tiene lugar cuando [falla una transferencia](https://docs.stripe.com/connect/payouts-connected-accounts.md#webhooks). Cuando una transferencia falla, se deshabilita la cuenta externa involucrada y no se pueden procesar transferencias automáticas ni manuales hasta que no se actualiza la cuenta externa. | | `person.updated` | `person` | Ocurre cuando se actualiza una `Person` asociada con `Account`. Si [usas la API Persons para gestionar los requisitos](https://docs.stripe.com/connect/handling-api-verification.md#verification-process), recibe notificaciones de este evento para monitorear los cambios en los requisitos y los cambios de estado para particulares. Disponible para las cuentas conectadas que tu plataforma controla, que incluye cuentas Custom y Express, y cuentas Standard con [controles de plataforma](https://docs.stripe.com/connect/platform-controls-for-stripe-dashboard-accounts.md) habilitados. | #### Evento - 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 ``` #### Evento - 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 ``` #### Evento - 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 ``` #### Evento - payment_intent.succeeded, cargo Direct #### 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 ``` #### Evento - payment_intent.succeeded, cargo no Direct #### 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 ``` #### Evento - 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 ``` #### Evento - 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 ``` #### Evento - 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 ``` ## Probar webhooks a nivel local Para probar los webhooks de eventos de forma local con la CLI de Stripe: 1. Si aún no lo haz hecho, [instala la CLI de Stripe](https://docs.stripe.com/stripe-cli/install.md) en tu máquina. 1. Inicia sesión en tu cuenta de Stripe y configura la CLI ejecutando `stripe login` en la línea de comandos. 1. Permite que tu host local reciba un evento simulado mediante la ejecución de [stripe listen](https://docs.stripe.com/cli/listen), según el alcance del evento: - **Cuentas conectadas**: `stripe listen --forward-connect-to localhost:{{PORT}}/{{CONNECT_WEBHOOK_ENDPOINT}}` - **Tu cuenta**: `stripe listen --forward-to localhost:{{PORT}}/{{WEBHOOK_ENDPOINT}}` 1. En otra ventana de terminal, activa un evento simulado mediante la ejecución de [stripe trigger](https://docs.stripe.com/cli/trigger), según el alcance del evento: - **Cuentas conectadas**: `stripe trigger --stripe-account {{CONNECTED_ACCOUNT_ID}} {{EVENT_NAME}}` - **Tu cuenta**: `stripe trigger {{EVENT_NAME}}` ## See also - [Documentación de webhooks](https://docs.stripe.com/webhooks.md) - [Referencia sobre el objeto Event](https://docs.stripe.com/api.md#events)