Saltar al contenido principal
Nivel: Avanzado · Etiquetas: WhatsApp, Cloud API, Webhooks, Seguridad, Plantillas Funcionalidades: Provider de la Cloud API de WhatsApp (@botmesh/meta: ingest, verifyChallenge, appSecret) · Ventana de 24 h y plantillas (OutsideSessionWindowError, kind: 'template') · Enviar fuera de un handler (bot.send) · Flujos (.ask con validate) · Seguridad · Apagado ordenado · Simulador en la terminal

Requisitos previos

  • Node.js 22.12 o superior y un proyecto ESM ("type": "module"), como en Inicio rápido.
  • Una app de Meta con el producto WhatsApp: un token de acceso, el id del número de teléfono, el app secret y un verify token que eliges tú. Una plantilla aprobada llamada order_shipped, en español, con un parámetro en el cuerpo.
  • Una URL pública HTTPS que llegue al puerto 3000 (un proxy inverso, o un túnel mientras desarrollas).

El servidor completo

Cómo funciona

1. El bot es una fábrica

La conversación vive en createBot, que recibe su provider. npx botmesh dev server.js importa la fábrica e inyecta el simulador de la terminal, así que iteras sobre las respuestas sin Meta, tokens ni URL pública. La conexión con la Cloud API solo corre bajo isMainModule (paso 5).

2. Bytes crudos, nunca JSON re-serializado

Meta firma exactamente los bytes que envía con tu app secret (X-Hub-Signature-256). readRawBody los junta en un Buffer, con un límite de 1 MiB, y provider.ingest(raw, req.headers) comprueba la firma antes de parsear. Parsear el body y volver a serializarlo (lo que hace un body parser de JSON) cambia los bytes y la firma deja de coincidir: no pongas express.json() ni nada parecido delante del webhook.

3. La ventana de 24 horas

En la Cloud API, los mensajes libres solo llegan a un usuario dentro de las 24 horas siguientes a su último mensaje. Fuera de ella, Meta rechaza el envío con el error 131047, que el provider convierte en OutsideSessionWindowError; entonces el servidor envía la plantilla aprobada order_shipped, que siempre está permitida. Para que el provider lleve la cuenta de la ventana, ponga el mensaje en cola y lo reintente cuando el usuario responda, configura su opción sessionWindow.

4. Las rutas

ingest() vuelve nada más despachar los eventos, así que Meta recibe su 200 al momento mientras los handlers corren. El token de administración se compara en tiempo constante y la ruta solo acepta 4 KiB.

5. Ponerlo en marcha

env() detiene el proceso al arrancar con una línea clara cuando falta una variable, en vez de un error del provider más tarde. appSecret activa la comprobación de firma: nunca despliegues sin él (ni pongas allowUnsignedWebhooks). Con SIGTERM el servidor deja de aceptar webhooks (Meta reintenta lo que no pudo entregar) y el bot drena las respuestas en curso. @botmesh/server empaqueta el mismo ingress con límites de concurrencia, timeouts y adaptadores para Express, Fastify y Hono: mira Servidor de webhooks.

Transcripción de ejemplo

La conversación, capturada con npx botmesh dev server.js:
En la Cloud API, las mismas respuestas salen por la Graph API.

Ejecutarlo en WhatsApp

En el panel de la app de Meta, pon como URL de callback https://<tu-dominio>/webhook con el mismo verify token y suscríbete al campo messages. Después escribe al número de empresa desde WhatsApp y llama a la ruta de aviso desde tu backend:

Siguientes pasos