Servidor Express que procesa webhooks de compra, personaliza PDFs (marca de agua central y banda de seguridad superior con metadatos y hash), y envía el resultado por email vía Gmail API.
- Marca de agua central no seleccionable (render SVG→PNG con Sharp).
- Banda de seguridad como imagen (SVG→PNG) con icono, mensajes y hash del documento.
- Metadatos PDF (título, autor, palabras clave, fechas).
- Soporte de payload Kajabi (incluye arrays de eventos).
- Procesamiento por oferta: para títulos mapeados se procesan todos los PDFs de
descargables/keto_optimizadoen lote. - Normalización de PDFs problemáticos (Ghostscript y copia de páginas con pdf-lib).
- Cola en memoria: las solicitudes se encolan y se procesan de forma secuencial.
- Compresión automática: si un PDF final > 17 MiB, se recomprime (/ebook) antes de enviar.
- Particionado de envíos: divide adjuntos en varios correos si el total excede ~17 MiB por mensaje.
- Node 18+ (para desarrollo local)
- Cuenta de Google Cloud con Gmail API habilitada (OAuth2)
- Docker (recomendado para producción). La imagen instala fontconfig, DejaVu y Ghostscript.
- Copia
.env.examplea.envy completa:
# Puerto local (producción usa PORT inyectado por la plataforma)
PORT=3000
# Gmail API OAuth2
GMAIL_CLIENT_ID=
GMAIL_CLIENT_SECRET=
GMAIL_REDIRECT_URI=https://developers.google.com/oauthplayground
GMAIL_REFRESH_TOKEN=
GMAIL_SENDER=
# Opcionales (según flujo)
# BASE_PDF_PATH=/usr/src/app/KO_ebook.pdf
# BASE_PDF_URL=https://.../KO_ebook.pdf
# KETO_OPTIMIZADO_URLS=[{"name":"Keto_Optimizado_Baja_kcal_2024.pdf","url":"https://.../Keto_Optimizado_Baja_kcal_2024.pdf"}]
# EBOK_KO_URLS=[{"name":"Ebook_KO.pdf","url":"https://drive.google.com/..."}]
# Storage persistente para descargas (sobrevive a redeploys)
PERSISTENT_STORAGE_PATH=/app/persistent
- El
GMAIL_REFRESH_TOKENdebe emitirse paraGMAIL_SENDERcon el scopehttps://mail.google.com/.
npm install
npm start
# o npm run devSalud:
curl -s http://localhost:3000/health- Endpoint:
POST /webhook - Cuerpo (soporta dos formas):
- Directo:
{
"fullName": "Nombre Apellido",
"email": "cliente@example.com",
"purchasedAt": "2025-09-03T12:34:56.000Z"
}- Kajabi (array) ejemplo:
[
{
"offer": { "title": "Keto Optimizado" },
"member": { "email": "cliente@example.com", "name": "Nombre Apellido" },
"payment_transaction": { "created_at": "2025-09-04T18:55:39.864Z" },
"event": "payment.succeeded"
}
]Se procesan todos los PDFs de descargables/keto_optimizado cuando offer.title es exactamente uno de:
Keto OptimizadoOFERTA CURSO KETO OPTIMIZADOCURSO KETO OPTIMIZADO (UPSELL KETOFAST)Test Product
Para cambiar estos títulos, edita allowedTitles en src/server.js.
- Límite por mensaje ~25 MiB en Gmail (incluye base64). El servicio usa ~17 MiB de umbral por mensaje para ir seguro y dividir en varios correos si hace falta.
- Cada PDF individual se recomprime automáticamente si supera 17 MiB (perfil
/ebook). - Los asuntos incluyen sufijo
(i/N)cuando un lote requiere varios correos.
docker build -t pdf-watermarker .
docker run -p 8080:8080 --env-file .env -e PORT=8080 pdf-watermarkerSalud: http://localhost:8080/health
- Conecta este repo desde GitHub.
- Railway construirá usando el
Dockerfile. - Variables en Railway:
GMAIL_CLIENT_ID,GMAIL_CLIENT_SECRET,GMAIL_REDIRECT_URI,GMAIL_REFRESH_TOKEN,GMAIL_SENDER.- No definas
PORT(Railway la inyecta). El servicio ya hace bind aprocess.env.PORT. - Opcionales:
KETO_OPTIMIZADO_URLS,EBOK_KO_URLS,BASE_PDF_URL/BASE_PDF_PATHsi usas flujos alternativos.
- Prueba:
curl -s https://<tu-app>.up.railway.app/healthdescargables/keto_optimizado/→ PDFs base de la oferta mapeada.src/watermark.js→ watermark central (SVG→PNG) y posicionamiento.src/security.js→ banda superior (SVG→PNG), metadatos y hash.src/mailer.js→ envío vía Gmail API, particionado por tamaño.src/server.js→ endpoint, cola, normalización (Ghostscript + pdf-lib), orquestación.descargables/ebook_ko/→ PDFs del pack "Ebook KO" (si no usas URLs por entorno).
- 502 en Railway: asegúrate de no fijar
PORT; el contenedor debe escuchar en el puerto inyectado. - Emails no llegan: seguramente por tamaño. Revisa logs; el servicio divide en varios correos y comprime si es necesario.
- PDFs con refs inválidas/emoji: el pipeline usa DejaVu y sanitiza con Ghostscript; además reescribe páginas con pdf-lib.
# Gmail API
GMAIL_CLIENT_ID=
GMAIL_CLIENT_SECRET=
GMAIL_REDIRECT_URI=https://developers.google.com/oauthplayground
GMAIL_REFRESH_TOKEN=
GMAIL_SENDER=hello@intergalactic.plus
# Redis (opcional para BullMQ)
REDIS_URL=
# Packs por URLs de Drive (JSON en una sola línea)
KETO_OPTIMIZADO_URLS=[]
KETO_FAST_URLS=[]
EBOK_KO_URLS=[]
LDL_COLESTEROL_URLS=[]
CONTROL_APETITO_URLS=[]
ANALITICAS_ESENCIALES_URLS=[]
# Procesamiento
ENABLE_GS=true
ENABLE_QPDF=true
BANNER_DPI=200
# Público (opcional para generar enlaces)
PUBLIC_BASE_URL=