# Recibe los eventos de Stripe en el punto de conexión de tu webhook

Examina los eventos de Stripe en tu punto de conexión webhook para que tu integración pueda activar reacciones automáticamente.

Puedes crear un punto de conexión de webhook HTTPS para recibir eventos. Una vez que registres un punto de conexión de webhook, Stripe le enviará datos en tiempo real cuando ocurran [eventos](https://docs.stripe.com/event-destinations.md#events-overview) en tu cuenta de Stripe. Stripe usa HTTPS para enviar eventos de webhook a tu aplicación en forma de carga de JSON que incluye información del evento.

La recepción de eventos de webhook te ayuda a responder a eventos asincrónicos, como cuando el banco de un cliente confirma un pago, un cliente disputa un cargo o un pago recurrente se realiza correctamente.

También puedes consumir eventos de Stripe en tu infraestructura de AWS o Azure enviándolos directamente a [Amazon EventBridge](https://docs.stripe.com/event-destinations/eventbridge.md) o [Azure Event Grid](https://docs.stripe.com/event-destinations/eventgrid.md).

Completa los pasos a continuación para empezar a recibir eventos de webhook en tu aplicación. Puedes registrar y crear un punto de conexión para gestionar varios tipos de eventos diferentes al mismo tiempo o configurar puntos de conexión individuales para eventos específicos.

## Configura tu punto de conexión

Usa la [API](https://docs.stripe.com/api/v2/event-destinations.md) o la pestaña [Webhooks](https://dashboard.stripe.com/webhooks) en Workbench para registrar la URL accesible de tu punto de conexión de webhook para que Stripe sepa dónde entregar los eventos. Puedes registrar hasta 16 puntos de conexión de webhook con Stripe. Los puntos de conexión de webhook registrados deben ser URL HTTPS de acceso público.

- Si tienes un servidor localhost pero no tienes una URL HTTPS de acceso público, puedes usar una herramienta de tunelización como [ngrok](https://ngrok.com/) para generar una URL HTTPS de acceso público temporal con fines de prueba.
- Como alternativa, puedes [hacer pruebas de forma local con la CLI de Stripe](https://docs.stripe.com/webhooks.md#local-listener) antes de registrar una URL HTTPS de acceso público.

### Formato de URL de webhooks

El formato de URL para registrar un punto de conexión de webhook es el siguiente:

```
https://<your-website>/<your-webhook-endpoint>
```

Por ejemplo, si tu dominio es `https://mycompanysite.com` y la ruta a tu punto de conexión de webhook es `@app.route('/stripe_webhooks', methods=['POST'])`, especifica `https://mycompanysite.com/stripe_webhooks` como URL del punto de conexión.

### Crea un destino de evento para el punto de conexión de tu webhook

#### Dashboard

Para crear un nuevo punto de conexión de webhook en el Dashboard, haz lo siguiente:

1. Abre la pestaña [Webhooks](https://dashboard.stripe.com/webhooks) en Workbench.
2. Haz clic en **Crear un destino de evento**.
3. Selecciona **Tu cuenta** para escuchar los eventos de tu propia cuenta.
4. Selecciona la versión de la API para el [objeto de eventos](https://docs.stripe.com/api/events.md) que quieras consumir.
5. Selecciona los [tipos de eventos](https://docs.stripe.com/api/events/types.md) que quieras enviar a un punto de conexión de webhook.
6. Selecciona **Continuar** y, a continuación, elige **Punto de conexión de webhook** como tipo de destino.
7. Haz clic en **Continuar** y, a continuación, proporciona la **URL de punto de conexión** y una descripción opcional del webhook.
8. En la página de configuración del webhook, aparece un secreto de firma que empieza por `whsec_`. Haz clic en **Revelar secreto** y copia el valor para usarlo cuando [crees un controlador](https://docs.stripe.com/webhooks.md#webhook-endpoint-def).

> [Workbench](https://docs.stripe.com/workbench.md) reemplaza el [Dashboard para desarrolladores](https://docs.stripe.com/development/dashboard.md) existente. Aún puedes [crear un nuevo punto de conexión de webhook](https://docs.stripe.com/development/dashboard/webhooks.md) en el Dashboard para desarrolladores, aunque te recomendamos usar Workbench.

#### API

Usa el punto de conexión [/v2/core/event_destinations](https://docs.stripe.com/api/v2/event-destinations.md) para registrar un nuevo punto de conexión.

#### Eventos instantáneos

Para escuchar [eventos de resumen](https://docs.stripe.com/api/events/types.md) de tu propia cuenta, establece el valor de [event_payload](https://docs.stripe.com/api/v2/core/event-destinations/create.md#v2_create_event_destinations-event_payload) en `snapshot` y el valor de [enabled_events](https://docs.stripe.com/api/v2/core/event-destinations/create.md#v2_create_event_destinations-enabled_events) en los tipos de eventos que quieras enviar al punto de conexión de webhook:

```curl
curl -X POST https://api.stripe.com/v2/core/event_destinations \
  -H "Authorization: Bearer <<YOUR_SECRET_KEY>>" \
  -H "Stripe-Version: 2026-08-26.preview" \
  --json '{
    "name": "My event destination",
    "type": "webhook_endpoint",
    "events_from": [
        "@self"
    ],
    "event_payload": "snapshot",
    "enabled_events": [
        "payment_intent.succeeded",
        "payment_intent.payment_failed"
    ],
    "webhook_endpoint": {
        "url": "https://mycompanysite.com/webhook"
    },
    "include": [
        "webhook_endpoint.signing_secret"
    ]
  }'
```

El resultado contiene un valor `webhook_endpoint.signing_secret` que empieza por `whsec_`. Copia este valor para usarlo cuando [crees un controlador](https://docs.stripe.com/webhooks.md#webhook-endpoint-def).

#### Eventos ligeros

Si estás utilizando [eventos ligeros](https://docs.stripe.com/api/v2/core/events/event-types.md), tendrás que registrar un punto de conexión de webhook distinto. Obtén más información sobre [las diferencias entre los eventos ligeros y los de instantánea](https://docs.stripe.com/event-destinations.md#events-overview).

Para escuchar [eventos ligeros](https://docs.stripe.com/api/v2/core/events/event-types.md) de tu propia cuenta, establece el valor de [event_payload](https://docs.stripe.com/api/v2/core/event-destinations/create.md#v2_create_event_destinations-event_payload) en `thin` y el valor de [enabled_events](https://docs.stripe.com/api/v2/core/event-destinations/create.md#v2_create_event_destinations-enabled_events) en los tipos de eventos que quieras enviar al punto de conexión de webhook:

```curl
curl -X POST https://api.stripe.com/v2/core/event_destinations \
  -H "Authorization: Bearer <<YOUR_SECRET_KEY>>" \
  -H "Stripe-Version: 2026-08-26.preview" \
  --json '{
    "name": "My event destination",
    "type": "webhook_endpoint",
    "events_from": [
        "@self"
    ],
    "event_payload": "thin",
    "enabled_events": [
        "v1.billing.meter.error_report_triggered"
    ],
    "webhook_endpoint": {
        "url": "https://mycompanysite.com/webhook"
    },
    "include": [
        "webhook_endpoint.signing_secret"
    ]
  }'
```

El resultado contiene un valor `webhook_endpoint.signing_secret` que empieza por `whsec_`. Copia este valor para usarlo cuando [crees un controlador](https://docs.stripe.com/webhooks.md#webhook-endpoint-def).

### Haz pruebas de forma local sin una URL registrada

Si no tienes registrada una URL HTTPS de acceso público, puedes hacer pruebas de webhooks de forma local mediante la CLI de Stripe para [reenviar eventos a tu punto de conexión local](https://docs.stripe.com/cli/use-cli#forward-events-to-your-local-webhook-endpoint):

1. Si aún no lo has hecho, [instala la CLI de Stripe](https://docs.stripe.com/cli/install) en tu equipo.

2. Inicia sesión en tu cuenta de Stripe y configura la CLI ejecutando `stripe login` en la línea de comandos.

3. Permite que tu host local reciba un evento simulado ejecutando [stripe listen](https://docs.stripe.com/cli/listen), en función del alcance y tipo de evento:

   #### Reenviar eventos de instantáneas

   Usa el siguiente comando para reenviar [eventos de resumen](https://docs.stripe.com/event-destinations.md#events-overview) de tu cuenta a tu receptor local.

   ```bash
   stripe listen --forward-to localhost:4242/webhook
   ```

   #### Reenviar eventos ligeros

   Usa el siguiente comando para reenviar [eventos ligeros](https://docs.stripe.com/event-destinations.md#events-overview) de tu cuenta a tu receptor local.

   ```bash
   stripe listen --forward-thin-to localhost:4242/webhook --thin-events "*"
   ```

   Este comando da por hecho que tienes un sitio web de localhost en el puerto 4242 con un punto de conexión `POST /webhook`, que puedes configurar cuando [crees un controlador](https://docs.stripe.com/webhooks.md#webhook-endpoint-def).

4. El comando `stripe listen` genera el `{{WEBHOOK_SIGNING_SECRET}}`. Copia este valor para usarlo cuando [crees un controlador](https://docs.stripe.com/webhooks.md#webhook-endpoint-def).

   ```output
   Ready! Your webhook signing secret is '{{WEBHOOK_SIGNING_SECRET}}' (^C to quit)
   ```

> Para usar el argumento `--forward-to` con `stripe listen`, debes ejecutar el comando con la [CLI de Stripe](https://docs.stripe.com/cli.md) en un terminal. Este comando no se puede ejecutar en el [Shell de Workbench](https://docs.stripe.com/workbench/shell.md) porque no admite el argumento `--forward-to`.

## Crear un controlador

Configura una función de punto de conexión HTTP o HTTPS que pueda aceptar peticiones de webhooks con un método POST. Si todavía estás desarrollando su función de punto de conexión en tu máquina local, puedes usar HTTP. Después de que sea de acceso público, la función de punto de conexión de tu webhook debe usar HTTPS.

Usa la referencia de la API de Stripe para identificar los [objetos de eventos ligeros](https://docs.stripe.com/api/v2/core/events/event-types.md) o los [objetos de los eventos instantáneos](https://docs.stripe.com/api/events/types.md) que tu controlador de webhook necesita procesar.

Configura la función del punto de conexión para que haga lo siguiente:

- Gestiona las solicitudes POST con una carga JSON que incluye información del evento.
- Verifica que Stripe genera la solicitud de webhook usando la carga JSON, el encabezado `Stripe-Signature` y el secreto de firma del webhook `whsec_` del paso anterior. Si falla la verificación, recibirás un error.
- Devuelve rápidamente un código de estado correcto (`2xx`) antes de cualquier lógica compleja que pueda causar un tiempo de espera agotado. Por ejemplo, debes devolver una respuesta `200` antes de actualizar la factura de un cliente como pagada en tu sistema de contabilidad.

> #### No manipules la solicitud de cuerpo sin procesar
> 
> Stripe requiere el cuerpo sin procesar para realizar la solicitud de verificación de la firma. Si estás usando una plataforma, asegúrate de que no manipule el cuerpo sin procesar. Cualquier manipulación del cuerpo sin procesar de la solicitud hace que la verificación falle.
> 
> Descubre cómo [solucionar errores de verificación de firma](https://docs.stripe.com/webhooks/signature.md).

#### Ejemplo de punto de conexión

Este fragmento de código es una función de webhook configurada para buscar eventos recibidos desde una cuenta de Stripe, gestionar los eventos y devolver respuestas `200`. Consulta el controlador de eventos de [instantáneas](https://docs.stripe.com/event-destinations.md#events-overview) cuando uses recursos de la API v1 y haz referencia al controlador de eventos [ligeros](https://docs.stripe.com/event-destinations.md#events-overview) cuando uses recursos de la API v2.

#### Controlador de eventos de instantáneas

Al crear un controlador de eventos de instantáneas, utiliza la definición de objeto de la API en el momento del evento para tu lógica accediendo a los campos `data.object` del evento. También puedes recuperar el recurso de la API de Stripe para acceder a la definición de objeto más reciente y actualizada.

#### Ruby

```ruby
require 'json'
require 'stripe'

client = Stripe::StripeClient.new(ENV.fetch('STRIPE_API_KEY'))

# Replace this endpoint secret with your unique endpoint secret key
# If you're testing with the CLI, run 'stripe listen' to find the secret key
# If you defined your endpoint using the API or the Dashboard, check your webhook settings for your endpoint secret: https://dashboard.stripe.com/webhooks
endpoint_secret = 'whsec_...';

# 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

  # Check that you have configured webhook signing
  if endpoint_secret
    # Retrieve the event by verifying the signature using the raw body and the endpoint secret
    signature = request.env['HTTP_STRIPE_SIGNATURE'];
    begin
      event = Stripe::Webhook.construct_event(
        payload, signature, endpoint_secret
      )
    rescue Stripe::SignatureVerificationError => e
      puts "⚠️  Webhook signature verification failed. #{e.message}"
      status 400
    end
  end

  # Handle the event
  case event.type
  when 'payment_intent.succeeded'
    payment_intent = event.data.object # contains a Stripe::PaymentIntent
    # Then define and call a method to handle the successful payment intent.
    # handle_payment_intent_succeeded(payment_intent)
  when 'payment_method.attached'
    payment_method = event.data.object # contains a Stripe::PaymentMethod
    # Then define and call a method to handle the successful attachment of a PaymentMethod.
    # handle_payment_method_attached(payment_method)
  # ... handle other event types
  else
    puts "Unhandled event type: #{event.type}"
  end

  status 200
end
```

#### Gestor de eventos ligeros (Clover+)

Cuando crees un controlador de eventos ligeros, utiliza el método `fetchRelatedObject()` para recuperar la última versión del objeto asociado con el evento. Los eventos pueden contener [datos adicionales](https://docs.stripe.com/event-destinations.md#fetch-data) que solo puedes recuperar a través del método de instancia `.fetchEvent()` en `EventNotification`. La forma exacta de esos datos depende del `type` de evento.

Los tipos de eventos deben estar disponibles en el momento del lanzamiento para generar clases en esa versión del SDK. Para gestionar eventos para los que el SDK no tiene clases, usa la clase `UnknownEventNotification`.

#### Python

```python
import os
from stripe import StripeClient
from stripe.events import UnknownEventNotification

from flask import Flask, request, jsonify

app = Flask(__name__)
api_key = os.environ.get("STRIPE_API_KEY", "")
webhook_secret = os.environ.get("WEBHOOK_SECRET", "")

client = StripeClient(api_key)

@app.route("/webhook", methods=["POST"])
def webhook():
    webhook_body = request.data
    sig_header = request.headers.get("Stripe-Signature")

    try:
        event_notif = client.parse_event_notification(
            webhook_body, sig_header, webhook_secret
        )

        # type checkers will narrow the type based on the `type` property
        if event_notif.type == "v1.billing.meter.error_report_triggered":
            # in this block, event_notification is typed as
            # a V1BillingMeterErrorReportTriggeredEventNotification

            # there's basic info about the related object in the notification
            print(f"Meter w/ id {event_notif.related_object.id} had a problem")

            # or you can fetch the full object form the API for more details
            meter = event_notif.fetch_related_object()
            print(
                f"Meter {meter.display_name} ({meter.id}) had a problem"
            )

            # And you can always fetch the full event:
            event = event_notif.fetch_event()
            print(f"More info: {event.data.developer_message_summary}")

        elif event_notif.type == "v1.billing.meter.no_meter_found":
            # in this block, event_notification is typed as
            # a V1BillingMeterNoMeterFoundEventNotification

            # that class doesn't define `fetch_related_object` because the event
            # has no related object.
            # so this line would correctly give a type error:
            # meter = event_notif.fetch_related_object()

            # but fetching the event always works:
            event = event_notif.fetch_event()
            print(
                f"Err! No meter found: {event.data.developer_message_summary}"
            )

        # Events that were introduced after this SDK version release are
        # represented as `UnknownEventNotification`s.
        # They're valid, the SDK just doesn't have corresponding classes for them.
        # You must match on the "type" property instead.
        elif isinstance(event_notif, UnknownEventNotification):
            # these lines are optional, but will give you more accurate typing in this block
            from typing import cast

            event_notif = cast(UnknownEventNotification, event_notif)

            # continue matching on the type property
            # from this point on, the `related_object` property _may_ be None
            # (depending on the event type)
            if event_notif.type == "some.new.event":
                # if this event type has a related object, you can fetch it
                obj = event_notif.fetch_related_object()
                # otherwise, `obj` will just be `None`
                print(f"Related object: {obj}")

                # you can still fetch the full event, but it will be untyped
                event = event_notif.fetch_event()
                print(f"New event: {event.data}")  # type: ignore

        return jsonify(success=True), 200
    except Exception as e:
        return jsonify(error=str(e)), 400
```

## Prueba tu controlador

Antes de pasar a modo activo con tu función de punto de conexión de webhook, te recomendamos que pruebes la integración de tu aplicación desencadenando eventos en un entorno de prueba o enviando eventos de prueba con la [CLI de Stripe](https://docs.stripe.com/cli.md).

### Desencadena eventos de prueba

Para enviar eventos de prueba, activa un tipo de evento al que está suscrito el destino de tu evento creando manualmente un objeto en el Dashboard de Stripe. Obtén más información sobre cómo activar eventos con [Stripe para VS Code](https://docs.stripe.com/stripe-vscode.md).

#### Activa un evento de instantánea

Puedes usar el siguiente comando en [Stripe Shell](https://docs.stripe.com/workbench/shell.md) o [Stripe CLI](https://docs.stripe.com/cli.md). Este ejemplo activa un evento `payment_intent.succeeded`:

```bash
stripe trigger payment_intent.succeeded
Running fixture for: payment_intent
Trigger succeeded! Check dashboard for event details.
```

#### Activar un evento ligero

Puedes usar el siguiente comando en la [CLI de Stripe](https://docs.stripe.com/cli.md). Este ejemplo activa un evento `v1.Billing.meter.error_report_triggered`:

```bash
stripe trigger v1.billing.meter.error_report_triggered
Setting up fixture for: list_billing_meters
Running fixture for: list_billing_meters
Setting up fixture for: billing_meter
Running fixture for: billing_meter
Setting up fixture for: list_billing_meters_after_creation
Running fixture for: list_billing_meters_after_creation
Setting up fixture for: billing_meter_event_session
Running fixture for: billing_meter_event_session
Setting up fixture for: create_billing_meter_event_stream
Running fixture for: create_billing_meter_event_stream
Trigger succeeded! Check dashboard for event details.
```

## Optional: Crea un destino de evento para Connect

Cuando [creas un destino de evento](https://docs.stripe.com/webhooks.md#create-webhook-endpoint) como plataforma de Connect, eliges qué ámbito escucha:

#### Dashboard

- **Tu cuenta**: Eventos de recursos de tu cuenta.
- **Cuentas conectadas**: Eventos de recursos que pertenecen a tus cuentas conectadas.

#### API

- [events_from=[“@self”]](https://docs.stripe.com/api/v2/core/event-destinations/create.md#v2_create_event_destinations-events_from): eventos de recursos de tu cuenta.
- [events_from=[“@accounts”]](https://docs.stripe.com/api/v2/core/event-destinations/create.md#v2_create_event_destinations-events_from): eventos de recursos que pertenecen a tus cuentas conectadas.

Registra un destino de evento para **Cuentas conectadas** para recibir eventos de recursos que pertenecen a tus cuentas conectadas. Algunos ejemplos son los [cargos directos](https://docs.stripe.com/connect/direct-charges.md), clientes y métodos de pago de cuentas conectadas, transferencias fallidas y actualizaciones de instantáneas heredadas del ciclo de vida de la cuenta conectada, como la activación, la verificación, los cambios de cuenta externa y las desconexiones de cuenta. Para cuentas v2, este ámbito solo recibe eventos de instantánea para objetos de cuenta que representen a tus cuentas conectadas.

Dependiendo de tu integración de Connect, es posible que también debas registrar un destino de evento para **Tu cuenta**. Estos son algunos de los posibles motivos:

- El procesamiento de eventos para los recursos de tu cuenta de plataforma, incluidos clientes de plataforma, cargos propiedad de la plataforma, [cargos indirectos](https://docs.stripe.com/connect/destination-charges.md) y [cargos y envíos de fondos separados](https://docs.stripe.com/connect/separate-charges-and-transfers.md).
- El procesamiento de eventos de resumen relacionados con los objetos de cuenta v2 que representan cuentas conectadas.

Consulta [webhooks de Connect](https://docs.stripe.com/connect/webhooks.md?accounts-namespace=v2) para obtener más información.

### Haz pruebas de Connect de forma local sin una URL registrada

#### Eventos instantáneos

Usa el siguiente comando para reenviar [eventos de resumen](https://docs.stripe.com/event-destinations.md#events-overview) desde las cuentas conectadas a tu receptor local.

```bash
stripe listen --forward-connect-to localhost:4242/webhook
```

#### Eventos ligeros

Usa el siguiente comando para reenviar [eventos ligeros](https://docs.stripe.com/event-destinations.md#events-overview) desde las cuentas conectadas a tu punto de escucha local.

```bash
stripe listen --forward-thin-connect-to localhost:4242/webhook --thin-events "*"
```

## Optional: Crea un destino de eventos para las organizaciones

Cuando [creas un destino de eventos](https://docs.stripe.com/webhooks.md#create-webhook-endpoint) como una organización, eliges el ámbito que escucha:

#### Dashboard

- **Cuentas de tu organización**: eventos de recursos en las cuentas de tu organización.
- **Cuentas conectadas**: eventos de recursos dentro de las cuentas conectadas de tu organización.

#### API

- [events_from=[“@organization_members”]](https://docs.stripe.com/api/v2/core/event-destinations/create.md#v2_create_event_destinations-events_from): eventos de recursos en las cuentas de tu organización.
- [events_from=[“@organization_members/@accounts”]](https://docs.stripe.com/api/v2/core/event-destinations/create.md#v2_create_event_destinations-events_from): eventos de recursos dentro de las cuentas conectadas de tu organización.

### Comportamientos de tipo de evento no admitidos para destinos de eventos de organización

Stripe envía la mayoría de los tipos de eventos de forma asíncrona, pero espera una respuesta para algunos tipos de eventos. En estos casos, Stripe se comporta de forma diferente dependiendo de si el destino de eventos responde.

Si el destino de tu evento recibe eventos de [Organización](https://docs.stripe.com/get-started/account/orgs.md), los que requieren una respuesta tienen las siguientes limitaciones:

- No puedes suscribirte a `issuing_authorization.request` para destinos de organización. En su lugar, configura un [punto de conexión de webhooks](https://docs.stripe.com/webhooks.md#example-endpoint) en una cuenta de Stripe dentro de la organización para suscribirte a este tipo de evento. Utiliza `issuing_authorization.request` para autorizar las solicitudes de compra en tiempo real.
- Los destinos de la organización que reciben `checkout_sessions.completed` no pueden[manejar el comportamiento de redirección](https://docs.stripe.com/checkout/fulfillment.md#redirect-hosted-checkout) cuando integras el [Proceso de compra](https://docs.stripe.com/payments/checkout.md) directamente en tu sitio web o redirigir a los clientes a una página de pago alojada en Stripe. Para influir en el comportamiento de redireccionamiento del proceso de compra, procesa este tipo de evento con un[punto de conexión webhook](https://docs.stripe.com/webhooks.md#example-endpoint) configurado en una cuenta de Stripe dentro de la organización.
- Los destinos de la organización que responden sin éxito a un evento de `invoice.created` no pueden influir en la [finalización automática de la factura cuando se utiliza el cobro automático](https://docs.stripe.com/billing/subscriptions/webhooks.md#understand). Debes procesar este tipo de evento con un[punto de conexión webhook](https://docs.stripe.com/webhooks.md#example-endpoint) configurado en una cuenta de Stripe dentro de la organización para activar la finalización automática de la factura.

#### Uso del `context`

#### Eventos instantáneos

Este fragmento de código es una función de webhook configurada para comprobar los eventos recibidos, detectar la cuenta de origen, si corresponde, gestionar el evento y devolver una respuesta `200`.

#### Ruby

```ruby
require 'json'

client = Stripe::StripeClient.new('sk_...')

# 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

  # Extract the context
  context = event.context

  # Define your API key variables (ideally loaded securely)
  ACCOUNT_123_API_KEY = "sk_test_123"
  ACCOUNT_456_API_KEY = "sk_test_456"

  account_api_keys = {
    "account_123" => ACCOUNT_123_API_KEY,
    "account_456" => ACCOUNT_456_API_KEY
  }

  api_key = account_api_keys[context]

  if api_key.nil?
    puts "No API key found for context: #{context}"
    status 400
    return
  end

  # Handle the event
  case event.type
  when 'customer.created'
    customer = event.data.object

    begin

      latest_customer = client.v1.customers.retrieve(customer.id, {api_key: api_key})
      handle_customer_created(latest_customer, context)
    rescue => e
      puts "Error retrieving customer: #{e.message}"
      status 500
      return
    end

  when 'payment_method.attached'
    payment_method = event.data.object

    begin
      latest_payment_method = client.v1.payment_methods.retrieve(payment_method.id, {api_key: api_key})
      handle_payment_method_attached(latest_payment_method, context)
    rescue => e
      puts "Error retrieving payment method: #{e.message}"
      status 500
      return
    end

  else
    puts "Unhandled event type: #{event.type}"
  end

  status 200
end
```

#### Gestor de eventos ligeros (Clover+)

Usa la propiedad `context` de `EventNotification` para identificar la cuenta para eventos dentro de tu [organización](https://docs.stripe.com/get-started/account/orgs.md). Debes establecer el [encabezado Stripe Context](https://docs.stripe.com/context.md) manualmente para todas las llamadas a la API excepto `.fetchRelatedObject()` y `.fetchEvent()`, que lo hacen automáticamente.

#### Python

```python
org_api_key = os.environ.get("STRIPE_API_KEY")
webhook_secret = os.environ.get("WEBHOOK_SECRET")
client = StripeClient(org_api_key)

# inside your webhook handler
event_notification = client.parse_event_notification(payload, sig_header, webhook_secret)

# uses `context` automatically
event_notification.fetch_event()

# pass context manually for other API requests
client.v1.invoices.list(stripe_context=event_notification.context)
```

## Depura las integraciones de webhook

Pueden ocurrir varios tipos de problemas al entregar eventos al punto de conexión de tu webhook:

- Es posible que Stripe no pueda entregar un evento a tu punto de conexión de webhook.
- Tu punto de conexión de webhooks podría tener un problema con el SSL.
- La conectividad de tu red es intermitente.
- El punto de conexión de tu webhook no está recibiendo los eventos que esperabas recibir.

### Consulta las entregas de eventos

Para consultar las entregas de eventos, abre [Workbench](https://docs.stripe.com/workbench.md), selecciona el punto de conexión del webhook en **Webhooks** y, después, haz clic en la pestaña **Entregas de eventos**. La pestaña **Entregas de eventos** muestra una lista de eventos y su estado: `Entregado`, `Pendiente` o `Error`. Haz clic en un evento para ver sus metadatos, incluido el código de estado HTTP del intento de entrega y la hora de las próximas entregas pendientes.

También puedes usar la [CLI de Stripe](https://docs.stripe.com/cli.md) para [escuchar eventos](https://docs.stripe.com/webhooks.md#test-webhook) directamente en tu terminal.

### Repara códigos de estado HTTP

Cuando un evento muestra un código de estado `200`, este indica que se ha entregado correctamente al punto de conexión del webhook. También puedes recibir un código de estado que no sea `200`. En la siguiente tabla, encontrarás una lista de los códigos de estado HTTP comunes y las soluciones recomendadas.

| Estado del webhook pendiente | Descripción | Reparar |
| --- | --- | --- |
| (No se ha podido conectar) ERR | No se puede establecer una conexión con el servidor de destino. | Asegúrate de que tu dominio de host sea de acceso público por Internet. |
| (`302`) ERR (u otro estado `3xx`) | El servidor de destino ha intentado redirigir la petición a otra ubicación. Consideramos las respuestas de redireccionamiento a las peticiones de webhook como fallos. | Establece el destino del punto de conexión del webhook a la URL resuelta por el redireccionamiento. |
| (`400`) ERR (u otro estado `4xx`) | El servidor de destino no puede o rechaza procesar la petición. Esto puede ocurrir cuando el servidor detecta un error (`400`), cuando la URL de destino tiene restricciones de acceso (`401`, `403`, `405`) o cuando la URL de destino no existe (`404`). | Asegúrate de que tu punto de conexión sea de acceso público a Internet y acepte un método POST HTTP. |
| (`500`) ERR (u otro estado `5xx`) | El servidor de destino encontró un error mientras se procesaba la solicitud. | Revisa los registros de tu aplicación para comprender por qué está devolviendo un error `500`. |
| (Error de TLS) ERR | No hemos podido establecer una conexión segura con el servidor de destino. Los problemas con el certificado SSL/TLS o un certificado intermedio en la cadena de certificados del servidor de destino suelen causar estos errores. Stripe requiere *TLS* (TLS refers to the process of securely transmitting data between the client—the app or browser that your customer is using—and your server. This was originally performed using the SSL (Secure Sockets Layer) protocol) versión `v1.2` o superior. | Realiza una [prueba del servidor SSL](https://www.ssllabs.com/ssltest/) para descubrir los problemas que puedan causar este error. |
| (Se ha agotado el tiempo de espera) ERR | El servidor de destino tardó demasiado en responder a la petición de webhook. | Asegúrate de diferir la lógica compleja y devolver una respuesta correcta de inmediato en tu código de gestión de webhooks. |

## Comportamientos de entrega de eventos

En esta sección recibirás ayuda para comprender los diferentes comportamientos que puedes esperar en relación con la forma en que Stripe envía los eventos al punto de conexión de tu webhook.

### Reintentos automáticos

En modo activo, Stripe intenta entregar eventos en tu destino durante un máximo de tres días con un retroceso exponencial. Consulta cuándo se realizará el siguiente reintento, si corresponde, en la pestaña **Entregas de eventos** de tu destino de evento. Reintentamos las entregas de eventos creadas en un entorno de prueba tres veces en el transcurso de unas pocas horas. Si tu destino se ha deshabilitado o eliminado cuando hacíamos el reintento, evitamos reintentos de ese evento en el futuro. Sin embargo, si deshabilitas y luego vuelves a habilitar el destino del evento antes de que podamos hacer el reintento, seguirás viendo reintentos en el futuro.

### Reintentos manuales

Hay dos maneras de reintentar eventos manualmente:

- En el Dashboard de Stripe, haz clic en **Reenviar** cuando estés viendo un evento específico. Esto funciona hasta 15 días después de la creación del evento.
- Con el [CLI de Stripe](https://docs.stripe.com/cli/events/resend), ejecuta el comando `stripe events resend <event_id> --webhook-endpoint=<endpoint_id>`. Esto funciona hasta 30 días después de la creación del evento.

El reenvío manual de un evento que tuvo fallos de entrega anteriores a un punto de conexión de webhook no anula el [comportamiento de reintentos automáticos](https://docs.stripe.com/webhooks.md#automatic-retries) de Stripe, incluso si da como resultado un código de estado `2xx`. Aprende a [procesar eventos de webhook no entregados](https://docs.stripe.com/webhooks/process-undelivered-events.md) para detener futuros reintentos.

### Orden de los eventos

Stripe no garantiza la entrega de eventos en el orden en que se han generado. Por ejemplo, la creación de una suscripción puede generar los siguientes eventos:

- `customer.subscription.created`
- `invoice.created`
- `invoice.paid`
- `charge.created` (si hay un cargo)

Asegúrate de que el destino de tus eventos no dependa de recibir eventos en un orden específico. Los eventos de resumen registran `created` en segundos, por lo que hay distintos eventos que pueden compartir una marca de tiempo. No uses `created` para determinar el orden de los eventos o si ya has procesado un evento. En su lugar, haz un seguimiento de los [ID de eventos](https://docs.stripe.com/api/events/object.md#event_object-id) para identificar entregas duplicadas. También puedes usar la API para recuperar cualquier objeto que falte. Por ejemplo, puedes recuperar los objetos factura, cargo y suscripción con la información de `invoice.paid` si recibes este evento primero.

### Control de versiones de API

La versión de la API en la configuración de tu cuenta cuando se produce el evento dicta la versión de la API y, por lo tanto, la estructura de un [Event](https://docs.stripe.com/api/events.md) enviado a tu destino. Por ejemplo, si tu cuenta está configurada con una versión de API anterior, como 2015-02-16, y cambias la versión de API para una solicitud específica con la [versión](https://docs.stripe.com/api.md#versioning), el objeto [Event](https://docs.stripe.com/api/events.md) generado y enviado a tu destino seguirá basándose en la versión de API 2015-02-16. No puedes cambiar los objetos [Event](https://docs.stripe.com/api/events.md) después de su creación. Por ejemplo, si actualizas un cargo, el evento del cargo original permanecerá sin cambios. En consecuencia, las actualizaciones posteriores de la versión de la API de tu cuenta no modificarán retroactivamente los objetos [Event](https://docs.stripe.com/api/events.md) existentes. La recuperación de un [Event](https://docs.stripe.com/api/events.md) anterior llamando a `/v1/events` con una versión de API más reciente tampoco influye en la estructura del evento recibido. Puedes definir destinos de eventos de prueba para tu versión de API predeterminada o para la última versión de API. El [Event](https://docs.stripe.com/api/events.md) enviado al destino se estructura para la versión especificada del destino del evento.

## Mejores prácticas para el uso de webhooks

Revisa estas prácticas recomendadas para asegurarte de que los puntos de conexión de tu webhook estén protegidos y funcionen bien con tu integración.

### Gestiona eventos duplicados

En ocasiones, los puntos de conexión de webhooks pueden recibir el mismo evento más de una vez. Puedes protegerte contra los recibos de eventos duplicados registrando los [ID de eventos](https://docs.stripe.com/api/events/object.md#event_object-id) que has procesado y no procesando los eventos ya registrados.

En algunos casos, se generan y envían dos objetos Event separados. Para identificar estos elementos duplicados, utiliza el ID del objeto en `data.object` junto con el `event.type`.

### Escucha solo los tipos de eventos que requiere tu integración

Configura los puntos de conexión de webhook para recibir solo los tipos de eventos que tu integración necesita. Si escuchas otros eventos (o todos los eventos) se producirá una saturación indebida en tu servidor que no es recomendable.

Puedes [modificar los eventos](https://docs.stripe.com/api/webhook_endpoints/update.md#update_webhook_endpoint-enabled_events) que recibe un punto de conexión de webhooks en el Dashboard o con la API.

### Gestiona eventos de forma asíncrona

Configura tu controlador para procesar eventos entrantes con una cola asíncrona. Es posible que tengas problemas de escalabilidad si decides procesar los eventos de forma sincronizada. Cualquier gran aumento en las entregas de webhook (por ejemplo, a principios de mes, cuando se renuevan todas las suscripciones) podría saturar los servidores de tus puntos de conexión.

Las colas asíncronas te permiten procesar los eventos simultáneos a una velocidad que el sistema puede admitir.

### Exime a la ruta de webhook de la protección CSRF

Si usas Rails, Django u otro marco web, tu sitio podría comprobar automáticamente si cada petición POST contiene un *token CSRF*. Esta es una función de seguridad importante que ayuda a protegerte a ti y a tus usuarios de intentos de [falsificación de peticiones en sitios cruzados](https://www.owasp.org/index.php/Cross-Site_Request_Forgery_\(CSRF\)). No obstante, esta medida de seguridad también puede impedir que tu sitio procese eventos legítimos. De ser así, quizá sea necesario que la ruta de webhooks quede excluida de la protección CSRF.

#### Rails

```ruby
class StripeController < ApplicationController
  # If your controller accepts requests other than Stripe webhooks,
  # you'll probably want to use `protect_from_forgery` to add CSRF
  # protection for your application. But don't forget to exempt
  # your webhook route!
  protect_from_forgery except: :webhook

  def webhook
    # Process webhook data in `params`
  end
end
```

### Recibir eventos con un servidor HTTPS

Si usas una URL HTTPS para el punto de conexión del webhook (obligatorio en el modo activo), Stripe valida que la conexión con el servidor sea segura antes de enviar los datos de tu webhook. Para que esto funcione, el servidor debe estar correctamente configurado para ser compatible con HTTPS con un certificado de servidor válido. Los webhooks de Stripe solo son compatibles con las versiones v1.2 y v1.3 de *TLS* (TLS refers to the process of securely transmitting data between the client—the app or browser that your customer is using—and your server. This was originally performed using the SSL (Secure Sockets Layer) protocol).

### Cambia periódicamente los secretos de firma de los puntos de conexión

El secreto que se usa para verificar que los eventos proceden de Stripe se puede modificar en la pestaña [Webhooks](https://dashboard.stripe.com/webhooks) de Workbench. Para protegerlos, te recomendamos que cambies los secretos periódicamente o cuando sospeches que se ha vulnerado uno de ellos.

Cómo cambiar un secreto:

1. Haz clic en cada punto de conexión de la pestaña [Webhooks](https://dashboard.stripe.com/webhooks) de Workbench para el que quieras cambiar el secreto.
2. Dirígete al menú de desbordamiento (⋯) y haz clic en **Cambiar secreto**. Puedes optar por la caducidad inmediatamente del secreto actual o retrasarla por hasta 24 horas para que tengas tiempo de actualizar el código de verificación en tu servidor. Durante este período, habrá varios secretos activos para el punto de conexión. Stripe generará una firma por secreto hasta su caducidad.

### Verifica que los eventos se envíen desde Stripe

Sin verificación, un atacante podría enviar eventos webhook falsos a tu punto de conexión para ejecutar acciones como completar pedidos, conceder acceso a cuentas o modificar registros. Verifica siempre que los eventos webhook proceden de Stripe antes de realizar ninguna acción.

Utiliza estas dos protecciones:

- **Lista de direcciones IP permitidas**: Stripe envía eventos webhook desde una lista determinada de [direcciones IP](https://docs.stripe.com/ips.md). Configura tu servidor o firewall para que solo acepte solicitudes webhook de estas direcciones.
- **Verificación de la firma**: Stripe firma todos los eventos de «webhook» incluyendo una firma en el encabezado `Stripe-Signature`. Verifica esta firma usando nuestras [bibliotecas oficiales](https://docs.stripe.com/webhooks.md#verify-signature) o sigue los [pasos de verificación manual](https://docs.stripe.com/webhooks.md?verify=verify-manually#verify-signature) para confirmar que el evento no ha sido enviado ni modificado por un tercero.

En la siguiente sección, se describe cómo verificar las firmas de webhook:

1. Recupera el secreto de tu punto de conexión.
2. Verifica la firma.

#### Cómo recuperar el secreto de tu punto de conexión

Usa Workbench y ve a la pestaña [Webhooks](https://dashboard.stripe.com/webhooks) para ver todos tus puntos de conexión. Selecciona un punto de conexión para el que quieras obtener el secreto y, a continuación, haz clic en **Haz clic para revelar**.

Stripe genera una clave secreta única para cada punto de conexión. Si utilizas el mismo punto de conexión para ambas [claves de API en modo de prueba y en modo activo](https://docs.stripe.com/keys.md#test-live-modes), la clave secreta será diferente para cada uno. Además, si utilizas varios puntos de conexión, debes obtener una clave secreta para cada uno de los que quieras verificar las firmas. Después de esta configuración, Stripe comenzará a firmar cada webhook que envía al punto de conexión.

#### Verificar la firma

#### Haz la verificación con las bibliotecas oficiales (recomendada)

### Haz la verificación manual de las firmas con las bibliotecas oficiales

Te recomendamos que uses nuestra biblioteca oficial para verificar las firmas. Para hacer la verificación, proporciona una carga de evento, el encabezado `Stripe-Signature` y el secreto del punto de conexión. Si falla la verificación, verás un error.

Si recibes un error de verificación de firma, lee nuestra guía para [solucionarlo](https://docs.stripe.com/webhooks/signature.md).

> Stripe requiere el cuerpo sin procesar para realizar la solicitud de verificación de la firma. Si estás usando una plataforma, asegúrate de que no manipule el cuerpo sin procesar. Cualquier manipulación del cuerpo sin procesar de la solicitud hace que la verificación falle.

#### 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('<<YOUR_SECRET_KEY>>')

require 'stripe'
require 'sinatra'

# 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_...'

# Using the Sinatra framework
set :port, 4242

post '/my/webhook/url' do
  payload = request.body.read
  sig_header = request.env['HTTP_STRIPE_SIGNATURE']
  event = nil

  begin
    event = Stripe::Webhook.construct_event(
      payload, sig_header, endpoint_secret
    )
  rescue JSON::ParserError => e
    # Invalid payload
    puts "Error parsing payload: #{e.message}"
    status 400
    return
  rescue Stripe::SignatureVerificationError => e
    # Invalid signature
    puts "Error verifying webhook signature: #{e.message}"
    status 400
    return
  end

  # Handle the event
  case event.type
  when 'payment_intent.succeeded'
    payment_intent = event.data.object # contains a Stripe::PaymentIntent
    puts 'PaymentIntent was successful!'
  when 'payment_method.attached'
    payment_method = event.data.object # contains a Stripe::PaymentMethod
    puts 'PaymentMethod was attached to a Customer!'
  # ... handle other event types
  else
    puts "Unhandled event type: #{event.type}"
  end

  status 200
end
```

#### Haz la verificación manual

### Haz la verificación manual de las firmas de webhook

Si bien te recomendamos que uses nuestra biblioteca oficial para verificar firmas de eventos de webhook, puedes crear una solución personalizada siguiendo esta sección.

El encabezado '`Stripe-Signature` incluido en cada evento firmado contiene una marca temporal y una o más firmas que debes verificar. La marca temporal tiene un prefijo `t=` y cada firma tiene un prefijo *scheme*. Los esquemas comienzan con `v`, seguido de un número entero. Actualmente, el único esquema válido de firma en modo activo es `v1`. Para facilitar las pruebas, Stripe envía una firma adicional con un esquema `v0` falso, para los eventos de prueba.

```
Stripe-Signature:
t=1492774577,
v1=5257a869e7ecebeda32affa62cdca3fa51cad7e77a0e56ff536d0ce8e108d8bd,
v0=6ffbb59b2300aae63f272406069a9788598b792a944a07aba816edb039989a39
```

> Proporcionamos nuevas líneas para que la claridad sea mayor, pero el encabezado `Stripe-Signature` real está en una única línea.

Stripe genera firmas utilizando el código de autenticación de mensajes basado en hash ([HMAC](https://en.wikipedia.org/wiki/Hash-based_message_authentication_code)) con [SHA-256](https://en.wikipedia.org/wiki/SHA-2). Para evitar los [ataques de degradación](https://en.wikipedia.org/wiki/Downgrade_attack), ignora todos los esquemas que no sean `v1`.

Es posible que tengas varias firmas con el mismo par esquema-secreto cuando [cambias el secreto de un punto de conexión](https://docs.stripe.com/webhooks.md#roll-endpoint-secrets) y eliges mantener el secreto anterior activo durante un máximo de 24 horas. Durante este período, tu punto de conexión tiene varios secretos activos y Stripe genera una firma para cada secreto.

Para crear una solución manual de verificación de firmas, debes completar los siguientes pasos:

#### Paso 1: extrae la marca temporal y las firmas del encabezado

Divide el encabezado con el carácter `,` como separador para obtener una lista de elementos. Luego, divide cada elemento con el carácter `=` como separador para obtener un par de prefijo y valor.

El valor del prefijo `t` corresponde a la marca temporal, y `v1` corresponde a la firma (o firmas). Puedes descartar el resto de elementos.

#### Paso 2: preparar la cadena `signed_payload`

La cadena `signed_payload` se crea al concatenar los siguientes elementos:

- La marca temporal (como cadena)
- El carácter `.`
- La carga real del JSON (esto es, el cuerpo de la petición)

#### Paso 3: determinar la firma prevista

Calcula un HMAC con la función hash SHA256. Utiliza el secreto de la firma del punto de conexión como clave y la cadena `signed_payload` como mensaje.

#### Paso 4: comparar las firmas

Compara la firma (o firmas) del encabezado con la firma prevista. Para obtener una coincidencia equivalente, calcula la diferencia entre la marca temporal actual y la recibida, y luego decide si la diferencia está dentro de tu tolerancia.

Para protegerte de los ataques de tiempo, utiliza una comparación de cadenas en tiempo constante para comparar la firma prevista con cada una de las firmas recibidas.

### Prevención de ataques de reproducción

Un [ataque de repetición](https://en.wikipedia.org/wiki/Replay_attack) ocurre cuando un atacante intercepta una carga válida y su firma, y luego las retransmite. Para mitigar tales ataques, Stripe incluye una marca temporal en el encabezado `Stripe-Signature`. Debido a que esta marca de tiempo es parte de la carga firmada, también se verifica mediante la firma, por lo que un atacante no puede cambiar la marca temporal sin invalidar la firma. Si la firma es válida, pero la marca temporal es demasiado antigua, tu aplicación puede rechazar la carga.

Nuestras bibliotecas tienen una tolerancia predeterminada de cinco minutos entre la marca temporal y la hora actual. Puedes cambiar esta tolerancia proporcionando un parámetro adicional al verificar las firmas. Utiliza el protocolo de tiempo de redes ([NTP](https://en.wikipedia.org/wiki/Network_Time_Protocol)) para asegurarte de que el reloj de simulación de tu servidor sea preciso y esté sincronizado con la hora de los servidores de Stripe.

> No uses un valor de tolerancia de `0`. Al usar un valor de tolerancia de `0` se desactiva por completo la comprobación de recencia.

Stripe genera la marca temporal y la firma cada vez que enviamos un evento a tu punto de conexión. Si Stripe reintenta un evento (por ejemplo, tu punto de conexión ha respondido previamente con un código de estado que no es`2xx`), generaremos una nueva firma y una marca temporal para el nuevo intento de entrega.

### Devolver rápidamente una respuesta 2xx

Tu [punto de conexión](https://docs.stripe.com/webhooks.md#example-endpoint) debe devolver rápidamente un código de estado correcto (`2xx`) antes de cualquier lógica compleja que pueda causar un tiempo de espera. Por ejemplo, debes devolver una respuesta `200` antes de actualizar una factura de cliente como pagada en tu sistema de contabilidad.

## See also

- [Envía eventos a tu cuenta de Amazon EventBridge](https://docs.stripe.com/event-destinations/eventbridge.md)
- [Enviar eventos a Azure Event Grid](https://docs.stripe.com/event-destinations/eventgrid.md)
- [Lista de tipos de eventos ligeros](https://docs.stripe.com/api/v2/core/events/event-types.md)
- [Lista de tipos de eventos de instantánesa](https://docs.stripe.com/api/events/.md)
- [Generador interactivo de puntos de conexión de webhooks](https://docs.stripe.com/webhooks/quickstart.md)
