template-saas/docs/01-modulos/SAAS-014-whatsapp.md
rckrdmrd 50a821a415
Some checks failed
CI / Backend CI (push) Has been cancelled
CI / Frontend CI (push) Has been cancelled
CI / Security Scan (push) Has been cancelled
CI / CI Summary (push) Has been cancelled
[SIMCO-V38] feat: Actualizar a SIMCO v3.8.0
- HERENCIA-SIMCO.md actualizado con directivas v3.7 y v3.8
- Actualizaciones de configuracion

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-10 08:53:08 -06:00

410 lines
9.7 KiB
Markdown

---
id: "SAAS-014"
title: "WhatsApp Business API"
type: "Module"
status: "Published"
priority: "P2"
module: "whatsapp"
version: "1.0.0"
created_date: "2026-01-10"
updated_date: "2026-01-10"
---
# SAAS-014: WhatsApp Business API
## Metadata
| Campo | Valor |
|-------|-------|
| Codigo | SAAS-014 |
| Modulo | WhatsApp |
| Prioridad | P2 |
| Estado | Completado |
| Fase | 5 - Integraciones |
| Sprint | Sprint 5 |
| Fecha Implementacion | 2026-01-10 |
| Ultima Actualizacion | 2026-01-10 |
---
## Descripcion
Integracion con WhatsApp Business API (Meta Cloud API) para envio de mensajes y notificaciones via WhatsApp. Permite a los tenants configurar su cuenta de WhatsApp Business y enviar mensajes de texto o templates pre-aprobados a sus usuarios.
---
## Objetivos
1. Proporcionar un canal adicional de comunicacion para notificaciones
2. Permitir configuracion por tenant de credenciales WhatsApp
3. Soportar envio de mensajes de texto y templates
4. Implementar tracking de estado de entrega
5. Aplicar rate limiting por tenant
---
## Alcance
### Incluido
- Configuracion de credenciales WhatsApp Business por tenant
- Envio de mensajes de texto simples
- Envio de templates pre-aprobados por Meta
- Webhook para recibir status de entrega (sent, delivered, read, failed)
- Rate limiting configurable por tenant
- Historial de mensajes enviados
- Pagina de configuracion en portal admin
- Integracion con sistema de notificaciones existente
### Excluido
- Chatbots interactivos
- Mensajes multimedia (imagenes, videos, documentos)
- Grupos de WhatsApp
- Recepcion de mensajes entrantes (solo outbound)
- Flujos conversacionales
---
## Modelo de Datos
### Schema: whatsapp
#### Tabla: whatsapp_configs
| Columna | Tipo | Descripcion |
|---------|------|-------------|
| id | uuid | PK, generado |
| tenant_id | uuid | FK a tenants.id |
| phone_number_id | varchar(50) | ID del numero en Meta |
| waba_id | varchar(50) | WhatsApp Business Account ID |
| access_token | text | Token de acceso (encriptado) |
| is_active | boolean | Si la integracion esta activa |
| rate_limit_per_minute | integer | Limite de mensajes por minuto |
| webhook_verify_token | varchar(100) | Token para verificar webhooks |
| created_at | timestamp | Fecha de creacion |
| updated_at | timestamp | Fecha de actualizacion |
**Indices:**
- `idx_whatsapp_configs_tenant` ON (tenant_id)
- `UNIQUE` ON (tenant_id) - Solo una config por tenant
**RLS:** Si, filtrado por tenant_id
#### Tabla: whatsapp_messages
| Columna | Tipo | Descripcion |
|---------|------|-------------|
| id | uuid | PK, generado |
| tenant_id | uuid | FK a tenants.id |
| config_id | uuid | FK a whatsapp_configs.id |
| to_phone | varchar(20) | Numero destino (formato E.164) |
| message_type | enum | 'text', 'template' |
| template_name | varchar(100) | Nombre del template (si aplica) |
| template_language | varchar(10) | Idioma del template (ej: 'es_MX') |
| content | text | Contenido del mensaje |
| status | enum | 'pending', 'sent', 'delivered', 'read', 'failed' |
| wamid | varchar(100) | WhatsApp Message ID |
| sent_at | timestamp | Cuando se envio |
| delivered_at | timestamp | Cuando se entrego |
| read_at | timestamp | Cuando se leyo |
| error_code | varchar(20) | Codigo de error si fallo |
| error_message | text | Mensaje de error si fallo |
| metadata | jsonb | Metadata adicional |
| created_at | timestamp | Fecha de creacion |
**Indices:**
- `idx_whatsapp_messages_tenant` ON (tenant_id)
- `idx_whatsapp_messages_status` ON (status)
- `idx_whatsapp_messages_wamid` ON (wamid)
- `idx_whatsapp_messages_created` ON (created_at DESC)
**RLS:** Si, filtrado por tenant_id
### Enums
```sql
CREATE TYPE whatsapp.message_status AS ENUM (
'pending',
'sent',
'delivered',
'read',
'failed'
);
CREATE TYPE whatsapp.message_type AS ENUM (
'text',
'template'
);
CREATE TYPE whatsapp.message_direction AS ENUM (
'outbound',
'inbound' -- Para uso futuro
);
```
---
## Endpoints API
### Configuracion
| Metodo | Ruta | Descripcion |
|--------|------|-------------|
| GET | `/whatsapp/config` | Obtener configuracion actual del tenant |
| POST | `/whatsapp/config` | Crear/actualizar configuracion |
| PUT | `/whatsapp/config` | Actualizar configuracion |
| DELETE | `/whatsapp/config` | Desactivar integracion |
### Mensajes
| Metodo | Ruta | Descripcion |
|--------|------|-------------|
| POST | `/whatsapp/send` | Enviar mensaje |
| POST | `/whatsapp/test` | Enviar mensaje de prueba |
| GET | `/whatsapp/messages` | Listar historial de mensajes |
| GET | `/whatsapp/messages/:id` | Obtener detalle de mensaje |
### Webhook
| Metodo | Ruta | Descripcion |
|--------|------|-------------|
| GET | `/whatsapp/webhook` | Verificacion de webhook (Meta challenge) |
| POST | `/whatsapp/webhook` | Recibir eventos de Meta (delivery status) |
---
## DTOs
### CreateConfigDto
```typescript
export class CreateWhatsAppConfigDto {
@IsString()
phoneNumberId: string;
@IsString()
wabaId: string;
@IsString()
accessToken: string;
@IsOptional()
@IsNumber()
@Min(1)
@Max(100)
rateLimitPerMinute?: number = 30;
}
```
### SendMessageDto
```typescript
export class SendWhatsAppMessageDto {
@IsString()
@Matches(/^\+[1-9]\d{1,14}$/)
to: string; // Formato E.164
@IsEnum(['text', 'template'])
type: 'text' | 'template';
@IsOptional()
@IsString()
text?: string;
@IsOptional()
@IsString()
templateName?: string;
@IsOptional()
@IsString()
templateLanguage?: string = 'es_MX';
@IsOptional()
@IsArray()
templateParams?: string[];
}
```
---
## Flujo de Envio
```
1. Usuario llama POST /whatsapp/send
2. Validar credenciales del tenant
3. Verificar rate limit
4. Crear registro en whatsapp_messages (status: pending)
5. Llamar Meta Cloud API
6. Actualizar status a 'sent' con wamid
7. Meta envia webhook con delivery status
8. Actualizar status (delivered/read/failed)
```
---
## Implementacion Backend
### Estructura de Archivos
```
apps/backend/src/modules/whatsapp/
├── whatsapp.module.ts
├── whatsapp.service.ts
├── whatsapp.controller.ts
├── whatsapp-webhook.controller.ts
├── entities/
│ ├── whatsapp-config.entity.ts
│ └── whatsapp-message.entity.ts
├── dto/
│ ├── create-config.dto.ts
│ ├── update-config.dto.ts
│ ├── send-message.dto.ts
│ └── index.ts
└── __tests__/
└── whatsapp.service.spec.ts
```
### Configuracion Requerida
Variables de entorno:
```env
# WhatsApp no requiere variables globales
# Cada tenant configura sus propias credenciales via API
```
---
## Implementacion Frontend
### Archivos
```
apps/frontend/src/
├── pages/admin/
│ └── WhatsAppSettings.tsx
├── hooks/
│ └── useWhatsApp.ts
├── services/
│ └── whatsapp.api.ts
└── components/whatsapp/
└── WhatsAppTestMessage.tsx
```
### Pagina de Configuracion
`WhatsAppSettings.tsx` incluye:
- Formulario de configuracion de credenciales
- Switch para activar/desactivar
- Boton para enviar mensaje de prueba
- Tabla de historial de mensajes recientes
- Indicador de estado de conexion
---
## Rate Limiting
| Plan | Mensajes/Minuto | Mensajes/Dia |
|------|-----------------|--------------|
| Free | 10 | 100 |
| Starter | 30 | 1,000 |
| Pro | 60 | 5,000 |
| Enterprise | Custom | Custom |
El rate limiting se aplica por tenant usando el campo `rate_limit_per_minute` de la configuracion.
---
## Integracion con Notifications
WhatsApp se integra como un canal adicional en el modulo de notificaciones:
```typescript
// En notifications.service.ts
async sendNotification(options: NotificationOptions) {
// ... otros canales ...
if (options.channels.includes('whatsapp') && options.phone) {
await this.whatsappService.send({
to: options.phone,
type: 'template',
templateName: options.template,
templateParams: options.params
});
}
}
```
---
## Seguridad
1. **Tokens encriptados**: El access_token se almacena encriptado en la base de datos
2. **Webhook verification**: Se verifica el token de Meta antes de procesar eventos
3. **RLS**: Todas las tablas tienen Row-Level Security por tenant_id
4. **Rate limiting**: Previene abuso y costos excesivos
---
## Dependencias
| Modulo | Tipo | Descripcion |
|--------|------|-------------|
| SAAS-002 (Tenants) | Requerido | tenant_id en configs y messages |
| SAAS-007 (Notifications) | Opcional | Canal adicional de notificacion |
| SAAS-005 (Plans) | Requerido | Limites por plan |
---
## Entregables
- [x] Schema DDL `whatsapp` con 2 tablas
- [x] 3 enums (message_status, message_type, message_direction)
- [x] WhatsAppModule backend con service y controllers
- [x] 2 entidades TypeORM
- [x] DTOs de configuracion y envio
- [x] Webhook handler para Meta
- [x] Pagina WhatsAppSettings.tsx
- [x] Hook useWhatsApp.ts
- [x] API client whatsapp.api.ts
- [x] 22 tests unitarios
---
## Criterios de Aceptacion
- [x] Configuracion de credenciales por tenant funciona
- [x] Envio de mensajes de texto exitoso
- [x] Envio de templates exitoso
- [x] Webhook recibe y procesa status correctamente
- [x] Rate limiting previene exceso de mensajes
- [x] Historial de mensajes accesible en UI
- [x] Mensaje de prueba funciona desde configuracion
---
## Referencias
- [Meta WhatsApp Business API Documentation](https://developers.facebook.com/docs/whatsapp/cloud-api)
- [Sprint 5 Plan](../../orchestration/planes/PLAN-SPRINT-5-WHATSAPP.md)
- [SAAS-007-notifications.md](./SAAS-007-notifications.md)
---
**Ultima actualizacion:** 2026-01-10
**Autor:** Claude Code (Reestructuracion Documental)