# Webhooks do Connect

Saiba como usar webhooks com o Connect para receber notificações de atividades da Stripe.

A Stripe usa *webhooks* (A webhook is a real-time push notification sent to your application as a JSON payload through HTTPS requests) para notificar os aplicativos quando um evento ocorre em sua conta. Todas as integrações do *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) devem estabelecer um [endpoint de webhook](https://dashboard.stripe.com/account/webhooks) para ouvir eventos do Connect.

## Webhooks conectados

Os webhooks para usuários do Connect monitoram eventos em diferentes escopos, dependendo da origem do evento:

- **Sua conta**: a maioria dos eventos acionados por recursos existentes na sua conta. Isso inclui a maioria das solicitações feitas com suas chaves da API e sem [autenticar como outra conta Stripe](https://docs.stripe.com/connect/authentication.md), como:
  - Eventos `v2.core.account.*` para `Accounts` v2 na sua conta
  - Eventos para `Clientes` na sua conta
  - Eventos para direct charges na sua conta
  - Eventos para *cobranças indiretas* (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) na sua conta relacionados às suas contas conectadas
- **Contas conectadas**: eventos acionados por recursos existentes nas contas conectadas e alguns recursos existentes na sua conta, como:
  - Eventos `v2.core.account.*` para `Accounts` v2 que representam clientes e destinatários das suas contas conectadas
  - Eventos `account.updated` tanto para `Accounts` v1 quanto v2 que representam clientes e destinatários das suas contas conectadas
  - *Direct charges* (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 das suas contas conectadas

> #### Escopos de eventos para Accounts v2 que representam contas conectadas
> 
> Os objetos da `Account` v2 acionam tanto `Eventos` v1 quanto v2, que podem ter escopos diferentes. Para eventos acionados por contas conectadas, os `Events` v2 usam o escopo **Sua conta**, enquanto os `Events` v1 usam o escopo **Contas conectadas**, mesmo quando acionados pela mesma `Account` v2.

Ao criar um Webhook no [Workbench](https://dashboard.stripe.com/workbench/webhooks), atribua o escopo definindo **Eventos de** como **Sua conta** ou **Contas conectadas**. Ao criar um Webhook usando a API, atribua o escopo definindo o parâmetro [connect](https://docs.stripe.com/api/webhook_endpoints/create.md#create_webhook_endpoint-connect) como falso (para **Sua conta**) ou verdadeiro (para **Contas conectadas**).

Para webhooks do Connect, os URLs de webhook de desenvolvimento recebem apenas webhooks de teste, mas os URLs de webhook de produção recebem webhooks de produção e de teste. Isso ocorre porque você pode realizar transações de produção e de teste em um aplicativo de produção. Recomendamos que você verifique o valor de `livemode` ao receber um evento de webhook para determinar se os usuários precisam realizar uma ação.

Você deve definir endpoints Webhook separados para suas contas de [área restrita](https://docs.stripe.com/sandboxes.md) receberem eventos dessas contas.

Cada evento de conta conectada contém uma propriedade `account` de nível superior que identifica a conta conectada. Como a conta conectada é proprietária [do objeto que acionou o evento](https://docs.stripe.com/api/events/object.md#event_object-data-object), você precisa fazer solicitações de API para esse objeto [como a conta 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": {...}
}
```

A tabela a seguir descreve alguns dos eventos mais comuns e importantes relacionados a contas conectadas:

| Evento | tipo data.object | Descrição |
| --- | --- | --- |
| `account.application.deauthorized` | `application` | Ocorre quando uma conta conectada se desconecta da sua plataforma. Você pode usá-lo para acionar a limpeza em seu servidor. Disponível para contas conectadas com acesso ao Stripe Dashboard, que inclui [contas Standard](https://docs.stripe.com/connect/standard-accounts.md). |
| `account.external_account.updated` | Uma conta externa, como `card` ou `bank_account` | Ocorre quando [uma conta bancária ou cartão de débito vinculado a uma conta conectada é atualizado](https://docs.stripe.com/connect/payouts-bank-accounts.md), o que pode afetar os repasses. Disponível para contas conectadas controladas pela sua plataforma, o que inclui contas Custom e Express, e contas Standard com [controles de plataforma](https://docs.stripe.com/connect/platform-controls-for-stripe-dashboard-accounts.md) habilitados. |
| `account.updated` | `account` | Permite monitorar alterações nos requisitos e mudanças de status das contas conectadas. Disponível para todas as contas conectadas. |
| `balance.available` | `balance` | Ocorre quando o seu saldo da Stripe é atualizado. Por exemplo, quando [fundos que você adicionou da sua conta bancária](https://docs.stripe.com/connect/top-ups.md) ficam disponíveis para repasse à sua conta conectada. |
| `payment_intent.succeeded` | `payment_intent` | Ocorre quando uma intenção de pagamento resulta em uma cobrança bem-sucedida. Disponível para todos os pagamentos, incluindo cobranças de [destino](https://docs.stripe.com/connect/destination-charges.md) e [diretas](https://docs.stripe.com/connect/direct-charges.md). |
| `payout.failed` | `payout` | Ocorre quando [um repasse falha](https://docs.stripe.com/connect/payouts-connected-accounts.md#webhooks). Quando um repasse falha, a conta externa envolvida é desativada e nenhum repasse automático ou manual é processado até que ela seja atualizada. |
| `person.updated` | `person` | Ocorre quando uma `Person` associada à `Account` é atualizada. Se você [usa a API Persons para gerenciar requisitos](https://docs.stripe.com/connect/handling-api-verification.md#verification-process), escute esse evento para monitorar alterações de requisitos e status de indivíduos. Disponível para contas conectadas controladas pela sua plataforma, o que inclui contas Custom e Express, e contas Standard com [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('<<YOUR_SECRET_KEY>>')

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

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

# 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, cobrança direta

#### Rubi

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

# 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, cobrança não direta

#### Rubi

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

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

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

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

# 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
```

## Testar webhook localmente

Para testar Webhooks de eventos localmente com o Stripe CLI:

1. Caso ainda não tenha feito isto, [instale a Stripe CLI](https://docs.stripe.com/cli/install) na sua máquina.

2. Acesse sua conta Stripe e configure a CLI executando `stripe login` na linha de comando.

3. Permita que seu host local receba um evento simulado executando [stripe listen](https://docs.stripe.com/cli/listen), dependendo do escopo do evento:

   - **Contas conectadas**: `stripe listen --forward-connect-to localhost:{{PORT}}/{{CONNECT_WEBHOOK_ENDPOINT}}`
   - **Sua conta**: `stripe listen --forward-to localhost:{{PORT}}/{{WEBHOOK_ENDPOINT}}`

4. Em outra janela do terminal, acione um evento simulado executando [stripe trigger](https://docs.stripe.com/cli/trigger), dependendo do escopo do evento:

   - **Contas conectadas**: `stripe trigger --stripe-account {{CONNECTED_ACCOUNT_ID}} {{EVENT_NAME}}`
   - **Sua conta**: `stripe trigger {{EVENT_NAME}}`

## See also

- [Documentação do webhook](https://docs.stripe.com/webhooks.md)
- [Referência do objeto Event](https://docs.stripe.com/api.md#events)
