agendapro/asaas_skill.md

7.5 KiB

Integração Asaas Payment Gateway - AgendaPRO

Este documento serve como guia técnico ("Skill") para a integração do gateway de pagamento Asaas na plataforma SaaS multi-tenant AgendaPRO. Ele detalha os fluxos de trabalho, estruturas de API, segurança do Webhook e regras de conciliação financeira em banco de dados PostgreSQL.


1. Visão Geral da Arquitetura

A integração é baseada no modelo SQL-First, onde o banco de dados PostgreSQL é a única fonte da verdade. O mapeamento é feito associando os IDs internos do sistema (UUID) ao campo externalReference fornecido pela API do Asaas.

sequenceDiagram
    participant Cliente/Tenant as App/Painel (AgendaPRO)
    participant Lib as Serviço Asaas (src/lib/asaas.ts)
    participant Asaas as Asaas API (Sandbox/Prod)
    participant DB as PostgreSQL

    Cliente/Tenant->>Lib: Solicita Cobrança/Assinatura
    Lib->>DB: Busca Configuração do Tenant (API Key)
    DB-->>Lib: Retorna Configuração do Tenant
    Lib->>Asaas: POST /v3/payments (ou /subscriptions) com externalReference
    Asaas-->>Lib: Retorna Dados da Transação (ID do Asaas)
    Lib-->>Cliente/Tenant: Retorna Link/QR Code Pix para o Cliente

2. Ambientes e Autenticação

O Asaas possui dois ambientes distintos. As chaves de API (API Keys) geradas no Sandbox não funcionam em Produção e vice-versa.

Ambiente URL Base da API v3 Variável de Ambiente
Sandbox (Homologação) https://api-sandbox.asaas.com/v3 ASAAS_API_KEY (Prefixo de teste)
Produção https://api.asaas.com/v3 ASAAS_API_KEY

Cabeçalhos HTTP Obrigatórios

Todas as chamadas à API devem conter:

  • access_token: Sua chave de API do Asaas (específica para o tenant ou plataforma).
  • Content-Type: application/json.
  • User-Agent: Nome da aplicação (ex: AgendaPRO-Integration).

3. Fluxo de Clientes (Customers)

Antes de emitir qualquer cobrança ou assinatura, o cliente (consumidor final) deve ser cadastrado no Asaas. O ID do cliente retornado (cus_...) deve ser salvo no banco local (ex: no cadastro de inquilino/tenant ou no cadastro de cliente do estabelecimento).

  • Endpoint: POST /v3/customers
  • Payload Exemplo:
    {
      "name": "João Mendes",
      "cpfCnpj": "00000000000",
      "email": "joao@email.com",
      "phone": "11999991234",
      "mobilePhone": "11999991234",
      "externalReference": "local-client-uuid",
      "notificationDisabled": false
    }
    
  • Response de Sucesso: Retorna o objeto do cliente contendo o "id": "cus_000005219613".

4. Fluxo de Cobranças Avulsas (Payments - Pix/Boleto/Cartão)

Usado para pagamentos individuais, como a cobrança por um agendamento específico.

  • Endpoint: POST /v3/payments
  • Payload Exemplo (Pix/Boleto):
    {
      "customer": "cus_000005219613",
      "billingType": "PIX",
      "value": 55.00,
      "dueDate": "2026-06-10",
      "description": "Corte Masculino - Barbearia Premium",
      "externalReference": "local-payment-uuid"
    }
    
  • Response de Sucesso: Retorna o ID da transação (ex: "id": "pay_080225913252").

Obtenção do QR Code Dinâmico Pix

Se a cobrança for do tipo PIX, você pode buscar a imagem em Base64 e a linha digitável ("copia e cola"):

  • Endpoint: GET /v3/payments/{id}/pixQrCode (Sem corpo na requisição)
  • Response Exemplo:
    {
      "encodedImage": "iVBORw0KGgoAAAANSUhEUgAA...",
      "payload": "00020101021126660014br.gov.bcb.pix...",
      "expirationDate": "2026-06-10T23:59:59Z"
    }
    

5. Fluxo de Assinaturas Recorrentes (Subscriptions)

Usado pelo SaaS para cobrar a mensalidade do próprio inquilino (Tenant) ou pelos inquilinos para oferecer planos recorrentes.

  • Endpoint: POST /v3/subscriptions
  • Payload Exemplo (Cartão de Crédito):
    {
      "customer": "cus_0T1mdomVMi39",
      "billingType": "CREDIT_CARD",
      "nextDueDate": "2026-07-03",
      "value": 99.90,
      "cycle": "MONTHLY",
      "description": "Assinatura AgendaPRO - Plano Professional",
      "externalReference": "local-subscription-uuid",
      "creditCard": {
        "holderName": "TITULAR DO CARTAO",
        "number": "0000000000000000",
        "expiryMonth": "12",
        "expiryYear": "2030",
        "ccv": "123"
      },
      "creditCardHolderInfo": {
        "name": "TITULAR DO CARTAO",
        "email": "titular@email.com",
        "cpfCnpj": "00000000000",
        "postalCode": "01310000",
        "addressNumber": "123",
        "phone": "11999991234"
      }
    }
    

6. Webhook e Segurança

O webhook do Asaas garante a conciliação automática do status de pagamentos de forma assíncrona.

Validação de Autenticidade (Signature)

Diferente de gateways que usam assinaturas HMAC, o Asaas utiliza um Token de Acesso Simples configurado na interface do webhook.

  1. Configure um Token Secreto no Painel do Asaas (ou salve em settings no banco local do tenant).
  2. O Asaas enviará este token no cabeçalho asaas-access-token em cada requisição de Webhook.
  3. A aplicação deve validar: req.headers.get('asaas-access-token') === webhookSecret.

Estrutura de Payload do Webhook

{
  "id": "evt_05b708f961d739ea7eba7e4db318f621",
  "event": "PAYMENT_RECEIVED",
  "dateCreated": "2026-06-03 20:20:00",
  "payment": {
    "id": "pay_080225913252",
    "customer": "cus_000005219613",
    "subscription": "sub_VXJBYgP2u0eO",
    "value": 100.00,
    "netValue": 95.00,
    "externalReference": "local-payment-uuid",
    "billingType": "PIX",
    "confirmedDate": "2026-06-03"
  }
}

Eventos Críticos a Processar

  • PAYMENT_RECEIVED / PAYMENT_CONFIRMED: Pagamento efetuado com sucesso.
  • PAYMENT_REFUNDED: Pagamento estornado pelo painel ou pelo banco.
  • PAYMENT_OVERDUE: Vencimento expirado sem quitação.
  • PAYMENT_DELETED: Cobrança removida manualmente.
  • SUBSCRIPTION_DELETED / SUBSCRIPTION_CANCELLED: Cancelamento de recorrência.

7. Estrutura do Código Implementado

A. Camada de Serviço (src/lib/asaas.ts)

Fornece funções isoladas e parametrizadas que realizam as chamadas seguras para a API, respeitando a separação de chaves por inquilino (tenant_id).

B. Handler de Webhook (src/app/api/webhooks/asaas/route.ts)

Endpoint público que recebe requisições do Asaas. Executa os seguintes passos:

  1. Valida o token asaas-access-token contra o token do Tenant (se enviado com ?tenant_id=...) ou contra o token mestre do sistema.
  2. Cria e utiliza a tabela asaas_webhook_events para garantir idempotência (ignora eventos duplicados).
  3. Atualiza o status financeiro local em uma transação segura (BEGIN/COMMIT).

8. Guia de Teste no Sandbox

  1. Configuração de Chaves:
    • Vá em Asaas Sandbox > Minha Conta > Integrações.
    • Gere uma chave de API e insira o webhook apontando para a sua URL pública exposta pelo Ngrok/Cloudflare Tunnel (ex: https://seu-dominio.trycloudflare.com/api/webhooks/asaas?tenant_id=UUID-DO-TENANT).
  2. Simulação de Pagamentos:
    • Crie uma cobrança do tipo Pix/Boleto pela API.
    • Acesse o painel de Sandbox do Asaas.
    • Procure a cobrança emitida e clique em Confirmar Recebimento (Botão de teste que simula o pagamento do cliente).
  3. Validação de Banco de Dados:
    • Execute: SELECT status, paid_at FROM payments WHERE id = 'seu-uuid';
    • Verifique se o status mudou para completed e a coluna paid_at foi preenchida corretamente.