Add Stripe payment integration and update configuration
- Added Stripe environment variables to docker-compose.yml for secret key, webhook secret, and base URL. - Created PAYMENTS.md to document the setup and usage of the Stripe payment system. - Updated webhook signature handling in stripe.js to use a new secret key. Signed-off-by: Omar Sánchez Pizarro <omar.sanchez@pistacero.net>
This commit is contained in:
257
PAYMENTS.md
Normal file
257
PAYMENTS.md
Normal file
@@ -0,0 +1,257 @@
|
||||
# Sistema de Pagos con Stripe
|
||||
|
||||
Este documento explica cómo configurar y usar el sistema de pagos integrado con Stripe en Wallabicher.
|
||||
|
||||
## Configuración
|
||||
|
||||
### 1. Crear cuenta de Stripe
|
||||
|
||||
1. Visita [https://stripe.com](https://stripe.com) y crea una cuenta
|
||||
2. Accede al Dashboard de Stripe
|
||||
3. Obtén tus claves API desde: Developers → API keys
|
||||
|
||||
### 2. Configurar variables de entorno
|
||||
|
||||
Crea un archivo `.env` en `/web/backend/` con las siguientes variables:
|
||||
|
||||
```bash
|
||||
# Stripe Configuration
|
||||
STRIPE_SECRET_KEY=sk_test_xxxxx # Tu clave secreta de Stripe
|
||||
STRIPE_WEBHOOK_SECRET=whsec_xxxxx # Secret del webhook (ver paso 3)
|
||||
BASE_URL=http://localhost # URL base de tu aplicación
|
||||
```
|
||||
|
||||
### 3. Configurar Webhooks de Stripe
|
||||
|
||||
Los webhooks son necesarios para que Stripe notifique a tu aplicación sobre eventos de pago:
|
||||
|
||||
1. Ve a Developers → Webhooks en el Dashboard de Stripe
|
||||
2. Haz clic en "Add endpoint"
|
||||
3. URL del endpoint: `https://tu-dominio.com/api/payments/webhook`
|
||||
4. Selecciona los siguientes eventos:
|
||||
- `checkout.session.completed`
|
||||
- `customer.subscription.updated`
|
||||
- `customer.subscription.deleted`
|
||||
- `invoice.payment_succeeded`
|
||||
- `invoice.payment_failed`
|
||||
5. Copia el "Signing secret" (whsec_xxxxx) y agrégalo a `STRIPE_WEBHOOK_SECRET`
|
||||
|
||||
### 4. Configurar productos y precios en Stripe (Opcional)
|
||||
|
||||
El sistema crea automáticamente los productos y precios en Stripe si no existen, pero puedes crearlos manualmente:
|
||||
|
||||
**Productos:**
|
||||
- Wallabicher Básico
|
||||
- Wallabicher Pro
|
||||
- Wallabicher Enterprise
|
||||
|
||||
**Precios:**
|
||||
- Cada producto debe tener precios mensual y anual
|
||||
- Los `lookup_key` deben seguir el formato: `{planId}_{billingPeriod}` (ej: `basic_monthly`, `pro_yearly`)
|
||||
|
||||
### 5. Actualizar Docker Compose
|
||||
|
||||
Descomenta las variables de Stripe en `docker-compose.yml`:
|
||||
|
||||
```yaml
|
||||
environment:
|
||||
- STRIPE_SECRET_KEY=${STRIPE_SECRET_KEY}
|
||||
- STRIPE_WEBHOOK_SECRET=${STRIPE_WEBHOOK_SECRET}
|
||||
- BASE_URL=${BASE_URL:-http://localhost}
|
||||
```
|
||||
|
||||
Luego crea un archivo `.env` en la raíz del proyecto:
|
||||
|
||||
```bash
|
||||
STRIPE_SECRET_KEY=sk_test_xxxxx
|
||||
STRIPE_WEBHOOK_SECRET=whsec_xxxxx
|
||||
BASE_URL=https://tu-dominio.com
|
||||
```
|
||||
|
||||
## Flujo de registro y pago
|
||||
|
||||
### 1. Registro de usuario
|
||||
|
||||
Los usuarios pueden registrarse desde la landing page o directamente en `/dashboard/register`:
|
||||
|
||||
1. Usuario selecciona un plan
|
||||
2. Completa el formulario de registro (usuario, email, contraseña)
|
||||
3. Si es plan gratuito:
|
||||
- Se crea la cuenta inmediatamente
|
||||
- Redirige al dashboard
|
||||
4. Si es plan de pago:
|
||||
- Se crea la cuenta
|
||||
- Se inicia sesión automáticamente
|
||||
- Redirige a Stripe Checkout
|
||||
|
||||
### 2. Checkout de Stripe
|
||||
|
||||
En Stripe Checkout el usuario:
|
||||
- Ingresa información de tarjeta
|
||||
- Confirma el pago
|
||||
- Es redirigido de vuelta al dashboard
|
||||
|
||||
### 3. Gestión de suscripción
|
||||
|
||||
Desde `/dashboard/subscription` el usuario puede:
|
||||
- Ver su plan actual y límites
|
||||
- Ver uso de búsquedas
|
||||
- Cambiar de plan
|
||||
- Cancelar suscripción
|
||||
- Reactivar suscripción cancelada
|
||||
- Gestionar método de pago (portal de Stripe)
|
||||
|
||||
## Endpoints API
|
||||
|
||||
### Pagos
|
||||
|
||||
- `POST /api/payments/create-checkout-session` - Crear sesión de checkout
|
||||
- `POST /api/payments/create-portal-session` - Abrir portal de cliente
|
||||
- `POST /api/payments/cancel-subscription` - Cancelar suscripción
|
||||
- `POST /api/payments/reactivate-subscription` - Reactivar suscripción
|
||||
- `POST /api/payments/webhook` - Webhook de Stripe (sin autenticación)
|
||||
|
||||
### Usuarios
|
||||
|
||||
- `POST /api/users/register` - Registro público
|
||||
- `POST /api/users/login` - Iniciar sesión
|
||||
- `POST /api/users/logout` - Cerrar sesión
|
||||
- `GET /api/users/me` - Información del usuario actual
|
||||
|
||||
### Suscripciones
|
||||
|
||||
- `GET /api/subscription/plans` - Obtener planes disponibles
|
||||
- `GET /api/subscription/me` - Obtener suscripción actual
|
||||
- `PUT /api/subscription/me` - Actualizar suscripción
|
||||
|
||||
## Límites de planes
|
||||
|
||||
Los límites se aplican automáticamente mediante middleware:
|
||||
|
||||
### Plan Gratuito
|
||||
- 2 búsquedas simultáneas
|
||||
- Solo Wallapop
|
||||
- 50 notificaciones/día
|
||||
|
||||
### Plan Básico (€9.99/mes)
|
||||
- 5 búsquedas simultáneas
|
||||
- Wallapop + Vinted
|
||||
- 200 notificaciones/día
|
||||
|
||||
### Plan Pro (€19.99/mes)
|
||||
- 15 búsquedas simultáneas
|
||||
- Todas las plataformas
|
||||
- 1000 notificaciones/día
|
||||
|
||||
### Plan Enterprise (€49.99/mes)
|
||||
- Búsquedas ilimitadas
|
||||
- Todas las plataformas
|
||||
- Notificaciones ilimitadas
|
||||
|
||||
## Modo de prueba vs Producción
|
||||
|
||||
### Modo de prueba (Desarrollo)
|
||||
|
||||
Usa claves de prueba (`sk_test_xxxxx`):
|
||||
- No se procesan pagos reales
|
||||
- Usa tarjetas de prueba: `4242 4242 4242 4242`
|
||||
- Los webhooks requieren Stripe CLI o túnel (ngrok)
|
||||
|
||||
Para probar webhooks localmente:
|
||||
|
||||
```bash
|
||||
stripe listen --forward-to localhost:3001/api/payments/webhook
|
||||
```
|
||||
|
||||
### Modo producción
|
||||
|
||||
#### 1. Obtener claves LIVE de Stripe
|
||||
|
||||
1. Ve a https://dashboard.stripe.com/apikeys (modo **LIVE**)
|
||||
2. Copia la clave secreta `sk_live_...`
|
||||
3. **¡IMPORTANTE!** Nunca hagas commit de esta clave a git
|
||||
|
||||
#### 2. Configurar webhook en Stripe Dashboard
|
||||
|
||||
1. Ve a https://dashboard.stripe.com/webhooks (modo **LIVE**)
|
||||
2. Click en **"Add endpoint"**
|
||||
3. **Endpoint URL:** Tu dominio + la ruta del webhook
|
||||
```
|
||||
https://tudominio.com/api/payments/webhook
|
||||
```
|
||||
Ejemplos:
|
||||
- `https://wallabag.midominio.com/api/payments/webhook`
|
||||
- `https://api.miapp.com/api/payments/webhook`
|
||||
|
||||
4. **Selecciona estos eventos:**
|
||||
- `checkout.session.completed`
|
||||
- `customer.subscription.updated`
|
||||
- `customer.subscription.deleted`
|
||||
- `invoice.payment_succeeded`
|
||||
- `invoice.payment_failed`
|
||||
|
||||
5. **Guarda** y copia el **Webhook signing secret** (`whsec_...`)
|
||||
|
||||
#### 3. Variables de entorno en tu servidor
|
||||
|
||||
**Docker Compose (VPS/servidor propio):**
|
||||
```bash
|
||||
# En tu servidor, edita .env
|
||||
STRIPE_SECRET_KEY=sk_live_TU_CLAVE_REAL
|
||||
STRIPE_WEBHOOK_SECRET=whsec_SECRET_DEL_WEBHOOK
|
||||
BASE_URL=https://tudominio.com
|
||||
|
||||
# Reinicia los contenedores
|
||||
docker-compose restart backend
|
||||
```
|
||||
|
||||
**Heroku:**
|
||||
```bash
|
||||
heroku config:set STRIPE_SECRET_KEY=sk_live_...
|
||||
heroku config:set STRIPE_WEBHOOK_SECRET=whsec_...
|
||||
heroku config:set BASE_URL=https://tu-app.herokuapp.com
|
||||
```
|
||||
|
||||
**Railway/Render/Vercel:**
|
||||
Añade las variables en el panel de configuración del servicio.
|
||||
|
||||
#### 4. ⚠️ Requisitos obligatorios
|
||||
|
||||
- **HTTPS habilitado** (Stripe requiere HTTPS en producción)
|
||||
- Certificado SSL válido
|
||||
- Dominio accesible públicamente
|
||||
|
||||
## Seguridad
|
||||
|
||||
- Las claves de Stripe NUNCA deben exponerse en el frontend
|
||||
- Los webhooks verifican la firma automáticamente
|
||||
- Las rutas de pago requieren autenticación (excepto webhook)
|
||||
- Los administradores pueden gestionar suscripciones de todos los usuarios
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Los webhooks no funcionan
|
||||
|
||||
1. Verifica que `STRIPE_WEBHOOK_SECRET` esté configurado
|
||||
2. Verifica que la URL del webhook en Stripe sea correcta
|
||||
3. En desarrollo, usa `stripe listen` para reenviar webhooks
|
||||
4. Revisa los logs en Stripe Dashboard → Developers → Webhooks
|
||||
|
||||
### Los pagos no se reflejan
|
||||
|
||||
1. Verifica que el webhook esté recibiendo eventos
|
||||
2. Verifica logs del backend para errores
|
||||
3. Verifica que los metadatos (userId, planId) se estén enviando correctamente
|
||||
|
||||
### Error "Stripe no está configurado"
|
||||
|
||||
- Verifica que `STRIPE_SECRET_KEY` esté en variables de entorno
|
||||
- Reinicia el servidor backend después de configurar
|
||||
|
||||
## Recursos
|
||||
|
||||
- [Documentación de Stripe](https://stripe.com/docs)
|
||||
- [Stripe Checkout](https://stripe.com/docs/payments/checkout)
|
||||
- [Stripe Webhooks](https://stripe.com/docs/webhooks)
|
||||
- [Stripe CLI](https://stripe.com/docs/stripe-cli)
|
||||
|
||||
@@ -37,6 +37,9 @@ services:
|
||||
- MONGODB_DATABASE=wallabicher
|
||||
- MONGODB_USERNAME=admin
|
||||
- MONGODB_PASSWORD=adminpassword
|
||||
- STRIPE_SECRET_KEY=sk_test_51SrpOfH73CrYqhOp2NfijzzU07ADADmwigscMVdLGzKu9zA83dsrODhfsaY1X4EFTSihhIB0lVtDQ2HpeOfMWTur00YLuuktSL
|
||||
- STRIPE_WEBHOOK_SECRET=whsec_8ebec8c2aa82a791aa9f2cd68211e297a5d172aea62ebd7b771d230e3a597aa8
|
||||
- BASE_URL=https://wb.pribyte.cloud/api
|
||||
volumes:
|
||||
# Montar archivos de configuración y datos en ubicación predecible
|
||||
- ./config.yaml:/data/config.yaml:ro
|
||||
|
||||
@@ -214,7 +214,7 @@ export function verifyWebhookSignature(payload, signature) {
|
||||
let webhookSecret = process.env.STRIPE_WEBHOOK_SECRET;
|
||||
|
||||
if (!webhookSecret) {
|
||||
webhookSecret = 'whsec_8ebec8c2aa82a791aa9f2cd68211e297a5d172aea62ebd7b771d230e3a597aa8';
|
||||
webhookSecret = 'whsec_n6tTKRSG38WJQDRX8jLjZTs7kPKxbdNP';
|
||||
}
|
||||
|
||||
if (!webhookSecret) {
|
||||
|
||||
Reference in New Issue
Block a user