# 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 Una plataforma Connect utiliza dos tipos de webhooks: - Los webhooks *Account* son para actividades en tu propia cuenta (por ejemplo, la mayoría de las solicitudes hechas con tus claves API cuando no [te autenticas como otra cuenta de Stripe](https://docs.stripe.com/connect/authentication.md)). Esto incluye todo tipo de cargos, excepto los efectuados directamente en una cuenta conectada. - Los webhooks *Connect* son para actividades en cualquier cuenta conectada. Enviamos todos los eventos de la cuenta conectada (incluidas las actualizaciones de la cuenta y los cargos Direct) a los webhooks de Connect. Al crear un webhook de Connect, debes configurarlo para recibir eventos de webhooks de Connect. Cuando lo crees en [el Dashboard](https://dashboard.stripe.com/test/webhooks), selecciona **Eventos en cuentas conectadas** para **Recibe notificaciones de**. Cuando lo crees con una API, establece el [parámetro connect](https://docs.stripe.com/api/webhook_endpoints/create.md#create_webhook_endpoint-connect) en verdadero. ![Configuración de webhook en el Dashboard de Stripe](https://b.stripecdn.com/docs-statics-srv/assets/webhooks.ac3d6c19a5281fbbd2b85a335cd887b3.png) 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 webook 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 Puedes probar webhooks a nivel 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. Le permite a tu host local recibir un evento simulado en tu cuenta conectada ejecutando `stripe listen --forward-to localhost:{PORT}/webhook` en una ventana de terminal y `stripe trigger {{EVENT_NAME}}` en otra. > Para webhooks de Connect, usa [–forward-connect-to](https://docs.stripe.com/cli/listen#listen-forward-connect-to) con `stripe listen` y [–stripe-account](https://docs.stripe.com/cli/trigger#trigger-stripe_account) con `stripe trigger` ## See also - [Documentación de webhooks](https://docs.stripe.com/webhooks.md) - [Referencia sobre el objeto Event](https://docs.stripe.com/api.md#events)