Files
ecommerce-platform/README.md
T
davide 126a74cddb docs: rewrite setup guide with Stripe webhook and bug fix notes
- Clarify that STRIPE_SECRET_KEY is required from step 2
- Document --profile dev as the recommended local startup command
- Replace manual stripe listen instructions with docker-compose service
- Add Stripe test cards and payment verification checklist
- Fix docker compose restart → --force-recreate in webhook setup steps
- Add troubleshooting entries for PENDING orders and .env not reloading
2026-05-19 16:05:37 +02:00

467 lines
13 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# E-commerce Platform
Piattaforma e-commerce containerizzata, avviabile con un singolo comando.
**Stack:** Next.js 14 · PostgreSQL 16 · Prisma · Stripe · Caddy · Docker Compose
---
## Avvio in locale (test su localhost)
### Prerequisiti
- [Docker Desktop](https://docs.docker.com/get-docker/) installato e avviato
- Porta **80** libera (nessun altro web server in esecuzione)
- Account [Stripe](https://stripe.com) gratuito (necessario per i pagamenti)
### 1. Clona il repository
```bash
git clone <url-repository>
cd ecommerce-platform
```
### 2. Crea il file `.env`
```bash
cp .env.example .env
```
Apri `.env` e inserisci la tua chiave Stripe test (gratuita, dalla [Stripe Dashboard → API keys](https://dashboard.stripe.com/test/apikeys)):
```env
STRIPE_SECRET_KEY=sk_test_la_tua_chiave
```
Il resto dei valori è già preconfigurato per localhost e non va modificato.
### 3. Avvia la piattaforma
**Senza pagamenti** (admin, catalogo, email):
```bash
docker compose up -d
```
**Con pagamenti e webhook Stripe attivi** (consigliato):
```bash
docker compose --profile dev up -d
```
Il primo avvio richiede **510 minuti**: Docker scarica le immagini, installa le dipendenze npm, compila Next.js, esegue le migrazioni e crea l'utente admin.
Segui il progresso con:
```bash
docker compose logs -f app
```
La piattaforma è pronta quando vedi:
```
✓ Ready in 91ms
```
### 4. Apri nel browser
| URL | Cosa trovi |
|-----|------------|
| http://localhost | Sito pubblico (vetrina) |
| http://localhost/admin | Dashboard amministratore |
| http://localhost:8025 | Mailpit — cattura le email di test |
### 5. Primo accesso admin
Vai su **http://localhost/admin** e accedi con:
```
Email: admin@example.com
Password: Admin1234!test
```
Al primo accesso il sistema ti obbliga a cambiare la password.
**Requisiti password:** minimo 12 caratteri, almeno una maiuscola, una minuscola, un numero e un simbolo.
### 6. Configura il negozio (ordine consigliato)
1. **Product Types** → crea un tipo di prodotto (es. "Prodotto") con gli attributi che vuoi
2. **Categories** → crea le categorie
3. **Products** → crea un prodotto, assegna tipo e categoria, impostalo su **Published**
4. Apri http://localhost → il prodotto appare in homepage
### 7. Setup webhook Stripe (una tantum per macchina)
Il profilo `dev` include un container `stripe-cli` che riceve i webhook da Stripe e li inoltra all'app. Senza di esso, dopo il pagamento l'ordine resta in `PENDING` e nessuna email viene inviata.
**Al primo avvio con `--profile dev`, recupera il webhook secret dai log:**
```bash
docker compose logs stripe-cli | grep "webhook signing secret"
```
Copia il valore `whsec_...` nel `.env`:
```env
STRIPE_WEBHOOK_SECRET=whsec_abc123...
```
Poi ricrea il container app per applicare la variabile (`restart` non ricarica il `.env`):
```bash
docker compose up -d --force-recreate app
```
Da questo momento `docker compose --profile dev up -d` avvia tutto inclusi i webhook — non serve altro.
### 8. Testa i pagamenti
**Carte di test Stripe:**
| Carta | Risultato |
|-------|-----------|
| `4242 4242 4242 4242` | Pagamento riuscito |
| `4000 0000 0000 0002` | Carta rifiutata |
| `4000 0025 0000 3155` | Richiede autenticazione 3D Secure |
Scadenza: qualsiasi data futura · CVC: qualsiasi 3 cifre
**Verifica che tutto funzioni dopo un pagamento:**
```bash
docker compose logs stripe-cli --tail=20
# deve mostrare [200] per checkout.session.completed
```
1. L'ordine nel pannello admin passa da `PENDING` a `PAID`
2. L'email di conferma appare su http://localhost:8025
### 9. Ferma la piattaforma
```bash
docker compose --profile dev down # ferma tutto (con stripe-cli), i dati restano
docker compose down -v # ferma e cancella anche il database
```
---
## Differenze tra localhost e produzione
Quattro cose cambiano quando si passa da localhost a un dominio reale.
### 1 — Dominio e HTTPS
Modificare **una sola riga** nel `Caddyfile`:
```
# localhost
localhost { ... }
# produzione
tuodominio.com { ... }
```
Caddy ottiene e rinnova automaticamente il certificato HTTPS tramite Let's Encrypt. Non serve nessuna configurazione SSL manuale.
### 2 — Variabili d'ambiente
Cinque variabili da aggiornare nel `.env`:
| Variabile | Localhost | Produzione |
|-----------|-----------|------------|
| `APP_URL` | `http://localhost` | `https://tuodominio.com` |
| `AUTH_SECRET` | qualsiasi stringa | `openssl rand -hex 32` |
| `STRIPE_SECRET_KEY` | `sk_test_...` | `sk_live_...` |
| `STRIPE_WEBHOOK_SECRET` | dal container stripe-cli | dal dashboard Stripe |
| `SMTP_*` | Mailpit locale (porta 8025) | provider reale (Resend, Mailgun, SendGrid…) |
### 3 — Server
Serve un VPS Linux con Docker installato (DigitalOcean, Hetzner, OVH, ecc.) e il record DNS del dominio puntato all'IP del server. Il comando di avvio è identico: `docker compose up -d` (senza `--profile dev`).
### 4 — Backup
In locale i dati si perdono con `docker compose down -v`. In produzione è necessario un backup automatico del database (vedi sezione [Backup database](#backup-database)) e conservare il volume `uploads` che contiene le immagini dei prodotti.
---
## Deploy in produzione
### Prerequisiti
- Server Linux con Docker e Docker Compose v2 (qualsiasi VPS o cloud VM)
- Dominio con record **A** puntato all'IP del server
- Porte **80** e **443** aperte nel firewall del server
- Account [Stripe](https://stripe.com) (per i pagamenti reali)
- Account SMTP (per le email: Mailgun, Resend, SendGrid, ecc.)
### 1. Clona il repository sul server
```bash
git clone <url-repository>
cd ecommerce-platform
```
### 2. Crea e configura `.env`
```bash
cp .env.example .env
nano .env
```
Modifica questi valori:
```env
# URL pubblico del sito — con https://
APP_URL=https://tuodominio.com
# Genera un segreto casuale: openssl rand -hex 32
AUTH_SECRET=incolla_qui_il_risultato_di_openssl
# Credenziali del primo admin — cambia subito dopo il primo accesso
INITIAL_ADMIN_EMAIL=admin@tuodominio.com
INITIAL_ADMIN_PASSWORD=UnaPasswordSicura1!
# Stripe — usa le chiavi live (non sk_test_)
STRIPE_SECRET_KEY=sk_live_xxxxxxxxxxxxxxxxxxxxxxxx
STRIPE_WEBHOOK_SECRET=whsec_xxxxxxxxxxxxxxxxxxxxxxxx
# SMTP reale per le email
SMTP_HOST=smtp.tuoprovider.com
SMTP_PORT=587
SMTP_USER=user@tuodominio.com
SMTP_PASSWORD=la_tua_password_smtp
SMTP_FROM=noreply@tuodominio.com
```
> `DATABASE_URL` non va modificato: usa già il nome del container Docker corretto.
### 3. Genera `AUTH_SECRET`
```bash
openssl rand -hex 32
```
Copia l'output nel campo `AUTH_SECRET` nel file `.env`.
### 4. Configura il dominio nel Caddyfile
Apri `Caddyfile` e sostituisci `localhost` con il tuo dominio:
```
tuodominio.com {
handle /uploads/* {
root * /srv
file_server
}
encode gzip zstd
reverse_proxy app:3000
}
```
### 5. Avvia
```bash
docker compose up -d
```
Attendi che l'app sia pronta:
```bash
docker compose logs -f app
# attendi: ✓ Ready in ...ms
```
Il sito è live su `https://tuodominio.com`.
### 6. Configura il webhook Stripe
Nel [dashboard Stripe → Webhooks](https://dashboard.stripe.com/webhooks), aggiungi un endpoint:
```
URL endpoint: https://tuodominio.com/api/webhooks/stripe
Eventi da ascoltare:
- checkout.session.completed
- payment_intent.succeeded
- payment_intent.payment_failed
```
Copia il **Signing secret** (`whsec_...`) nel `.env` come `STRIPE_WEBHOOK_SECRET`, poi ricrea il container per applicarlo:
```bash
docker compose up -d --force-recreate app
```
### 7. Primo accesso e configurazione negozio
1. Vai su `https://tuodominio.com/admin`
2. Accedi con le credenziali del `.env`
3. Cambia la password quando richiesto
4. Configura il negozio in questo ordine:
- **Settings** → nome negozio, logo, colori
- **Product Types** → tipi di prodotto con attributi personalizzati
- **Categories** → categorie prodotto
- **Products** → aggiungi i tuoi prodotti
- **Admin Users** → aggiungi altri amministratori se necessario
---
## Porte di rete
### Porte da aprire nel firewall del server (produzione)
| Porta | Protocollo | Servizio | Perché è necessaria |
|-------|-----------|---------|---------------------|
| **80** | TCP | Caddy (HTTP) | Redirect automatico HTTP → HTTPS e rinnovo certificati Let's Encrypt (ACME challenge) |
| **443** | TCP | Caddy (HTTPS) | Traffico web principale — sito pubblico e pannello admin |
> Solo queste due porte devono essere aperte verso l'esterno. Tutto il resto è interno a Docker.
### Porte interne (rete Docker — non esporre al pubblico)
| Porta | Servizio | Note |
|-------|---------|------|
| **3000** | Next.js (app) | Accessibile solo da Caddy tramite `reverse_proxy app:3000` |
| **5432** | PostgreSQL (db) | Accessibile solo dall'app tramite `DATABASE_URL` |
| **1025** | Mailpit SMTP | Accessibile solo dall'app per l'invio email |
### Porta solo per sviluppo locale (non aprire in produzione)
| Porta | Servizio | Note |
|-------|---------|------|
| **8025** | Mailpit UI | Interfaccia web per ispezionare le email di test — non deve mai essere esposta in produzione |
### Riepilogo comandi firewall (UFW — Ubuntu/Debian)
```bash
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw deny 8025/tcp
sudo ufw enable
sudo ufw status
```
---
## Aggiornamenti
```bash
git pull
docker compose build app
docker compose up -d
```
Le migrazioni del database vengono applicate automaticamente all'avvio.
---
## Backup database
**Dump manuale:**
```bash
docker compose exec db pg_dump -U ecommerce ecommerce > backup_$(date +%Y%m%d_%H%M%S).sql
```
**Ripristino:**
```bash
cat backup_XXXXXXXX_XXXXXX.sql | docker compose exec -T db psql -U ecommerce ecommerce
```
**Backup automatico giornaliero** (aggiungi al crontab del server con `crontab -e`):
```bash
0 3 * * * cd /percorso/ecommerce-platform && docker compose exec -T db pg_dump -U ecommerce ecommerce | gzip > /backups/ecommerce_$(date +\%Y\%m\%d).sql.gz
```
---
## Problemi comuni
**Il build impiega molto tempo al primo avvio**
È normale. npm install + compilazione Next.js richiedono 510 minuti la prima volta. I build successivi sono molto più veloci grazie alla cache Docker.
**http://localhost non risponde (502 Bad Gateway)**
L'app è ancora in fase di avvio. Aspetta qualche secondo e ricarica. Controlla lo stato con:
```bash
docker compose logs -f app
```
**Errore "port 80 already in use"**
Un altro servizio usa la porta 80 (Apache, Nginx, ecc.). Fermalo o cambia la porta nel `docker-compose.yml`.
**L'ordine resta in PENDING dopo il pagamento**
Il container `stripe-cli` non è in esecuzione o `STRIPE_WEBHOOK_SECRET` non è configurato. Verifica:
```bash
docker compose --profile dev ps # stripe-cli deve essere "running"
docker compose logs stripe-cli --tail=10
```
Se il `whsec_...` manca nel `.env`, segui lo step 7 del setup locale.
**Le variabili del `.env` non vengono applicate dopo la modifica**
`docker compose restart` non ricarica il `.env`. Usa sempre:
```bash
docker compose up -d --force-recreate app
```
**Dimentico la password admin**
Resetta direttamente nel database:
```bash
# genera hash bcrypt per la nuova password
docker compose exec app node -e "
const bcrypt = require('bcryptjs');
bcrypt.hash('NuovaPassword1!', 12).then(h => console.log(h));
"
# aggiorna nel db
docker compose exec db psql -U ecommerce ecommerce -c \
"UPDATE \"User\" SET \"passwordHash\"='HASH_QUI', \"mustChangePassword\"=true WHERE email='admin@example.com';"
```
---
## Struttura del progetto
```
ecommerce-platform/
├── docker-compose.yml Orchestrazione: db, app, caddy, mailpit, stripe-cli (profilo dev)
├── Caddyfile Reverse proxy — modifica qui il dominio
├── .env Variabili d'ambiente (non committare)
├── .env.example Template da copiare
└── app/
├── Dockerfile Build multi-stage Next.js
├── entrypoint.sh Sequenza avvio: migrazioni → admin → server
├── prisma/
│ └── schema.prisma Schema database completo
├── scripts/
│ └── bootstrap-admin.ts Crea il primo OWNER se non esiste
└── src/
├── app/ Pagine Next.js (App Router)
│ ├── admin/ Dashboard admin (protetta per ruolo)
│ ├── api/ API routes (auth, prodotti, ordini, webhook)
│ └── (storefront) Homepage, catalogo, carrello, checkout
├── components/ Componenti React riutilizzabili
└── lib/ Auth, Prisma client, Stripe, email
```
---
## Variabili d'ambiente
| Variabile | Descrizione | Locale | Produzione |
|-----------|-------------|:------:|:----------:|
| `APP_URL` | URL pubblico del sito | `http://localhost` | `https://tuodominio.com` |
| `DATABASE_URL` | Connessione PostgreSQL | invariato | invariato |
| `AUTH_SECRET` | Segreto sessioni (min 32 char) | qualsiasi | `openssl rand -hex 32` |
| `INITIAL_ADMIN_EMAIL` | Email primo admin | qualsiasi | la tua email |
| `INITIAL_ADMIN_PASSWORD` | Password primo admin | qualsiasi | sicura |
| `STRIPE_SECRET_KEY` | Chiave Stripe | `sk_test_...` | `sk_live_...` |
| `STRIPE_WEBHOOK_SECRET` | Segreto webhook Stripe | dal container stripe-cli | dal dashboard Stripe |
| `SMTP_HOST` | Server SMTP | `mailpit` | provider reale |
| `SMTP_PORT` | Porta SMTP | `1025` | `587` |
| `SMTP_USER` | Utente SMTP | vuoto | obbligatorio |
| `SMTP_PASSWORD` | Password SMTP | vuoto | obbligatorio |
| `SMTP_FROM` | Mittente email | qualsiasi | `noreply@tuodominio.com` |