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étodo | Ruta | Permiso | Descripción |
|---|---|---|---|
POST | /connections/whatsapp/:id/start | CONNECTION_UPDATE | Inicia la sesión; devuelve { sessionState, qr } |
DELETE | /connections/whatsapp/:id/logout | CONNECTION_DELETE | Cierra sesión |
GET | /connections/whatsapp/:id/status | CONNECTION_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.credsyWhatsappSessionKey.valueusanEncryptedEnvelopeSchema(core/crypto/encrypted-envelope.model.ts).auth/mongo-auth-state.tscifra/descifra conencryptSecret/decryptSecretde Crypto.- Cambio de esta rama: se eliminó
whatsapp/auth/session-encryption.tsywhatsapp/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) leecontactMessage/contactsArrayMessagey su vCard (waidoTEL) y producesharedContacts: { name, phone }[], que se guarda en el mensaje. No aplica a mensajes ver-una-vez ni ubicaciones. - Citas:
helpers/quoted-message.helper.tsextraecontextInfo.stanzaIdpara enlazarparentIdcon el mensaje citado. helpers/incoming-media.helper.tsdescarga y guarda adjuntos (imagen, video, audio, documento) yincoming-location.helper.tsprocesa 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
| Variable | Uso |
|---|---|
WHATSAPP_SESSION_ENCRYPTION_KEY | Obligatoria. 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.