Files
whatsapp/modules/soporte/docs/tecnica/40-whatsapp-bot.md
T
Lizandro GuarnizoandClaude Opus 5 32c209710c Documentación completa del proyecto en el módulo Soporte
21 documentos en cuatro secciones, escritos sobre el comportamiento real del
sistema —incluidos los casos que costaron diagnosticar esta semana.

Manual de usuario (visible para todos): primeros pasos, recepción, toma de
muestras, portal del enfermero y administración. Orientado a tareas concretas,
no a describir pantallas.

Documentación técnica: índice de módulos, turnero, formularios y firma digital,
WhatsApp y bot, domicilios, webhook (migrado de WEBHOOK_ENDPOINTS.md) e
inventario de endpoints.

Arquitectura: visión general, enrutamiento y registro de módulos, roles y
permisos, modelo de datos, integración con WhatsApp, y decisiones tomadas con
su deuda técnica asociada.

Operación: runbook de incidentes ordenado por síntoma, configuraciones críticas
—incluido qué vive en Meta y no en la base— y despliegue.

Se documentan explícitamente las trampas conocidas: role/role_id que hay que
mantener sincronizados, las columnas can_* que el control de acceso no lee, las
URL de plantilla que no se cambian desde el código, y las columnas históricas
que quedaron en NULL sin forma de recuperarlas.

README_DOCS.md apunta al módulo y explica cómo agregar páginas.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-04 10:14:32 -05:00

3.2 KiB

WhatsApp y bot

El sistema nació como bot de WhatsApp y esa integración sigue siendo central.

Servicios

{{servicios}}

WhatsAppService

Envuelve la Cloud API de Meta. Se elige la línea al construirlo:

$wa = new WhatsAppService();           // principal
$wa = new WhatsAppService('turnero');  // turnero

Ambas líneas comparten cuenta (WABA) y token; lo único que cambia es el phone_number_id. Si un mensaje sale por la línea equivocada, casi siempre falta el argumento.

Métodos principales:

$wa->sendTextMessage($telefono, $texto, $meta);
$wa->sendTemplateMessage($telefono, $plantilla, $idioma, [], [], $componentes, $meta);

$meta acompaña el registro del mensaje: ['canal' => 'turnero', 'operator_id' => adminId()].

Plantillas

Fuera de la ventana de 24 horas hay que usar plantilla aprobada. message_templates guarda una copia local con sus components, pero la copia no manda: la versión real vive en Meta.

Consecuencia importante:

Las URL de los botones están en la plantilla, no en el código. Nuestro código solo envía los parámetros ({{1}}). Cambiar el código no altera el enlace que recibe el paciente.

Ejemplo — botón de consentimiento_turno_v2:

https://erp.laboratorioximenacaicedo.com/form_cliente.php?t={{1}}

Y así se arman los componentes al enviar:

$rawComps = [
    ['type' => 'body',   'parameters' => [['type' => 'text', 'text' => $codigo]]],
    ['type' => 'button', 'sub_type' => 'url', 'index' => '0',
     'parameters' => [['type' => 'text', 'text' => $token]]],
];

Respaldo

Si el envío por plantilla falla, se manda un texto plano con el enlace armado desde el dominio del servidor. Ese texto no pasa por Meta, así que su URL puede diferir de la del botón.

BotService

Decide qué hacer con cada mensaje entrante:

  1. ¿Aceptó los términos? Si no, se los pide y no avanza.
  2. ¿Está en horario? (BusinessHoursService)
  3. ¿La conversación la tomó un operador humano? El bot no interrumpe.
  4. Si no, responde según el estado de la conversación (ConversationStateService) y el menú (MenuService).

Términos y condiciones

Tabla Contenido
terms_versions Versión activa, URL del documento, mensajes
terms_acceptance Historial de aceptaciones
system_config.terms_message Texto de bienvenida, repite la URL dentro

Se vuelve a pedir la aceptación si nunca aceptó, si pasaron más de 6 meses, o si hay versión nueva con forzar_reenvio.

La URL del documento está en dos lugares. Cambiar solo uno deja al otro sirviendo un enlace viejo.

Configuración

Todo en system_config: whatsapp_token, whatsapp_api_url, whatsapp_business_account_id, whatsapp_phone_number_id, whatsapp_phone_number_id_turnero, webhook_verify_token.

Diagnóstico

Síntoma Dónde mirar
Sale por el número equivocado Falta 'turnero' en el constructor
Enlace roto en un botón La plantilla en Meta
No llega ninguna plantilla Estado de aprobación en WhatsApp Manager
Llega texto plano en vez de plantilla El respaldo actuó: la plantilla falló
El bot no responde webhook_logs, horario, estado de la conversación