## Objetivo

Ligar contas Stripe existentes via OAuth `read_only` e aceitar push directo de plataformas quando a conta Stripe ligada não vê a venda completa.

## Endpoints Stripe OAuth

| Endpoint | Função | Resultado esperado |
| --- | --- | --- |
| `POST /api/stripe/oauth/start?org={slug}&mode={test\|live}&lang={locale}` | preparar ligação OAuth | `redirectUrl` temporária para consentimento Stripe |
| `GET /api/stripe/oauth/start?org={slug}&mode={test\|live}&lang={locale}` | shortcut com redirect imediato | resposta `302/307` para a Stripe |
| `GET /api/stripe/oauth/callback?code=...&state=...` | callback interno OAuth | redirecionamento para o dashboard com ligação validada |

## Endpoints Beacon Connect

| Endpoint | Função | Resultado esperado |
| --- | --- | --- |
| `POST /api/platform-connect/verify-mapping` | validar `externalOrgRef` | devolve organização Beacon resolvida |
| `POST /api/platform-connect/payments` | ingerir payment | cria/enriquece `Payment` e, se houver dados suficientes, `Sale` |
| `POST /api/platform-connect/refunds` | ingerir refund | cria `PaymentRefund` e actualiza estado |
| `POST /api/platform-connect/disputes` | ingerir dispute | cria `PaymentDispute` e actualiza estado |

## Fluxo operacional recomendado

<Steps>
  <Step title="1) Iniciar OAuth">Chama `oauth/start` com organização e modo (`test|live`).</Step>
  <Step title="2) Validar callback">A Beacon valida `state`, troca `code` por token e falha se o scope não incluir `read_only`.</Step>
  <Step title="3) Ingerir Stripe visível">A conta ligada começa a alimentar `Payment.kind=CHARGE|TRANSFER|PAYOUT` e enriquecimento financeiro por `balance_transactions`.</Step>
  <Step title="4) Enriquecer quando faltar venda">Se a conta ligada só vir efeito financeiro parcial, a plataforma envia Beacon Connect para completar `Sale` e contexto fiscal.</Step>
</Steps>

## Validações obrigatórias

- `STRIPE_EXTENSION_ENABLED=true`.
- O callback OAuth exige `read_only`; `read_write` não é tratado como fallback funcional equivalente.
- `providerEventId` é obrigatório em Beacon Connect.
- Reconciliação de `Payment` segue prioridade: `stripeChargeId -> stripePaymentIntentId -> providerEventId -> (platformIntegrationId, externalPaymentId)`.

## Exemplo OAuth start

```bash
curl -X POST "https://test.beacon.pt/api/stripe/oauth/start?org=acme&mode=test&lang=pt" \
  -H "Authorization: Bearer <beacon_session_token>"
```

```json
{
  "ok": true,
  "redirectUrl": "https://connect.stripe.com/oauth/authorize?...",
  "expiresAt": "2026-03-18T11:00:00.000Z"
}
```

## Exemplo Beacon Connect verify-mapping

```bash
curl -X POST "https://app.beacon.pt/api/platform-connect/verify-mapping" \
  -H "Authorization: Bearer <platform_secret>" \
  -H "Content-Type: application/json" \
  -d '{"externalOrgRef":"seller_org_123"}'
```

## Falhas comuns e mitigação

| Sinal | Causa provável | Mitigação |
| --- | --- | --- |
| callback OAuth falha | app Stripe sem configuração Extension ou sem `read_only` | corrigir configuração Stripe e reiniciar fluxo |
| payment parcial sem `Sale` | visibilidade limitada da conta ligada | completar via Beacon Connect |
| `429` em Beacon Connect | quota da integração excedida | respeitar `retryAfterSec` e usar backoff com jitter |

<Tip title="Operação segura">O runtime Stripe usa sempre chave da plataforma com `Stripe-Account`. Os tokens OAuth ficam apenas para auditoria cifrada.</Tip>
