Created
June 29, 2026 13:03
-
-
Save mbmaciel/715f45d40eebe9d40ca96ad20d50ac30 to your computer and use it in GitHub Desktop.
Integração Asaas BaaS
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| ## Integração Asaas BaaS — Status: ✅ Completo | |
| A integração com o Asaas BaaS (Banking as a Service) está **totalmente implementada** conforme o documento `docs/INTEGRACAO-FINANCEIRA-BAAS.md`. Todos os checklists do documento foram concluídos. | |
| ### Arquitetura | |
| ``` | |
| PlenoCRM (Master API Key) | |
| └── POST /v3/accounts (cria subconta por sindicato) | |
| └── Subconta Sindicato (apiKey + walletId próprios) | |
| ├── POST /v3/payments (PIX / Boleto) | |
| ├── POST /v3/customers (sync filiado) | |
| ├── POST /v3/transfers (transferência automática) | |
| └── Webhook → PlenoCRM (PAYMENT_RECEIVED, PAYMENT_CONFIRMED, etc.) | |
| ``` | |
| ### Arquivos principais | |
| | Arquivo | Responsabilidade | | |
| |---------|-----------------| | |
| | `backend/src/modules/finance/payment.adapters.ts` | Adapter Asaas: `createCharge`, `getPixQrCode`, `getBoletoInfo`, `syncCustomer`, `createSubaccount`, `createTransfer`, `getBalance`, `validateWebhookSignature` | | |
| | `backend/src/shared/crypto.ts` | AES-256-GCM: `encrypt()`, `decrypt()`, `isEncrypted()`, `safeDecryptApiKey()` | | |
| | `backend/src/modules/financeiro/financeiro.routes.ts` | Webhook handler (`POST /financeiro/asaas/webhook`), split de comissão + transferência automática no evento `PAYMENT_CONFIRMED` | | |
| | `backend/src/modules/tenants/tenants.routes.ts` | Criação automática de subconta Asaas ao criar tenant (`criar_subconta_asaas: true`) | | |
| | `backend/src/modules/tenant-admin/tenant-admin.routes.ts` | Máscara da API key (`abcd...wxyz`), criptografia ao salvar nova chave | | |
| | `backend/src/modules/commissions/commissions.routes.ts` | CRUD de regras de comissão, listagem de splits, resumo financeiro, reprocessamento de transferências | | |
| | `database/migrations/043_asaas_financial_tables.sql` | Tabelas: `financial_accounts`, `payment_splits`, `transfers`, `webhook_logs`, `commission_rules` | | |
| | `docs/INTEGRACAO-FINANCEIRA-BAAS.md` | Documento de arquitetura completo com checklist atualizado | | |
| ### Criptografia AES-256-GCM | |
| Toda `apiKey` de subconta é armazenada criptografada no banco (`tenant_modules.settings.asaas_api_key`). | |
| ```typescript | |
| import { encrypt, decrypt, safeDecryptApiKey, isEncrypted } from '../../shared/crypto.js'; | |
| // Ao SALVAR (nunca armazenar em texto puro): | |
| settings.asaas_api_key = encrypt(novaApiKey); | |
| // Ao LER (descriptografa automaticamente, compatível com chaves legadas): | |
| const apiKey = safeDecryptApiKey(settings.asaas_api_key); | |
| ``` | |
| **Regras de segurança:** | |
| - API key **nunca** é exibida na interface — apenas mascarada como `abcd...wxyz` | |
| - API key **nunca** aparece em logs (`payment_logs`, `audit_log`) | |
| - `getPaymentAdapterForTenant()` descriptografa automaticamente antes de usar | |
| - `maskAsaasApiKey()` descriptografa apenas para exibir os 4 primeiros e 4 últimos caracteres | |
| ### Módulo de Comissão (`/commissions`) | |
| Endpoints disponíveis apenas para perfil `MASTER`: | |
| | Método | Rota | Descrição | | |
| |--------|------|-----------| | |
| | `GET` | `/commissions` | Listar todas as regras de comissão | | |
| | `GET` | `/commissions/global` | Regra global (tenant_id = null) | | |
| | `GET` | `/commissions/tenant/:tenantId` | Regra específica de um sindicato | | |
| | `POST` | `/commissions` | Criar/atualizar regra (upsert por tenant_id) | | |
| | `PUT` | `/commissions/:id` | Editar regra existente | | |
| | `DELETE` | `/commissions/:id` | Remover regra (exceto global) | | |
| | `GET` | `/commissions/splits` | Listar splits de comissão (filtros: tenant_id, status, período) | | |
| | `GET` | `/commissions/splits/summary` | Resumo: total bruto, comissão, líquido, quantidade, % médio | | |
| | `GET` | `/commissions/transfers` | Listar transferências (filtros: tenant_id, status) | | |
| | `GET` | `/commissions/transfers/pending` | Transferências com falha aguardando retry | | |
| | `POST` | `/commissions/transfers/:id/retry` | Reprocessar manualmente uma transferência com falha | | |
| **Comportamento padrão:** regra global de 3% fixo é criada automaticamente pela migration 043. | |
| ### Fluxo de transferência automática | |
| Quando o Asaas envia o webhook `PAYMENT_CONFIRMED`: | |
| 1. Calcula comissão (busca regra do tenant ou global) | |
| 2. Registra split em `payment_splits` (gross, commission, net) | |
| 3. Cria registro em `transfers` com `status = 'pending'` | |
| 4. Chama `POST /v3/transfers` no Asaas | |
| 5. Se sucesso: `status = 'processing'` | |
| 6. Se falha: `status = 'failed'` + agenda retry com exponential backoff (2, 4, 8, 16, 32, 60 min) | |
| ### Variáveis de ambiente necessárias | |
| ```env | |
| # Gateway de pagamento (produção: 'asaas', dev: 'mock') | |
| PAYMENT_PROVIDER=asaas | |
| # Asaas — Subconta (usada se não houver tenant_modules configurado) | |
| ASAAS_API_KEY=$ASAAS_SANDBOX_API_KEY | |
| ASAAS_SANDBOX=true | |
| ASAAS_ENVIRONMENT=sandbox | |
| # Asaas — Conta Master (para criar subcontas Marketplace) | |
| ASAAS_MASTER_API_KEY= | |
| # Asaas — Webhook | |
| ASAAS_WEBHOOK_TOKEN=token-configurado-no-painel-asaas | |
| ASAAS_WEBHOOK_ENABLED=false | |
| # Criptografia da API Key (se não definida, usa JWT_SECRET como fallback) | |
| ASAAS_ENCRYPTION_KEY= | |
| ``` | |
| ### Para testar localmente | |
| ```bash | |
| # 1. Subir banco | |
| docker compose up -d | |
| # 2. Rodar migrations (inclui a 043 com tabelas financeiras) | |
| cd backend && npm run migrate | |
| # 3. Rodar backend com provider mock (não depende do Asaas real) | |
| PAYMENT_PROVIDER=mock npm run dev | |
| # 4. Rodar testes | |
| cd backend && npx tsx --test src/shared/crypto.test.ts | |
| cd backend && npx tsx --test src/modules/finance/payment.adapters.test.ts | |
| cd backend && npx tsx --test src/app.test.ts | |
| ``` | |
| ### Para usar em produção (sandbox Asaas) | |
| ```bash | |
| # Criar tenant com subconta automática: | |
| curl -X POST http://localhost:3333/tenants \ | |
| -H "Authorization: Bearer <master_token>" \ | |
| -H "Content-Type: application/json" \ | |
| -d '{ | |
| "name": "Sindicato Exemplo", | |
| "slug": "sindicato-exemplo", | |
| "cnpj": "12345678000199", | |
| "email": "financeiro@sindicato.com", | |
| "criar_subconta_asaas": true | |
| }' | |
| # O sistema automaticamente: | |
| # 1. Cria subconta no Asaas via POST /v3/accounts | |
| # 2. Criptografa e salva a apiKey no tenant_modules | |
| # 3. Salva walletId e webhook token | |
| # 4. Configura webhook no Asaas | |
| ``` |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment