Cómo Integrar y Mantener la API de WhatsApp Business en tu Aplicación PHP (XAMPP)

En este artículo encontrarás la documentación completa, con datos ficticios, de todos los pasos y archivos necesarios para:

  • Renovar automáticamente el token de WhatsApp Business
  • Configurar tu helper de envío para usar ese token
  • Ajustar el panel de configuración para almacenar Client ID, Client Secret, Phone Number ID y Access Token
  • Probar y validar el flujo de notificaciones por WhatsApp

1. Estructura de la Base de Datos

Creamos una tabla configuraciones_panel para centralizar todas las opciones (SMTP, Telegram, WhatsApp, etc.). Ejemplo de DDL:

CREATE TABLE `configuraciones_panel` (
  `clave_config` varchar(100) NOT NULL,
  `valor_config` text DEFAULT NULL,
  `descripcion_config` varchar(255) DEFAULT NULL,
  `tipo_dato` enum('string','integer','float','boolean','color','text','json') NOT NULL DEFAULT 'string',
  `grupo_config` varchar(50) DEFAULT 'General',
  `fecha_modificacion` timestamp NULL DEFAULT CURRENT_TIMESTAMP() 
    ON UPDATE CURRENT_TIMESTAMP(),
  PRIMARY KEY (`clave_config`),
  KEY `idx_grupo_config` (`grupo_config`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

Valores ficcticios para ser cambiados por tus datos reales:

INSERT INTO `configuraciones_panel`
  (`clave_config`,             `valor_config`,                     `descripcion_config`,                                        `tipo_dato`,   `grupo_config`)
VALUES
  ('whatsapp_client_id',       '098765432101234',                 'ID de la App de Facebook (Client ID)',                     'string',      'Notificaciones'),
  ('whatsapp_client_secret',   'abc123FakeSecretXYZ',             'Client Secret de la App de Facebook para WhatsApp',        'string',      'Notificaciones'),
  ('whatsapp_api_instancia_id','123456789012345',                 'Phone Number ID para la API de WhatsApp Business',         'string',      'Notificaciones'),
  ('whatsapp_api_token',       'EAAIACFakeLongTokenForTesting...', 'Access Token inicial de la API de WhatsApp (short-lived).', 'text',        'Notificaciones'),
  ('whatsapp_api_version',     'v21.0',                            'Versión de la Graph API para WhatsApp',                    'string',      'Notificaciones'),
  ('whatsapp_token_last_renew_at','2025-12-01 02:00:00',           'Fecha de última renovación de token.',                      'string',      'Notificaciones');

2. Script de Renovación Automática del Token

Para evitar errores de “session invalid” o tokens caducados, creamos un script PHP que:

  1. Lee el token, Client ID y Client Secret de la BD.
  2. Llama a Facebook Graph /oauth/access_token con grant_type=fb_exchange_token.
  3. Almacena el nuevo token y la fecha en la BD.

2.1 Archivo: includes/renew_whatsapp_token.php

 

<?php
// Muestra errores en pantalla (solo en desarrollo)
ini_set('display_errors', 1);
error_reporting(E_ALL);

 

// 1) Conexión PDO
require_once __DIR__ . '/db_conexion.php';

 

// 2) Leer credenciales desde BD
$sql = "
  SELECT clave_config, valor_config
    FROM configuraciones_panel
   WHERE clave_config IN (
     'whatsapp_api_token',
     'whatsapp_client_id',
     'whatsapp_client_secret'
   )
";
$stmt   = $pdo->query($sql);
$config = $stmt->fetchAll(PDO::FETCH_KEY_PAIR);

 

$currentToken = trim($config['whatsapp_api_token']     ?? '');
$clientId     = trim($config['whatsapp_client_id']     ?? '');
$clientSecret = trim($config['whatsapp_client_secret'] ?? '');

 

if (!$currentToken || !$clientId || !$clientSecret) {
    echo "❌ Faltan credenciales en BD. Verifica whatsapp_api_token, whatsapp_client_id o whatsapp_client_secret.\n";
    exit(1);
}

 

// 3) Construir URL de renovación
$params = http_build_query([
    'grant_type'        => 'fb_exchange_token',
    'client_id'         => $clientId,
    'client_secret'     => $clientSecret,
    'fb_exchange_token' => $currentToken
]);
$url = "https://graph.facebook.com/{$config['whatsapp_api_version']}/oauth/access_token?{$params}";

 

// 4) Ejecutar cURL
$ch       = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_TIMEOUT, 15);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);

 

$data = json_decode($response, true);

 

// 5) Procesar respuesta
if ($httpCode === 200 && !empty($data['access_token'])) {
    $newToken = $data['access_token'];
    $now      = date('Y-m-d H:i:s');

 

    try {
        $pdo->beginTransaction();

 

        // Actualizar token
        $stmt1 = $pdo->prepare("
          UPDATE configuraciones_panel
             SET valor_config = :tok
           WHERE clave_config = 'whatsapp_api_token'
        ");
        $stmt1->execute([':tok' => $newToken]);

 

        // Actualizar timestamp
        $stmt2 = $pdo->prepare("
          UPDATE configuraciones_panel
             SET valor_config = :ts
           WHERE clave_config = 'whatsapp_token_last_renew_at'
        ");
        $stmt2->execute([':ts' => $now]);

 

        $pdo->commit();
        echo "✅ Token renovado y guardado con éxito ({$now}).\n";
        exit(0);
    } catch (Exception $e) {
        $pdo->rollBack();
        echo "❌ Error guardando en BD: " . $e->getMessage() . "\n";
        exit(1);
    }
} else {
    $err = $data['error']['message'] ?? $response;
    echo "❌ Error al renovar token (HTTP {$httpCode}): {$err}\n";
    exit(1);
}

 

2.2 Programar la tarea en Windows

  • Abre Programador de Tareas (taskschd.msc).
  • Crear tarea → Nombre: “Renovar Token WhatsApp”.
  • Desencadenadores: cada 20 horas.
  • Acciones:
    • Programa: C:\xampp\php\php.exe
    • Argumentos: -f "C:\xampp\htdocs\ejemplo\includes\renew_whatsapp_token.php"
    • Iniciar en: C:\xampp\htdocs\ejemplo\includes

Así, el script se ejecutará automáticamente y mantendrá el token siempre vigente.

 

3. Ajustes en el Helper de Envío (whatsapp_helper.php)

Quitamos la lógica interna de renovación por hora y dejamos que solo lea el token actualizado en la BD.

 

function obtenerTokenWhatsAppValido(PDO $pdo, array &$config) {
    $stmt = $pdo->query("
      SELECT clave_config, valor_config
        FROM configuraciones_panel
       WHERE clave_config LIKE 'whatsapp_%'
    ");
    while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
        $config[$row['clave_config']] = $row['valor_config'];
    }
    return $config['whatsapp_api_token'] ?? false;
}

Las funciones de envío (enviarWhatsAppNotificacionDeuda, _enviarPayloadWhatsApp, etc.) permanecen idénticas, usando el token que esta función devuelve.

4. Corrección y Formulario de Configuración

En configuracion/index.php ajustamos:

  1. Mapa genérico $config_map_guardado:
    • Eliminamos la línea de whatsapp_client_secret para que no se machaque con valor vacío.
  2. Bloque independiente para procesar whatsapp_client_secret solo si el usuario ingresa un valor:

// Después del loop genérico:
if (!empty(trim($_POST['whatsapp_client_secret']))) {
    $nuevo = trim($_POST['whatsapp_client_secret']);
    $sql = "INSERT INTO configuraciones_panel
              (clave_config,valor_config,tipo_dato,grupo_config,descripcion_config)
            VALUES
              ('whatsapp_client_secret',:val,'string','Notificaciones','Client Secret de la App WhatsApp')
            ON DUPLICATE KEY UPDATE
              valor_config = :val, fecha_modificacion = CURRENT_TIMESTAMP()";
    $s = $pdo->prepare($sql);
    $s->execute([':val' => $nuevo]);
}

 

Fragmento HTML

<h6 class="text-info">Configuración API de WhatsApp</h6>
<div class="form-check form-switch mb-3">
  <input class="form-check-input" type="checkbox"
    id="whatsapp_notificaciones_habilitadas"
    name="whatsapp_notificaciones_habilitadas" value="1"
    <?= $whatsapp_notificaciones_habilitadas ? 'checked' : '' ?>>
  <label class="form-check-label" for="whatsapp_notificaciones_habilitadas">
    Habilitar Notificaciones por WhatsApp</label>
</div>

<div class="row">
  <div class="col-md-6 mb-3">
    <label for="whatsapp_client_id">Client ID (App ID)</label>
    <input type="text" id="whatsapp_client_id" name="whatsapp_client_id"
      class="form-control"
      value="<?= htmlspecialchars($whatsapp_client_id) ?>">
  </div>
  <div class="col-md-6 mb-3">
    <label for="whatsapp_client_secret">Client Secret (App Secret)</label>
    <input type="password" id="whatsapp_client_secret"
      name="whatsapp_client_secret" class="form-control"
      placeholder="Dejar en blanco para no cambiar">
    <small class="form-text text-muted">
      Ingrese solo para actualizar el Client Secret.</small>
  </div>
</div>

<div class="row">
  <div class="col-md-6 mb-3">
    <label for="whatsapp_api_instancia_id">Phone Number ID</label>
    <input type="text" id="whatsapp_api_instancia_id"
      name="whatsapp_api_instancia_id" class="form-control"
      value="<?= htmlspecialchars($whatsapp_api_instancia_id) ?>">
  </div>
  <div class="col-md-6 mb-3">
    <label for="whatsapp_api_version">Versión API</label>
    <input type="text" id="whatsapp_api_version"
      name="whatsapp_api_version" class="form-control"
      value="<?= htmlspecialchars($whatsapp_api_version) ?>">
  </div>
</div>

<div class="mb-3">
  <label for="whatsapp_api_token">Token de Acceso Inicial</label>
  <textarea id="whatsapp_api_token" name="whatsapp_api_token"
    class="form-control" rows="2"
    placeholder="Token short-lived inicial"><?= htmlspecialchars($whatsapp_api_token) ?></textarea>
</div>

Con esto, el panel permitirá configurar Client ID, Client Secret (solo si se ingresa), Phone Number ID, API Version y el token inicial.

5. Flujo Completo de Envío de Notificaciones

  1. El Programador de Tareas renueva el token cada 20 horas.
  2. Tu helper obtenerTokenWhatsAppValido() lee el token largo almacenado.
  3. Al invocar:

enviarWhatsAppNotificacionDeuda(
  $config_whatsapp,
  '5491123456789',              // Número de cliente ficticio
  ['nombre_cliente'=>'ACME','monto_total_adeudado'=>150.75,'monedas_adeudadas'=>'USD']
);

6. Pruebas y Verificación

  • Ejecuta manualmente http://localhost/ejemplo/includes/renew_whatsapp_token.php para ver en pantalla:

✅ Token renovado y guardado con éxito (2025-12-08 14:00:02).

SELECT clave_config, valor_config 
  FROM configuraciones_panel 
 WHERE clave_config='whatsapp_api_token'
   OR clave_config='whatsapp_token_last_renew_at';

En el panel de config, modifica solo el Client Secret y guarda; confirma que en BD cambia solo si hubo texto en el password.

Conclusión

Con esta implementación:

  • Garantizas que tu token de WhatsApp Business siempre esté vigente, sin interrupciones.
  • Mantienes un helper de envío sencillo, enfocado sólo en construir el payload y llamar a la API.
  • Permites al administrador del sistema actualizar Client ID, Client Secret, Phone Number ID, API Version y Token inicial desde un formulario centralizado.
  • Usas tecnología estándar (PHP + MySQL + Windows Task Scheduler) sin dependencias externas complejas.

¡Listo para integrar notificaciones de WhatsApp Business de principio a fin en tu proyecto local o en producción!

 

Tags: Tags php xampp whatsapp-business-api token-renewal notifications mysql tutorial programación whatsapp api
27 vistas

Artículos Relacionados