Skip to main content

Módulo WhatsApp

src/app/modules/whatsapp/

Canal whatsapp-qr: sesión de WhatsApp Web mediante la librería Baileys (baileys). Esta página documenta lo verificado en la rama feat/meta_connections; los cambios de esa rama sobre el módulo son: cifrado compartido, mensajes de contactos compartidos, citas (respuestas), bloqueo por contacto y envío por el router saliente común.

Estados de sesión​

whatsapp.constants.ts — WHATSAPP_SESSION_STATE: init, qr, connecting, connected, disconnected, logged_out. El estado fino se refleja en connection.whatsappConfig.sessionState (escrito solo por WhatsappSessionManager); connection.status mantiene sus 3 valores. Reconexión: backoff de 2 s a 60 s, máximo 8 intentos (WHATSAPP_RECONNECT).

Endpoints​

Base /api/v1/connections/whatsapp. Todos con @Auth() + PermissionsGuard; solo operan sobre conexiones whatsapp-qr del tenant.

MétodoRutaPermisoDescripción
POST/connections/whatsapp/:id/startCONNECTION_UPDATEInicia la sesión; devuelve { sessionState, qr }
DELETE/connections/whatsapp/:id/logoutCONNECTION_DELETECierra sesión
GET/connections/whatsapp/:id/statusCONNECTION_READ{ sessionState, qr, phoneJid }

El QR y los cambios de estado también se difunden por socket al usuario que pidió el inicio (WhatsappBroadcastWiringService).

Persistencia cifrada de la sesión​

Las credenciales y claves Signal se guardan cifradas (AES-256-GCM) con WHATSAPP_SESSION_ENCRYPTION_KEY:

  • WhatsappSession.creds y WhatsappSessionKey.value usan EncryptedEnvelopeSchema (core/crypto/encrypted-envelope.model.ts).
  • auth/mongo-auth-state.ts cifra/descifra con encryptSecret / decryptSecret de Crypto.
  • Cambio de esta rama: se eliminó whatsapp/auth/session-encryption.ts y whatsapp/models/whatsapp-encrypted-envelope.model.ts; ahora el código es compartido con Meta.

Entrada (inbound)​

services/whatsapp-inbound.service.ts:

  • Toma el lock por contacto (InboundLockService.withContactLock(tenantId, jid, …)) para no duplicar tickets.
  • Usa el pipeline compartido ingestInbound (ver Message).
  • Contactos compartidos: helpers/incoming-contact.helper.ts (resolveIncomingContacts) lee contactMessage / contactsArrayMessage y su vCard (waid o TEL) y produce sharedContacts: { name, phone }[], que se guarda en el mensaje. No aplica a mensajes ver-una-vez ni ubicaciones.
  • Citas: helpers/quoted-message.helper.ts extrae contextInfo.stanzaId para enlazar parentId con el mensaje citado.
  • helpers/incoming-media.helper.ts descarga y guarda adjuntos (imagen, video, audio, documento) y incoming-location.helper.ts procesa ubicaciones.

Salida (outbound)​

services/whatsapp-outbound.dispatcher.ts implementa OutboundDispatcher y se registra en OutboundDispatcherRegistry como el único dispatcher del canal whatsapp-qr. Es invocado por OutboundRouterService (ver Message).

Variables de entorno​

VariableUso
WHATSAPP_SESSION_ENCRYPTION_KEYObligatoria. Clave base64 de 32 bytes para cifrar la sesión

Gotchas​

  • Si cambia WHATSAPP_SESSION_ENCRYPTION_KEY, las sesiones guardadas dejan de poder descifrarse (la autenticación GCM falla) y hay que re-vincular el QR.
  • La clave de WhatsApp y la de Meta deben ser distintas.