# Estratégia de pagamentos — Maison

Este projeto é **frontend estático**. O checkout atual (`js/checkout.js`) **simula**
os pagamentos no browser para poderes testar todo o fluxo sem servidor. Serve para
demonstração/UX — **nunca** para produção: validar cartões ou "aprovar" pagamentos
só no cliente é inseguro e falsificável.

Abaixo fica a estratégia para ligar pagamentos **reais em sandbox**, do mais simples
ao mais completo, cobrindo os três métodos pedidos: **Multibanco (Entidade/Referência)**,
**PayPal** e **Cartão de crédito**.

---

## Como testar já (modo simulação, sem backend)

Abre `checkout.html`, adiciona artigos ao cesto e experimenta:

| Método | Como testar |
|---|---|
| **Cartão** | `4242 4242 4242 4242` → **aprova**. `4000 0000 0000 0002` → **recusa**. Validade futura + CVC qualquer. (Validação Luhn incluída.) |
| **Multibanco** | Gera Entidade `21883` + Referência + valor. Botão **"Simular pagamento recebido"** confirma. |
| **PayPal** | Mock do ecrã Sandbox → **"Iniciar sessão e pagar"** confirma. |

---

## Arquitetura recomendada para produção

O princípio de ouro: **o valor a cobrar e a confirmação do pagamento vivem no servidor**,
nunca no cliente. O frontend só recolhe dados e mostra estados.

```
[Browser / checkout.js]  →  [Backend teu]  →  [PSP: Stripe / PayPal / IfThenPay]
      recolhe dados          calcula total          processa e devolve estado
      mostra estado          cria "intent"          envia WEBHOOK de confirmação
                             confirma via webhook
```

Precisas de um backend mínimo (Node/Express, PHP, serverless…). Duas chaves por PSP:
**publishable/client-id** (frontend, pública) e **secret** (só backend).

---

## Opção A — Stripe (recomendada: cartão **e** Multibanco num só PSP)

O Stripe suporta cartões e **Multibanco** (método `multibanco`, gera Entidade/Referência)
com a mesma API. É a via mais rápida para ter os dois.

**Sandbox:** conta em modo *Test*, chaves `pk_test_...` / `sk_test_...`.
Cartões de teste: `4242 4242 4242 4242` (ok), `4000 0000 0000 0002` (recusado).

### Backend (cria o PaymentIntent — o total é calculado aqui)
```js
// server.js — Node + Express
import express from 'express';
import Stripe from 'stripe';
const stripe = new Stripe(process.env.STRIPE_SECRET_KEY); // sk_test_...
const app = express(); app.use(express.json());

app.post('/api/create-payment-intent', async (req, res) => {
  const amount = calcularTotalDoCesto(req.body.items); // €→cêntimos, validado no servidor
  const intent = await stripe.paymentIntents.create({
    amount, currency: 'eur',
    payment_method_types: ['card', 'multibanco'],
  });
  res.json({ clientSecret: intent.client_secret });
});

// Confirmação FIÁVEL: webhook (não confies no browser)
app.post('/api/webhook', express.raw({ type: 'application/json' }), (req, res) => {
  const event = stripe.webhooks.constructEvent(
    req.body, req.headers['stripe-signature'], process.env.STRIPE_WEBHOOK_SECRET);
  if (event.type === 'payment_intent.succeeded') marcarEncomendaPaga(event.data.object);
  res.json({ received: true });
});
```

### Frontend (substitui a simulação)
```html
<script src="https://js.stripe.com/v3/"></script>
```
```js
const stripe = Stripe('pk_test_...');           // chave pública
const { clientSecret } = await fetch('/api/create-payment-intent', {
  method: 'POST', headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({ items: CART.items() })
}).then(r => r.json());

const elements = stripe.elements({ clientSecret });
elements.create('payment').mount('#payment-element'); // mostra cartão + Multibanco

// no submit:
const { error } = await stripe.confirmPayment({
  elements, confirmParams: { return_url: location.origin + '/checkout.html?done=1' }
});
```
Para Multibanco, o Stripe devolve a **Entidade/Referência** no objeto do PaymentIntent
(`next_action.multibanco_display_details`) — mostras esses dados no ecrã (como no mock).

---

## Opção B — PayPal (Sandbox, quase sem backend)

O PayPal tem SDK de botões que corre no cliente; para segurança, a captura deve ser
confirmada no servidor. Em sandbox dá para testar só com o SDK.

**Sandbox:** cria app em <https://developer.paypal.com> → obténs `client-id` de teste e
contas de comprador/vendedor sandbox para login de teste.

```html
<script src="https://www.paypal.com/sdk/js?client-id=SANDBOX_CLIENT_ID&currency=EUR"></script>
<div id="paypal-button-container"></div>
```
```js
paypal.Buttons({
  createOrder: (data, actions) => actions.order.create({
    purchase_units: [{ amount: { value: CART.total().toFixed(2) } }]
  }),
  onApprove: async (data, actions) => {
    const details = await actions.order.capture();   // em produção: capturar no backend
    mostrarConfirmacao(details.id);
    CART.clear();
  }
}).render('#paypal-button-container');
```

---

## Opção C — Multibanco "puro" com PSP nacional (IfThenPay / Easypay / SIBS)

Se quiseres **Entidade/Referência Multibanco** sem o Stripe, usa um gateway português:

- **IfThenPay** — API simples: pedes referência e recebes `Entidade` + `Referência` + `Valor`.
  Também tem MB WAY e Payshop. Ambiente de testes com credenciais de demo.
- **Easypay** — API REST, sandbox dedicada, suporta Multibanco/MB WAY/cartão.
- **SIBS Gateway** — oficial (rede Multibanco), mais burocrático.

Fluxo típico (backend → IfThenPay):
```
POST /multibanco/reference  { chave, valor, id_encomenda }
→ { Entidade: "21883", Referencia: "123 456 789", Valor: "129.00" }
```
O pagamento é assíncrono: o cliente paga na caixa/homebanking e o PSP chama o teu
**callback/webhook** a confirmar. Só aí marcas a encomenda como paga.

---

## Recomendação final

| Objetivo | Escolha |
|---|---|
| Testar rápido a UX (agora) | Simulação incluída neste projeto |
| Cartão + Multibanco com 1 integração | **Stripe** (Opção A) |
| Só PayPal, mínimo esforço | **PayPal SDK Sandbox** (Opção B) |
| Multibanco/MB WAY nacional dedicado | **IfThenPay / Easypay** (Opção C) |

**Regras não-negociáveis em produção:**
1. Total **sempre** recalculado no servidor a partir dos IDs do cesto.
2. Confirmação de pagamento **sempre** via webhook do PSP (nunca só `onApprove`/redirect).
3. Chaves *secret* **apenas** no backend; no frontend só as públicas.
4. Servir sob **HTTPS**; cumprir SCA/3-D Secure (o Stripe/PayPal tratam disto).
