michangarrito/docs/02-integraciones/INT-001-whatsapp-meta.md
rckrdmrd 97f407c661 [MIGRATION-V2] feat: Migrar michangarrito a estructura v2
- Prefijo v2: MCH
- TRACEABILITY-MASTER.yml creado
- Listo para integracion como submodulo

Workspace: v2.0.0 | SIMCO: v4.0.0
2026-01-10 11:28:54 -06:00

345 lines
9.2 KiB
Markdown

---
id: INT-001
type: Integration
title: "WhatsApp Meta Business API"
provider: "WhatsApp/Meta"
status: Activo
integration_type: "messaging"
created_at: 2026-01-04
updated_at: 2026-01-10
simco_version: "3.8.0"
tags:
- whatsapp
- messaging
- webhooks
- multi-tenant
---
# INT-001: WhatsApp Meta Business API
## Metadata
| Campo | Valor |
|-------|-------|
| **Codigo** | INT-001 |
| **Proveedor** | Meta (Facebook) |
| **Tipo** | Comunicacion |
| **Estado** | Implementado |
| **Multi-tenant** | Si |
| **Fecha integracion** | 2026-01-06 |
| **Ultimo update** | 2026-01-10 |
| **Owner** | Backend Team |
---
## 1. Descripcion
WhatsApp Business API es el canal principal de comunicacion de MiChangarrito. Permite a los duenos de tiendas interactuar con el sistema mediante mensajes de texto y voz.
**Casos de uso principales:**
- Recibir consultas de ventas, inventario y ganancias
- Procesar comandos via chat (agregar producto, registrar venta)
- Recibir pedidos de clientes
- Enviar notificaciones y recordatorios
- Procesar mensajes de voz (transcripcion via Whisper)
---
## 2. Credenciales Requeridas
### Variables de Entorno
| Variable | Descripcion | Tipo | Obligatorio |
|----------|-------------|------|-------------|
| `WHATSAPP_PHONE_NUMBER_ID` | ID del numero de telefono en Meta | string | SI |
| `WHATSAPP_ACCESS_TOKEN` | Token de acceso a la API | string | SI |
| `WHATSAPP_VERIFY_TOKEN` | Token para verificar webhooks | string | SI |
| `WHATSAPP_APP_SECRET` | Secret para validar firma de webhooks | string | SI |
| `WHATSAPP_WEBHOOK_URL` | URL del webhook (para referencia) | string | NO |
### Ejemplo de .env
```env
# WhatsApp Business API
WHATSAPP_PHONE_NUMBER_ID=123456789012345
WHATSAPP_ACCESS_TOKEN=EAABxxxxxxxxxxxxxxx
WHATSAPP_VERIFY_TOKEN=michangarrito_verify_2026
WHATSAPP_APP_SECRET=xxxxxxxxxxxxxxxxxxxxxxxxx
```
### Obtencion de Credenciales
1. Crear cuenta en [Meta for Developers](https://developers.facebook.com/)
2. Crear App de tipo "Business"
3. Agregar producto "WhatsApp Business Platform"
4. Configurar numero de telefono de prueba
5. Generar Access Token permanente
6. Configurar Webhook URL
---
## 3. Endpoints/SDK Utilizados
### Operaciones Implementadas
| Operacion | Metodo | Endpoint | Descripcion |
|-----------|--------|----------|-------------|
| Enviar mensaje texto | POST | `/v17.0/{phone_id}/messages` | Mensaje de texto simple |
| Enviar mensaje template | POST | `/v17.0/{phone_id}/messages` | Mensaje con template aprobado |
| Enviar mensaje interactivo | POST | `/v17.0/{phone_id}/messages` | Botones, listas |
| Marcar como leido | POST | `/v17.0/{phone_id}/messages` | Mark as read |
| Descargar media | GET | `/{media_id}` | Obtener URL de audio/imagen |
### SDK/Cliente Utilizado
```typescript
// No se usa SDK oficial, cliente HTTP custom
import { HttpService } from '@nestjs/axios';
const WHATSAPP_API_URL = 'https://graph.facebook.com/v17.0';
async sendMessage(phoneNumber: string, text: string) {
return this.httpService.post(
`${WHATSAPP_API_URL}/${process.env.WHATSAPP_PHONE_NUMBER_ID}/messages`,
{
messaging_product: 'whatsapp',
to: phoneNumber,
type: 'text',
text: { body: text }
},
{
headers: {
Authorization: `Bearer ${process.env.WHATSAPP_ACCESS_TOKEN}`
}
}
);
}
```
---
## 4. Rate Limits
| Limite | Valor | Periodo | Accion si excede |
|--------|-------|---------|------------------|
| Mensajes iniciados por negocio | 1,000 | por 24h (tier basico) | Esperar o upgrade tier |
| Mensajes de respuesta | Ilimitados | 24h ventana | N/A |
| Requests API | 200 | por segundo | Retry con backoff |
### Estrategia de Retry
```typescript
const delays = [1000, 2000, 4000];
for (let attempt = 0; attempt < 3; attempt++) {
try {
return await this.sendMessage(phone, text);
} catch (error) {
if (error.response?.status === 429) {
await sleep(delays[attempt]);
continue;
}
throw error;
}
}
```
---
## 5. Manejo de Errores
### Codigos de Error
| Codigo | Descripcion | Accion Recomendada | Retry |
|--------|-------------|-------------------|-------|
| 400 | Formato de mensaje invalido | Validar payload | NO |
| 401 | Token invalido o expirado | Regenerar token | NO |
| 403 | Numero no registrado | Verificar numero | NO |
| 429 | Rate limit excedido | Backoff exponencial | SI |
| 500 | Error de Meta | Retry 3 veces | SI |
### Ejemplo de Manejo
```typescript
try {
await whatsappService.sendMessage(phone, message);
} catch (error) {
this.logger.error('WhatsApp error', {
service: 'whatsapp',
operation: 'sendMessage',
code: error.response?.data?.error?.code,
message: error.response?.data?.error?.message,
tenantId: context.tenantId,
});
// Guardar en cola para reintento
await this.queue.add('whatsapp-retry', { phone, message });
}
```
---
## 6. Fallbacks
### Estrategia de Fallback
| Escenario | Fallback | Tiempo maximo |
|-----------|----------|---------------|
| API caida | Cola Redis para reintentar | 24 horas |
| Rate limited | Throttle + prioridad | 1 hora |
| Token expirado | Alerta admin | Inmediato |
### Modo Degradado
Si WhatsApp no esta disponible:
- Mensajes se encolan en Redis
- Usuario puede usar app movil/web
- Notificaciones push como alternativa
---
## 7. Multi-tenant
### Modelo de Credenciales
- [x] **Por Tenant:** Cada tenant puede configurar su numero de WhatsApp
- [x] **Global con fallback:** Numero compartido si tenant no tiene propio
### Almacenamiento
```sql
-- En schema messaging
CREATE TABLE messaging.tenant_whatsapp_config (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
tenant_id UUID REFERENCES auth.tenants(id) NOT NULL,
phone_number_id VARCHAR(50) NOT NULL,
access_token TEXT NOT NULL, -- Encriptado
is_active BOOLEAN DEFAULT true,
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
UNIQUE(tenant_id)
);
```
### Contexto en Llamadas
```typescript
async sendMessageForTenant(tenantId: UUID, phone: string, text: string) {
const config = await this.getWhatsAppConfig(tenantId);
// Usar config del tenant o fallback a global
const phoneNumberId = config?.phone_number_id || process.env.WHATSAPP_PHONE_NUMBER_ID;
const accessToken = config?.access_token || process.env.WHATSAPP_ACCESS_TOKEN;
return this.send(phoneNumberId, accessToken, phone, text);
}
```
---
## 8. Webhooks
### Endpoints Registrados
| Evento | Endpoint Local | Descripcion |
|--------|----------------|-------------|
| `messages` | `/webhooks/whatsapp` | Mensajes entrantes |
| `message_status` | `/webhooks/whatsapp` | Estado de entrega |
### Validacion de Webhooks
```typescript
function verifyWebhookSignature(payload: string, signature: string): boolean {
const expected = crypto
.createHmac('sha256', process.env.WHATSAPP_APP_SECRET)
.update(payload)
.digest('hex');
return signature === `sha256=${expected}`;
}
```
### Configuracion en Meta
1. Meta Dashboard → WhatsApp → Configuration
2. Webhook URL: `https://api.michangarrito.com/webhooks/whatsapp`
3. Verify Token: `WHATSAPP_VERIFY_TOKEN`
4. Suscribir a: `messages`, `message_status`
---
## 9. Testing
### Modo Sandbox/Test
| Ambiente | Credenciales | Datos |
|----------|--------------|-------|
| Sandbox | Test phone number | Mensajes a numeros verificados |
| Production | Business verified | Mensajes a cualquier numero |
### Numeros de Prueba
En sandbox, solo se pueden enviar mensajes a numeros registrados en Meta Dashboard.
### Comandos de Test
```bash
# Test de conexion
curl -X POST \
"https://graph.facebook.com/v17.0/${PHONE_NUMBER_ID}/messages" \
-H "Authorization: Bearer ${ACCESS_TOKEN}" \
-H "Content-Type: application/json" \
-d '{"messaging_product":"whatsapp","to":"521234567890","type":"text","text":{"body":"Test"}}'
# Test de webhook local
curl -X POST http://localhost:3143/webhooks/whatsapp \
-H "Content-Type: application/json" \
-d '{"object":"whatsapp_business_account","entry":[{"changes":[{"value":{"messages":[{"from":"521234567890","text":{"body":"Hola"}}]}}]}]}'
```
---
## 10. Monitoreo
### Metricas a Monitorear
| Metrica | Descripcion | Alerta |
|---------|-------------|--------|
| Latencia | Tiempo de respuesta API | > 3s |
| Error Rate | % de requests fallidos | > 5% |
| Messages Sent | Mensajes enviados por hora | < 10 (posible caida) |
| Webhook Delay | Tiempo entre evento y procesamiento | > 10s |
### Logs Estructurados
```typescript
this.logger.info('WhatsApp message sent', {
service: 'whatsapp',
operation: 'sendMessage',
tenantId: context.tenantId,
messageId: result.messages[0].id,
to: phone,
duration: durationMs,
});
```
---
## 11. Referencias
### Documentacion Oficial
- [WhatsApp Business Platform](https://developers.facebook.com/docs/whatsapp/cloud-api)
- [Webhooks Reference](https://developers.facebook.com/docs/whatsapp/cloud-api/webhooks)
- [Message Types](https://developers.facebook.com/docs/whatsapp/cloud-api/messages)
### Modulos Relacionados
- [WhatsApp Service](../../apps/whatsapp-service/)
- [Messaging Module](../../apps/backend/src/modules/messaging/)
- [Arquitectura Multi-Tenant](../90-transversal/ARQUITECTURA-MULTI-TENANT-INTEGRACIONES.md)
### Soporte
- Meta Business Help: https://business.facebook.com/help
---
**Ultima actualizacion:** 2026-01-10
**Autor:** Backend Team