Implementado em: 2026-04-02 Status: Ativo Provedor: Asaas (PIX + Cartão)
Resumo
O admin pode gerar um link de pagamento Asaas pré-preenchido para converter um cliente manual em assinante pagante. O link contém os dados do cliente (nome, email, CPF/CNPJ) e quando o pagamento é confirmado, o plano é ativado automaticamente via webhook.
Fluxo
Admin > Clientes > "Vincular Plano"
→ Seleciona plano, ciclo, forma de pagamento
→ Preenche dados do cliente
→ POST /admin/tenants/{orgId}/generate-payment-link
→ Cria customer Asaas (com dados pré-preenchidos)
→ Cria subscription (nextDueDate = hoje + 7 dias)
→ Busca invoiceUrl do primeiro pagamento
→ Atualiza planId do tenant
→ Retorna checkout_url
→ Admin copia e envia para o cliente
→ Cliente abre link → dados já preenchidos → paga
→ Webhook Asaas: PAYMENT_CONFIRMED → status = "active"
Endpoint
POST /admin/tenants/{orgId}/generate-payment-link
Auth: require_staff_permission("tenants:write")
Request:
{
"planSlug": "profissional",
"billingCycle": "monthly",
"billingType": "PIX",
"customerName": "João da Silva",
"customerEmail": "joao@loja.com",
"customerCpfCnpj": "12345678901"
}
Response:
{
"checkoutUrl": "https://www.asaas.com/c/xxx",
"subscriptionId": "sub_xxx",
"customerId": "cus_xxx",
"planName": "Profissional",
"billingCycle": "monthly"
}
Parâmetros:
| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
| planSlug | string | Sim | Slug do plano (essencial, profissional, business, enterprise) |
| billingCycle | string | Não (default: monthly) | monthly, semiannual, annual |
| billingType | string | Não (default: PIX) | PIX, CREDIT_CARD |
| customerName | string | Não | Nome pré-preenchido no Asaas |
| customerEmail | string | Não | Email para notificações Asaas |
| customerCpfCnpj | string | Não | CPF ou CNPJ (só números) |
Frontend
Página: frontend/src/app/(dashboard)/admin/clients/page.tsx
Botão: "Vincular Plano" (ícone link, azul) — em cada card de cliente
Modal (2 estados):
Estado 1: Formulário
- Dropdown de plano (carregado via GET /admin/plans)
- Toggle de ciclo: Mensal / Semestral -15% / Anual -25%
- Toggle de pagamento: PIX / Cartão
- Campos pré-preenchimento: Nome, Email, CPF/CNPJ
- Botão "Gerar Link de Pagamento"
Estado 2: Resultado (após gerar)
- Badge verde "Link gerado com sucesso!"
- Nome do plano + ciclo
- Link copiável (encurtado visualmente, título com link completo)
- Botão "Copiar"
- Info: dados pré-preenchidos + ativação automática via webhook
- Botão "Fechar"
Integração Asaas
Customer pré-preenchido
customer_data = {
"name": "João da Silva", # Pré-preenchido no formulário
"email": "joao@loja.com", # Recebe notificações
"cpfCnpj": "12345678901", # Documento fiscal
"externalReference": "cf_org_xxx", # Vínculo com tenant
"groupName": "ConvertaFlow", # Filtro no painel Asaas
}
Subscription com trial
sub_data = {
"customer": customer_id,
"billingType": "PIX",
"value": 149.90,
"nextDueDate": "2026-04-09", # hoje + 7 dias (trial)
"cycle": "MONTHLY",
"description": "[ConvertaFlow] Plano Profissional (monthly)",
"externalReference": "cf_org_xxx",
}
Webhook de confirmação
Quando o cliente paga, o Asaas envia webhook PAYMENT_CONFIRMED:
POST /billing/webhook/asaas- Extrai
org_iddoexternalReference - Atualiza
TenantSubscription.status = "active" - Plano ativado automaticamente
Casos de uso
| Cenário | Como usar |
|---|---|
| Demo para prospect | Criar cliente manual → deixar usar → vincular plano quando decidir |
| Onboarding enterprise | Criar manual → configurar junto → vincular plano pós-setup |
| Trial estendido | Criar manual → dar acesso ilimitado → vincular quando trial acabar |
| Migração de plataforma | Criar manual → importar dados → vincular plano |
Arquivos
| Arquivo | Função |
|---|---|
backend-python/app/api/admin.py |
Endpoint generate-payment-link |
backend-python/app/services/billing/asaas_service.py |
create_checkout(), _create_customer() |
frontend/src/app/(dashboard)/admin/clients/page.tsx |
UI com botão + modal + resultado |