--- 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