## Objetivo

Garantir que os eventos Stripe chegam ao Beacon com validação criptográfica, deduplicação e capacidade de replay.

## Procedimento recomendado

<Steps>
  <Step title="1) Definir endpoint estável">Usa o endpoint Beacon canónico sem redirects e com o `org` certo na query string.</Step>
  <Step title="2) Guardar o signing secret">Armazena o segredo no cofre de secrets e nunca em código.</Step>
  <Step title="3) Validar eventos obrigatórios">Confirma que a Stripe entrega os eventos mínimos esperados para checkout e subscrição.</Step>
  <Step title="4) Configurar replay seguro">Mantém replay manual por `webhookEventId` e registo de auditoria por evento.</Step>
</Steps>

<Tip title="Boas práticas">Ativa alertas para backlog de eventos por organização e para falhas de assinatura consecutivas.</Tip>

## Endpoints canónicos por ambiente

- Geral `test`: `https://test.beacon.pt/api/webhooks/stripe?org=<organization_slug>&mode=test`
- Geral `live`: `https://app.beacon.pt/api/webhooks/stripe?org=<organization_slug>&mode=live`
- Billing dedicado: mesma convenção em `/api/webhooks/stripe/billing`

## Exemplo de verificação mínima

<Tabs>
  <Tab label="curl">
    ```bash
curl -X POST "https://test.beacon.pt/api/webhooks/stripe?org=acme&mode=test" \
  -H "Content-Type: application/json" \
  -H "Stripe-Signature: t=1710492000,v1=<assinatura_real>" \
  -d '{"id":"evt_123","type":"checkout.session.completed"}'
```
  </Tab>
  <Tab label="node">
    ```ts
const signature = request.headers.get("stripe-signature");
const payload = await request.text();
const event = stripe.webhooks.constructEvent(payload, signature ?? "", process.env.STRIPE_WEBHOOK_SECRET!);
await processEvent(event);
```
  </Tab>
</Tabs>

## Critérios de pronto

- Taxa de erro < 1% por janela de 15 minutos.
- Reprocessamento de eventos possível por `webhookEventId`.
- Logs com correlação entre evento, organização e pipeline fiscal.
