# 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. ```mermaid 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:** ```json { "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):** ```json { "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:** ```json { "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):** ```json { "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 ```json { "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](https://sandbox.asaas.com/) > 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.