Setup
1. Asaas Dashboard
- https://asaas.com (ou sandbox: https://sandbox.asaas.com)
- Configuracoes > Integracoes > API > copie Access Token
- Configuracoes > Webhooks > Add:
- URL:
https://[tenant].studeia.com/api/webhooks/asaas?token=<SEU_TOKEN> - Eventos: PAYMENT_RECEIVED, PAYMENT_OVERDUE, PAYMENT_REFUNDED, SUBSCRIPTION_CREATED/UPDATED/DELETED
- URL:
- Customize token (string aleatoria, criptograficamente forte)
2. Env vars
ASAAS_API_KEY=$aact_...
ASAAS_WEBHOOK_TOKEN=...gerado-no-passo-3...
ASAAS_SANDBOX=true # opcional, default false
3. Criar produtos no Asaas
Asaas usa modelo de cobrança recorrente diferente do Stripe. Em Studeia, planos sao mapeados via codigo (nao precisa criar product no Asaas dashboard).
Fluxo PIX
Admin clica "Pagar com PIX" em /institution/billing
↓
POST /api/institution/billing/checkout
Body: { planSlug: "mini", provider: "asaas" }
↓
Studeia AsaasBillingProvider.createCheckout():
1. Resolve asaasCustomerId (cria se nao existe — POST /customers)
2. POST /subscriptions com billingType=PIX
3. Asaas retorna QR Code + copy-paste payload PIX
4. Studeia retorna { url } pagina hosted Asaas com QR
↓
Admin escaneia QR no app bancario, paga
↓
PIX confirma em ~30s (instantaneo)
↓
Webhook PAYMENT_RECEIVED → applyWebhookEvent → promove Tenant.plan
Hardening (regras 138, 139)
- Fail-closed: ausencia de ASAAS_WEBHOOK_TOKEN env = 503
asaas_not_configured(regra 138). Anti-bypass. - Token validation: query param ?token=<...> comparado com env (timing-safe comparison)
- 5xx em falha: re-tenta automaticamente
- PaymentLog idempotente: unique [provider, externalEventId]
- PII redact: rawPayload passa por redactPaymentPayload() — remove cpfCnpj, email, name, address, billing_details (regra 139)
Customer split por provider
TenantSubscription tem campos separados:
stripeCustomerId— para StripeasaasCustomerId— para AsaasexternalCustomerId— legado (mantido como fallback se provider bater)
resolveCustomerIdForProvider() em create-checkout.ts usa novos campos — NUNCA reuse ID cross-provider.
Quando usar Asaas vs Stripe
| Cenario | Recomendado |
|---|---|
| Cliente brasileiro com PIX | Asaas |
| Cliente brasileiro com boleto | Asaas |
| Cliente brasileiro com cartao | Asaas (mais barato) ou Stripe |
| Cliente internacional | Stripe USD obrigatorio (Asaas bloqueado) |
| Conta empresarial enterprise grande | Stripe (mais ferramentas — Sigma, custom reports) |
Taxas comparadas
| Metodo | Asaas | Stripe |
|---|---|---|
| PIX | 1.99% | NAO oferece nativo |
| Boleto | R$3.49 fixo | NAO oferece nativo |
| Cartao credito | 4.99% + R$0.49 | 3.99% + R$0.59 (USD) |
| Cartao debito | 1.99% + R$0.39 | NAO oferece (BR) |
| Antecipacao recebivel | Disponivel | NAO |
Para volume B2B brasileiro tipico: Asaas e ~20-40% mais barato em taxas totais.