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
IntegrationWebhookcom os dados informados. - Quando um evento de pagamento é disparado (pagamento modificado, webhook do Asaas, etc.), uma engine varre os
IntegrationWebhookdisponí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
IntegrationWebhookeIntegrationCheckout - [x] Renomear
WebhookparaWebhookLog - [x] Migrar
WebhookparaWebhookLoge 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/