API de webhooks de integração

TLDR: permitir que organizações registrem URLs para receber eventos de cobrança, escolhendo quais eventos e quais checkouts disparam o envio.

Contexto

Organizações têm sistemas próprios — área de membros ou qualquer outro — que precisam reagir a eventos de pagamento. Não há hoje um mecanismo genérico: cada integração nova exige código dedicado.

Objetivos

  • Construir a API na V2.
  • A API cria um registro de IntegrationWebhook com os dados informados.
  • Quando um evento de pagamento é disparado (pagamento modificado, webhook do Asaas, etc.), uma engine varre os IntegrationWebhook disponíveis — para todos os checkouts, ou para os checkouts específicos cadastrados no webhook.
  • Uma chave de status ativa ou desativa o webhook.
  • Usar uma fila dedicada apenas para os webhooks.

Fora de escopo

Webhooks são enviados via POST. Outros métodos não são suportados.

Mudanças

Modelo IntegrationWebhook

belongs_to :organization.

Campo Nome Descrição
organization_id ID da organização Organização associada ao webhook
name Nome Nome do webhook
kind Tipo Tipo do webhook (por enquanto apenas um)
url URL URL para a qual o webhook será enviado
status Status Enum inactive/active
user_accepted_legal_terms Termos legais aceitos Se o usuário aceitou os termos legais do webhook (boolean)
events Eventos Eventos de cobrança que disparam o webhook, ex.: PAYMENT_PAID, PAYMENT_OVERDUE
created_at Data de criação —
updated_at Data de atualização —

Modelo IntegrationCheckout

Tabela de junção que escopa um webhook a checkouts específicos.

Autenticação

A API já tem autenticação baseada na organização para a Api::V2. Cada requisição deve incluir um token válido, verificado para garantir que a organização tem permissão sobre os recursos solicitados.

Controller

CRUD completo em Api::V2::IntegrationWebhooksController, herdando de Api::BaseAuthenticatedController e escopando tudo por current_organization.integration_webhooks:

```ruby class Api::V2::IntegrationWebhooksController < Api::BaseAuthenticatedController def index render json: current_organization.integration_webhooks end

def show render json: current_organization.integration_webhooks.find(params[:id]) end

def create webhook = current_organization.integration_webhooks.new(webhook_params) if webhook.save render json: webhook, status: :created else render json: { errors: webhook.errors.full_messages }, status: :unprocessable_entity end end

# update, destroy análogos

private

def webhook_params params.require(:checkout_webhook).permit(:url, :events, :status) end end ```

Validações

```ruby class IntegrationWebhook < ApplicationRecord belongs_to :organization

validates :url, presence: true, format: { with: URI::regexp(%w[http https]) } validates :events, presence: true validates :status, inclusion: { in: [true, false] } end ```

ActiveAdmin

  • Interface para gerenciar os webhooks — visualizar, criar, editar e excluir.
  • Filtros e busca para localizar webhooks específicos.
  • Validação dos campos obrigatórios ao criar ou editar.
  • Exibição clara dos eventos associados ao webhook.
  • Garantir que mudanças feitas pelo admin se reflitam na API.

Roadmap

  • [x] Configurar a autenticação baseada na organização para a Api::V2
  • [x] Criar os modelos IntegrationWebhook e IntegrationCheckout
  • [x] Renomear Webhook para WebhookLog
  • [x] Migrar Webhook para WebhookLog e ajustar as chamadas de modelo
  • [x] Criar o controller de gerenciamento dos webhooks
  • [x] Adicionar validações nos modelos
  • [x] Implementar a interface do ActiveAdmin
  • [x] Atualizar o Postman
  • [x] Criar os jobs
  • [x] Criar a engine que escuta os eventos e dispara os webhooks (OutcomeWebhooks::IntegrationWebhooks::Dispatcher::SenderFlow)
  • [x] Criar a engine que salva os webhooks enviados para o usuário consultar (OutcomeWebhookLog)
  • [x] Testes em staging
  • [x] Testar com TRG, com pagamento e transferências
  • [x] Deploy em produção

Como verificar

— (não registrado na spec original)

Sugestão a partir do estado atual do código: registrar um IntegrationWebhook ativo para PAYMENT_CONFIRMED, confirmar um pagamento e conferir o OutcomeWebhookLog do envio.

Documentação

  • Contrato público resultante: ../reference/payments/payment_webhooks.md
  • Implementação: app/models/integration_webhook.rb, app/use_cases/outcome_webhooks/integration_webhooks/dispatcher/sender_flow.rb, app/jobs/outcome_webhooks/