# Integración con WhatsApp Es la parte del sistema con más piezas fuera de nuestro control. Buena parte de la configuración vive **en Meta**, no en la base de datos, y eso explica varios comportamientos que de otro modo parecen inexplicables. ## Dos números, una misma cuenta El laboratorio opera con dos líneas sobre la misma cuenta de WhatsApp Business (WABA): | Canal | Configuración | Para qué | |---|---|---| | Principal | `whatsapp_phone_number_id` | Bot de atención general | | Turnero | `whatsapp_phone_number_id_turnero` | Consentimientos, encuestas y avisos de turno | Se elige al construir el servicio: ```php $wa = new WhatsAppService(); // línea principal $wa = new WhatsAppService('turnero'); // línea del turnero ``` > Si un mensaje sale por el número equivocado, casi siempre es porque se instanció sin el canal. Es el mismo WABA y el mismo token: **lo único que cambia es el `phone_number_id`**. ## Configuración Todo en `system_config`: | Clave | Qué es | |---|---| | `whatsapp_token` | Token de acceso a la API | | `whatsapp_api_url` | URL base de la Cloud API | | `whatsapp_business_account_id` | Identificador del WABA | | `whatsapp_phone_number_id` | Número principal | | `whatsapp_phone_number_id_turnero` | Número del turnero | | `webhook_verify_token` | Verificación del webhook | ## Plantillas: la parte que no controlamos Para escribir primero a alguien (fuera de la ventana de 24 horas) hay que usar una **plantilla aprobada por Meta**. `message_templates` guarda una copia local, pero **la copia no manda**: la versión real está en Meta. Esto tiene una consecuencia importante y poco intuitiva: > **Las URL de los botones viven en la plantilla, no en nuestro código.** La plantilla `consentimiento_turno_v2` tiene un botón así: ``` https://erp.laboratorioximenacaicedo.com/form_cliente.php?t={{1}} ``` Nuestro código solo envía el token como `{{1}}`. Cambiar el código **no cambia** el enlace que recibe el paciente: hay que editar la plantilla en el WhatsApp Manager de Meta y esperar la reaprobación. El único lugar donde sí armamos la URL completa es el **respaldo en texto plano**, que se usa cuando falla el envío por plantilla (`modules/turnero/api/send_consentimiento.php`). ## Por qué el enlace pasa por dos páginas El botón apunta a `form_cliente.php?t=`, pero el consentimiento del turnero lo muestra `ver_formulario_enviado.php?token=`. `form_cliente.php` detecta que el token tiene formato UUID —o sea, que viene del turnero— y redirige. Convive así porque la plantilla ya estaba aprobada apuntando a la página de envíos, y cambiarla obliga a otra ronda de aprobación en Meta. ## Términos y condiciones Antes de conversar, el bot exige aceptar los términos. El usuario responde **ACEPTO** o **NO ACEPTO**. La URL del documento está escrita en **dos lugares** y hay que cambiarlos juntos: | Dónde | Rol | |---|---| | `terms_versions.documento_url` | El bot la adjunta al final del mensaje | | `system_config.terms_message` | Va escrita dentro del texto de bienvenida | Se vuelve a pedir la aceptación si: nunca aceptó, pasaron más de 6 meses, o hay una versión nueva con `forzar_reenvio`. ## El webhook Meta envía los mensajes entrantes al webhook, que los registra y se los pasa a `BotService`. Ahí se decide si responde el bot automático o queda para un operador humano, según el estado de la conversación y el horario de atención (`BusinessHoursService`). ## Qué revisar cuando algo falla | Síntoma | Dónde mirar primero | |---|---| | El mensaje sale por el número equivocado | Que se haya pasado `'turnero'` al constructor | | Un enlace llega roto o apunta mal | La plantilla en Meta, no el código | | No llega ninguna plantilla | Estado de aprobación en el WhatsApp Manager | | Falla el envío pero llega un texto plano | Es el respaldo actuando: la plantilla falló | | El bot no responde | `webhook_logs`, y el horario de atención |