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

9.2 KiB

id type title provider status integration_type created_at updated_at simco_version tags
INT-001 Integration WhatsApp Meta Business API WhatsApp/Meta Activo messaging 2026-01-04 2026-01-10 3.8.0
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

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

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

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

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

  • Por Tenant: Cada tenant puede configurar su numero de WhatsApp
  • Global con fallback: Numero compartido si tenant no tiene propio

Almacenamiento

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

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

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

# 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

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

Modulos Relacionados

Soporte


Ultima actualizacion: 2026-01-10 Autor: Backend Team