Skip to content

Latest commit

 

History

1 Commit

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

CapiBot — Bot de WhatsApp para Capibara's Crochet

Servidor webhook para la API oficial de WhatsApp Business (Meta Cloud API). Recibe mensajes de clientes, detecta palabras clave y responde automáticamente.


Arquitectura

Cliente escribe en WhatsApp
          ↓
    Meta recibe el mensaje
          ↓
    Meta hace POST → /webhook (este servidor)
          ↓
    verifySignature (HMAC-SHA256)
          ↓
    messageHandler (detecta palabra clave)
          ↓
    sendMessage → API de Meta → cliente recibe respuesta

Estructura del proyecto

CapiBot/
├── src/
│   ├── config.js                  # Variables de entorno centralizadas y validadas
│   ├── middleware/
│   │   ├── verifySignature.js     # Verificación de firma Meta (HMAC-SHA256)
│   │   └── security.js            # Helmet + Rate Limit + CORS
│   ├── handlers/
│   │   └── messageHandler.js      # Lógica del bot y palabras clave
│   └── utils/
│       └── sendMessage.js         # Funciones para enviar mensajes via API Meta
├── index.js                       # Servidor principal (Express)
├── .env                           # Variables locales (NO subir a GitHub)
├── .env.example                   # Plantilla de variables (sí va en GitHub)
├── .gitignore
└── package.json

Variables de entorno

Copia .env.example a .env y llena cada valor antes de arrancar.

Variable Descripción Dónde encontrarla
PORT Puerto del servidor (default: 3000) Tú lo defines
NODE_ENV development o production Tú lo defines
VERIFY_TOKEN String inventado por ti para verificar el webhook Tú lo defines — debe coincidir con lo que ingresas en Meta
WHATSAPP_TOKEN Token permanente de acceso a la API Meta Developers → Usuarios del sistema → Generar token
PHONE_NUMBER_ID ID del número de WhatsApp registrado Meta Developers → WhatsApp → Configuración de la API
APP_SECRET Secreto de la app para verificar firmas Meta Developers → Tu app → Configuración → Básica

Instalación

# Instalar dependencias
npm install

# Copiar plantilla de variables de entorno
cp .env.example .env

# Editar .env con tus valores reales
# (abre el archivo y llena cada campo)

# Arrancar en desarrollo (recarga automática)
npm run dev

# Arrancar en producción
npm start

Endpoints

GET /health

Verifica que el servidor está corriendo.

Respuesta: { "status": "ok", "env": "production" }

GET /webhook

Meta lo usa una sola vez para verificar que el servidor es tuyo. Compara el hub.verify_token con tu VERIFY_TOKEN del .env.

Parámetros (los envía Meta automáticamente):
  hub.mode          → "subscribe"
  hub.verify_token  → el token que configuraste en Meta
  hub.challenge     → string que debes devolver si el token es correcto

POST /webhook

Recibe todos los mensajes de clientes en tiempo real. Protegido por verificación de firma HMAC-SHA256.


Palabras clave del bot

El cliente escribe El bot responde
hola, buenas, buenos días Mensaje de bienvenida con menú
catalogo, catálogo, productos Link al catálogo en Vercel
cotizacion, cotización, precio, cuanto Link al formulario de cotización
info, horario, envio, envío Información del negocio
cualquier otro texto Menú de opciones

Seguridad implementada

1. Verificación de firma Meta (la más importante)

Cada POST que Meta envía al webhook incluye el header X-Hub-Signature-256. Es un HMAC-SHA256 del cuerpo del mensaje usando el APP_SECRET.

El servidor recalcula la firma y la compara. Si no coincide → 403 Forbidden. Esto garantiza que solo Meta puede enviar mensajes al webhook.

Header recibido:  X-Hub-Signature-256: sha256=abc123...
Firma calculada:  sha256=HMAC(APP_SECRET, rawBody)
¿Coinciden? → procesa el mensaje
¿No coinciden? → 403

2. Helmet

Agrega automáticamente 11 cabeceras HTTP de seguridad:

  • X-Content-Type-Options: nosniff
  • X-Frame-Options: DENY
  • Strict-Transport-Security (HSTS)
  • Content-Security-Policy
  • entre otras

3. Rate Limiting

Máximo 30 peticiones por minuto por IP. Previene abuso y ataques de denegación de servicio básicos.

4. CORS bloqueado

Meta hace peticiones server-to-server, no desde un navegador. CORS deshabilitado completamente en el webhook — cualquier petición desde un browser es rechazada.

5. Variables de entorno

Todos los tokens y secretos viven en .env (local) o en las variables de Railway (producción). Nunca están escritos en el código.

6. Sin stack traces en producción

El manejador de errores global devuelve solo "Error interno" cuando NODE_ENV=production. Los detalles del error solo se muestran en desarrollo.

7. HTTPS

Railway provee HTTPS automáticamente. Todo el tráfico está encriptado en tránsito.


Deploy en Railway

1. Crear cuenta

Ve a railway.app y crea una cuenta con GitHub.

2. Crear proyecto

  • Click "New Project"
  • Selecciona "Deploy from GitHub repo"
  • Conecta el repositorio de CapiBot

3. Configurar variables de entorno

En el panel de Railway → tu servicio → "Variables":

NODE_ENV        = production
PORT            = 3000
VERIFY_TOKEN    = (el que definiste)
WHATSAPP_TOKEN  = (token permanente de Meta)
PHONE_NUMBER_ID = (ID del número en Meta)
APP_SECRET      = (secreto de la app en Meta)

4. URL pública

Railway genera una URL HTTPS automáticamente:

https://capibot-production.up.railway.app

5. Configurar en Meta

En Meta Developers → tu app → WhatsApp → Configuración → Webhooks:

URL de callback:       https://capibot-production.up.railway.app/webhook
Token de verificación: (el mismo VERIFY_TOKEN que pusiste en Railway)
Campos suscritos:      messages ✅

Verificación local (pruebas manuales)

# 1. Verificar que el servidor arranca
npm run dev
# Debe mostrar: 🚀 CapiBot corriendo en puerto 3000 [development]

# 2. Health check
curl http://localhost:3000/health
# Respuesta: {"status":"ok","env":"development"}

# 3. Simular verificación de Meta
curl "http://localhost:3000/webhook?hub.mode=subscribe&hub.verify_token=TU_VERIFY_TOKEN&hub.challenge=test123"
# Respuesta: test123

# 4. Simular mensaje entrante (sin firma válida — debe responder 403)
curl -X POST http://localhost:3000/webhook \
  -H "Content-Type: application/json" \
  -d '{"entry":[{"changes":[{"value":{"messages":[{"from":"521234567890","type":"text","text":{"body":"hola"}}]}}]}]}'
# Respuesta: 403 (correcto — falta la firma Meta)

Flujo completo de producción

1. Cliente escribe "cotización" al número de WhatsApp de Capibara's Crochet
2. Meta recibe el mensaje en sus servidores
3. Meta hace POST a https://capibot-production.up.railway.app/webhook
4. El servidor verifica la firma HMAC-SHA256 → válida ✅
5. messageHandler detecta la palabra "cotización"
6. sendMessage llama a la API de Meta con el link del formulario
7. Meta entrega el mensaje al cliente
8. Cliente recibe el link y llena el formulario de cotización

Dependencias

Paquete Versión Uso
express ^5.2.1 Servidor HTTP
helmet ^8.x Cabeceras de seguridad
express-rate-limit ^8.x Límite de peticiones
cors ^2.x Control de origen
dotenv ^17.x Variables de entorno en local
crypto built-in Node.js Verificación de firma HMAC-SHA256

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages