📅 BookingApp
Del anuncio de Meta a la reunión en Google Meet, con recordatorios automáticos por WhatsApp
Escala del Proyecto
Descripción General
Un negocio que capta clientes con publicidad en Facebook e Instagram tiene un problema de continuidad: el anuncio genera el interés, pero entre el clic y la reunión efectiva se pierde la mitad de los leads. Alguien tiene que llamar, cuadrar agenda, crear la videollamada y recordarla.
BookingApp automatiza toda esa cadena. El usuario llega desde el anuncio a una landing de cuatro pasos, rellena sus datos, ve el calendario con la disponibilidad real, elige hora y confirma. En ese instante el sistema crea la sala de Google Meet, envía la confirmación por WhatsApp y registra todo.
Después vienen los recordatorios: uno 24 horas antes y otro 2 horas antes, este último con el enlace directo a la videollamada. Un cron se encarga de enviarlos. El panel de administración cierra el círculo con KPIs, gestión de citas, configuración de horario semanal, días bloqueados y el log de todos los mensajes enviados.
Tecnologías Utilizadas
PHP 8.1+
MySQL 8
PDO Singleton
Twilio WhatsApp
Google Calendar API
Meta Webhook
Cron
AJAX
Módulos Principales
Formulario de cuatro pasos con barra de progreso, calendario con disponibilidad en tiempo real por AJAX y diseño mobile-first sin dependencias externas.
Recibe los leads en tiempo real verificando la firma HMAC-SHA256, y asocia automáticamente los datos del lead a la cita.
Crea la sala de reunión al confirmar la cita mediante la API de Google Calendar, e incluye el enlace en los recordatorios.
Confirmación inmediata, recordatorio a 24 horas y recordatorio a 2 horas con el enlace de Meet. Todo queda registrado.
KPIs en tiempo real: citas de hoy, de la semana, confirmadas y leads recibidos.
Listado con filtros por estado, fecha y búsqueda, con acciones de cancelar y completar desde la propia tabla.
Horario semanal configurable día por día, con interruptores y duración de los tramos.
Excepciones puntuales para festivos y vacaciones, o para habilitar días extra.
Historial completo de los mensajes de WhatsApp enviados.
cron/reminders.php recorre las citas próximas y dispara los
avisos correspondientes.
Arquitectura
Aplicación PHP plana con separación clara entre la parte pública, el panel privado,
las integraciones y el cron. La conexión a base de datos se resuelve con un
Singleton PDO en db.php, y cada integración externa
está encapsulada en su propio fichero de includes/ para que se pueda
sustituir sin tocar el flujo de reserva.
booking-app/ ├── index.php # landing con calendario ├── get_slots.php # AJAX: tramos disponibles ├── process_booking.php # confirmación de la reserva ├── confirm.php ├── webhook.php # receptor de Meta Lead Ads ├── db.php # conexión PDO Singleton ├── includes/ │ ├── whatsapp.php # Twilio WhatsApp API │ ├── google_meet.php # Google Calendar API │ ├── helpers.php # CSRF, formateo │ └── auth_check.php # middleware del panel ├── admin/ # login, dashboard, citas, disponibilidad ├── cron/reminders.php # recordatorios automáticos └── sql/schema.sql
Base de Datos
7 tablas. La separación entre horario recurrente y excepciones puntuales es lo que permite configurar "los martes de 10 a 14" y a la vez bloquear un martes concreto sin romper la regla general.
| Tabla | Contenido |
|---|---|
| admin_users | Usuarios del panel de administración |
| leads | Leads recibidos desde Meta y Facebook Ads |
| appointments | Citas agendadas con todos sus datos y su enlace de Meet |
| availability_schedule | Horario recurrente por día de la semana |
| availability_exceptions | Días bloqueados o habilitados de forma puntual |
| notification_logs | Registro de todos los mensajes de WhatsApp enviados |
Integraciones Externas
Envío de la confirmación inmediata y de los dos recordatorios. Cada mensaje
queda registrado en notification_logs.
Creación automática de la sala de Google Meet en el momento de confirmar la cita.
Webhook que recibe los leads de Facebook e Instagram Ads en tiempo real, con verificación de firma.
Ejecución programada de cron/reminders.php, protegida contra
acceso web sin clave secreta.
Del Anuncio a la Reunión
- Clic en el anuncio: el usuario llega a la landing con su
lead_idde Meta en la URL. - Datos personales: primer paso del formulario: nombre, email y teléfono.
- Elección de día: el calendario muestra los días con disponibilidad real.
- Elección de hora: una llamada AJAX a
get_slots.phpdevuelve los tramos libres de ese día. - Confirmación: al confirmar se crea la sala de Google Meet, se envía la confirmación por WhatsApp y se registra todo en base de datos.
- Recordatorio a 24 horas: el cron detecta la cita del día siguiente y envía el aviso.
- Recordatorio a 2 horas: segundo aviso, esta vez con el enlace directo a Google Meet.
- Gestión: desde el panel se marca la cita como completada o cancelada.
Seguridad Implementada
- Verificación HMAC-SHA256 de la firma en el webhook de Meta: sin firma válida no se procesa nada.
- Token CSRF de sesión en todos los formularios.
- Prepared statements en todas las consultas.
session_regenerate_id()en el login para evitar fijación de sesión.- Contraseñas con
password_hash()y bcrypt. - Retardo de 1 segundo en los intentos de login fallidos como freno al ataque por fuerza bruta.
- El cron está protegido contra ejecución por web sin clave secreta.
config.phpygoogle_tokens.jsonexcluidos del repositorio.
Retos Técnicos y Decisiones de Diseño
Disponibilidad real, no un calendario decorativo
Mostrar todos los tramos y descubrir al confirmar que ya estaba ocupado es la peor
experiencia posible. El calendario consulta la disponibilidad por AJAX contra
get_slots.php, que cruza el horario recurrente con las excepciones y
con las citas ya existentes. Lo que se muestra es lo que hay.
Horario recurrente frente a excepciones
Modelar la agenda como una lista de huecos concretos obliga a generarlos con meses
de antelación. Separar availability_schedule — la regla semanal — de
availability_exceptions — el caso puntual — permite decir "los martes
de 10 a 14" una sola vez y luego bloquear un martes de agosto sin tocar la regla.
Tres integraciones que pueden fallar en el peor momento
En la confirmación conviven tres servicios externos. Si Google falla, la cita no debe perderse; si Twilio falla, la reserva sigue siendo válida. Cada integración está aislada en su fichero, y el log de notificaciones permite ver exactamente qué se envió y qué no, en lugar de suponerlo.
Verificar el webhook antes de confiar en él
Un endpoint público que crea registros es una invitación. La verificación HMAC-SHA256 de la firma de Meta es lo que separa recibir leads de recibir basura: sin firma válida, la petición se descarta antes de tocar la base de datos.
Mi Rol
Desarrollador full stack — autor único.
Modelo de datos, landing multipaso, motor de disponibilidad, las tres integraciones
externas, el cron de recordatorios, el panel de administración y la documentación de
configuración en SETUP.md.
Estado del Proyecto
Marcado como listo para producción en el repositorio. Requiere PHP 8.1+, MySQL 8, acceso a cron y cuentas de Twilio, Google Cloud y Meta for Developers. Licencia MIT.
Código y Enlaces
La configuración detallada de las tres integraciones está en SETUP.md.
Las credenciales viven en config.php, excluido del control de
versiones.