- HERENCIA-SIMCO.md actualizado con directivas v3.7 y v3.8 - Actualizaciones de configuracion Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
410 lines
9.7 KiB
Markdown
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)
|