Fluxo de ativação de filiação via webhook do checkout

TLDR: O checkout notifica POST /api/v1/webhook com o pagamento; o citrg-api cria (ou renova) a Membership, garante User e UserProfile, e dispara o e-mail correspondente. Renovação sempre cria uma nova Membership com o mesmo register_number. Existe uma segunda origem, POST /api/v2/webhook, para compras feitas fora do checkout (Hotmart) — ela só traduz o payload e cai no mesmo WebhookMembershipService, sem alterar nada do fluxo descrito aqui.

Visão geral

O citrg-api não conhece checkout, campanha nem bloqueio de pendência financeira — só reage ao status que o gateway envia. Toda a lógica de ativação vive em WebhookMembershipService.

mermaid flowchart TD CK["Checkout envia POST /api/v1/webhook"] --> WC["webhook_controller"] WC --> V{"status == 'paid'?"} V -->|não| UP["update_membership: só grava o payment_status"] V -->|sim| NM["initialize_new_membership"] NM --> RN["register_number: reusa o do usuário, ou último + 1"] RN --> DT["set_valid_since_and_until"] DT --> DC{"issued_definitive_card?"} DC -->|sim| AUTO["card_status auto_issued<br/>filiação e perfil aprovados<br/>sem onboarding novo"] DC -->|não| MAN["card_status not_issued<br/>aprovação do perfil zerada<br/>cria onboarding"] AUTO --> E1["e-mail: renovação aprovada"] MAN --> E2["e-mail: enviar documentos"]

Fluxo

Primeira compra

  1. O request chega em app/controllers/api/v1/webhook_controller.rb com o payload de pagamento.
  2. Passando a validação, são criados Membership, User e UserProfile.
  3. Um e-mail é disparado ao usuário para que ele envie a documentação.
  4. O UserProfile fica pendente de documentação.
  5. O usuário faz login com as credenciais do Apolo e é levado à página de documentação, onde permanece até enviar todas as informações e os três arquivos: comprovante de residência, foto da carteira e documento com foto.
  6. Ao concluir, o usuário vê a mensagem de “aguarde aprovação” e o perfil é movido para a aba “Pronta para revisar” no Admin.
  7. O administrador confere a documentação e aprova o UserProfile — ver Operação diária no Admin.
  8. Aprovado, o usuário recebe e-mail e passa a poder editar o perfil público.

Renovação

  1. O checkout envia o mesmo payload de pagamento.
  2. O citrg-api identifica que usuário e filiação já existem.
  3. Uma nova Membership é criada, com o mesmo register_number; User e UserProfile são mantidos.
  4. As datas da nova filiação encadeiam a partir da vigência em andamento — ver R-002.
  5. Para membro com carteira definitiva, a renovação é aprovada automaticamente e o e-mail é o de renovação aprovada; para os demais, a aprovação do perfil é zerada, um onboarding novo é criado e o e-mail é o de pedido de documentos — ver R-004.

Como toda renovação cria uma linha nova sem aprovação própria (salvo carteira definitiva), a exposição da filiação para consumidores externos precisa compor a resposta a partir de duas filiações — ver R-001.

Contratos

Payload esperado em POST /api/v1/webhook:

json { "payment": { "id": "payment_92839288432", "status": "paid", "billing_type": "CREDIT_CARD", "checkout_id": 1, "installment_count": 5, "customer": { "id": 123, "email": "pessoa@exemplo.com", "doc_number": "05278901462" } } }

Campo Papel
status "paid" dispara a criação da filiação; qualquer outro valor só atualiza o payment_status
checkout_id resolve o MembershipGroup via gateway_product_id; sem match, cai no último grupo
id vira o payment_reference da filiação (tem validação de unicidade)
customer.email obrigatório — chave de identificação do usuário
customer.doc_number obrigatório — sem CPF o webhook falha

Campos mínimos ausentes produzem Campos mínimos enviados: status, checkout_id, user.doc_number, user.email.

POST /api/v2/webhook recebe um payload diferente (formato de evento da Hotmart: PURCHASE_APPROVED/PURCHASE_REFUNDED/PURCHASE_DELAYED) e usa Membership::ProcessPurchaseWebhook pra traduzir pros mesmos campos acima antes de chamar o WebhookMembershipService — ver contrato completo em Endpoints da API pública.

Referências

  • app/services/webhook_membership_service.rb
  • app/controllers/api/v1/webhook_controller.rb
  • app/services/account_creator_service.rb
  • Endpoints da API pública