Runbook — WhatsApp incidents
Sesión de una empresa cae (status=logged_out)
php yii whatsapp/status <empresa_id>para confirmar estado- El admin debe entrar a
/configuracion/canales/whatsappy re-escanear QR - Si el cliente reporta no haber recibido email: verificar
views/mail/whatsapp/session-disconnected.phpyempresas.admin_email
Webhook genérico devolviendo 401
- Verificar que
whatsapp_sessions.webhook_secretcoincida con el secret en la URL del cliente - Si rotaron secret: el cliente debe actualizar la URL en su integración
Queue Bull stuck
redis-cli LLEN bull:whatsapp-sends:wait # jobs pendientes
redis-cli LLEN bull:whatsapp-sends:failed # jobs fallidos
pm2 logs excucha-wa # ver errores recientes
Si el Node está caído: pm2 restart excucha-wa.
Número baneado por WhatsApp
Síntomas: connection.update con statusCode=403 o 405. Mitigación:
- Reducir
daily_capde la empresa (UPDATE whatsapp_sessions SET daily_cap=100 WHERE empresa_id=X) - Documentar al cliente que pruebe con otro número
- Largo plazo: considerar migrar al WhatsApp Business API oficial (out of scope actual)
Restart limpio del Node
pm2 stop excucha-wa
pm2 start ecosystem.config.js
pm2 logs excucha-wa --lines 50
Las sesiones se re-hidratan automáticamente en boot (sessionManager.rehydrateAll).
Auth state corrupto en una empresa
UPDATE whatsapp_sessions SET auth_state = NULL, status = 'disconnected' WHERE empresa_id = X;
Luego pedir al admin re-escanear QR.
Smoke test E2E (post-deploy)
- Iniciar Node service
cd whatsapp-service && cp .env.example .env # editar valores reales npm install npm run dev - Verificar health:
curl http://localhost:3001/health→{ok:true, sessions_active:0} - Conectar empresa de test:
- Login como admin de empresa #1
- Ir a
/configuracion/canales/whatsapp - Click "Conectar" → escanear QR con un WhatsApp de prueba
- Verificar status →
connected
- Envío manual:
- POST
/api/v1/envios/whatsappcon{telefono: "+57...", encuesta_id: 1} - Verificar que llega el WhatsApp al teléfono
- Verificar
whatsapp_envios.statusevoluciona:queued → sent → delivered → read
- POST
- Webhook trigger:
- Copiar webhook URL del panel
- cURL POST con
envio_id_externo: "smoke-1"→ debe responder 202 - Reintento mismo
envio_id_externo→ 202 conduplicate:true
- Auto-reply: responder al WhatsApp recibido → verificar fila en
whatsapp_inbound_logconauto_replied=1y mensaje guía recibido - Reconexión: desde el teléfono cerrar WhatsApp Web → verificar status
logged_out+ email recibido - PM2 production:
pm2 start ecosystem.config.js && pm2 save