Cómo recibir notificaciones de un formulario por Telegram con PHP

Si ya tienes un bot de Telegram creado con PHP, hay un uso que es casi obligatorio: que te avise al instante cuando alguien llena tu formulario de contacto, en lugar de tener que estar revisando el correo (o la carpeta de spam, donde muchas veces terminan estos avisos).

En este artículo vamos a construir eso: un formulario de contacto simple en PHP que, al enviarse, te manda un mensaje a Telegram con los datos de la persona que escribió.

Recibir notificaciones de un formulario con Telegram PHP
Recibir notificaciones de un formulario con Telegram PHP

Lo bueno de este caso es que no necesitas webhook. El webhook es para cuando el bot tiene que recibir mensajes de un usuario. Aquí es al revés: tu servidor le habla a la API de Telegram para enviarte un aviso, así que es una llamada saliente simple, sin necesidad de registrar nada adicional en BotFather.

Requisitos

  • Un bot de Telegram ya creado (con su token). Si no lo tienes, mira el artículo de cómo crear tu primer bot con BotFather.
  • Un servidor con PHP y la extensión cURL habilitada (viene activada por defecto en la mayoría de hostings).
  • Tu chat_id, que vamos a obtener en el siguiente paso.

Paso 1: Obtener tu Chat ID

El token identifica al bot, pero para enviarte un mensaje a ti necesitamos tu chat_id. Se obtiene así:

  1. Abre una conversación con tu bot y mándale cualquier mensaje (por ejemplo “hola”).
  2. Desde el navegador, visita esta URL reemplazando tu token:
https://api.telegram.org/bot<TU_TOKEN>/getUpdates
  1. En la respuesta JSON busca el bloque "chat":{"id": ... }. Ese número es tu chat_id.
{
  "result": [
    {
      "message": {
        "chat": {
          "id": 123456789,
          "first_name": "Tu Nombre"
        },
        "text": "hola"
      }
    }
  ]
}

Guarda ese número, lo vamos a usar en la configuración.

Paso 2: El formulario de contacto

Un formulario simple, sin dependencias externas:

<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<title>Contacto</title>
</head>
<body>

<h1>Contáctanos</h1>

<form action="procesar.php" method="POST">
    <label for="nombre">Nombre</label>
    <input type="text" id="nombre" name="nombre" required>

    <label for="email">Email</label>
    <input type="email" id="email" name="email" required>

    <label for="mensaje">Mensaje</label>
    <textarea id="mensaje" name="mensaje" rows="5" required></textarea>

    <!-- Honeypot anti-spam: invisible para humanos, los bots lo suelen rellenar -->
    <input type="text" name="website" style="display:none" tabindex="-1" autocomplete="off">

    <button type="submit">Enviar mensaje</button>
</form>

</body>
</html>

El campo website es un honeypot: un input oculto que ningún humano ve ni llena, pero que los bots de spam suelen rellenar automáticamente. Si llega lleno, sabemos que es spam y descartamos el envío sin procesarlo.

Paso 3: La función para notificar a Telegram

Esta es la pieza reutilizable — la puedes usar en este formulario y en cualquier otro caso de negocio que quieras notificar (citas, pedidos, stock bajo):

<?php
/**
 * Envía un mensaje a un chat de Telegram usando la API oficial.
 *
 * @param string $token   Token del bot (de BotFather)
 * @param string $chatId  Chat ID de destino
 * @param string $mensaje Texto a enviar (admite HTML básico: <b>, <i>, etc.)
 * @return array|false    Respuesta decodificada de Telegram, o false si falló
 */
function notificarTelegram($token, $chatId, $mensaje)
{
    $url = "https://api.telegram.org/bot{$token}/sendMessage";

    $ch = curl_init($url);
    curl_setopt($ch, CURLOPT_POST, true);
    curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query([
        'chat_id'    => $chatId,
        'text'       => $mensaje,
        'parse_mode' => 'HTML',
    ]));
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_TIMEOUT, 10);

    $respuesta = curl_exec($ch);
    $error     = curl_error($ch);
    curl_close($ch);

    if ($error) {
        error_log('Error enviando notificación a Telegram: ' . $error);
        return false;
    }

    return json_decode($respuesta, true);
}

Usamos cURL en lugar de file_get_contents (que sí usamos en el artículo del bot base) porque aquí queremos manejar errores de red de forma más prolija — si Telegram no responde, no debería romper el formulario para el usuario.

Paso 4: El procesador del formulario

Aquí juntamos todo: validación de los datos, el honeypot, y el envío de la notificación.

<?php
require_once 'config.php';
require_once 'notificar_telegram.php';

// Honeypot: si este campo viene lleno, es un bot rellenando el formulario
if (!empty($_POST['website'])) {
    exit;
}

$nombre  = trim($_POST['nombre'] ?? '');
$email   = trim($_POST['email'] ?? '');
$mensaje = trim($_POST['mensaje'] ?? '');

// Validaciones básicas
if (empty($nombre) || empty($email) || empty($mensaje)) {
    die('Por favor completa todos los campos.');
}

if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
    die('El email no es válido.');
}

// Armamos el mensaje que le va a llegar a tu Telegram
$textoTelegram = "📩 <b>Nuevo mensaje de contacto</b>\n\n"
               . "<b>Nombre:</b> " . htmlspecialchars($nombre) . "\n"
               . "<b>Email:</b> " . htmlspecialchars($email) . "\n"
               . "<b>Mensaje:</b>\n" . htmlspecialchars($mensaje) . "\n\n"
               . "🕒 " . date('d/m/Y H:i');

notificarTelegram(TELEGRAM_TOKEN, TELEGRAM_CHAT_ID, $textoTelegram);

// Aquí también podrías guardar el mensaje en base de datos o enviarlo por
// email como respaldo, en caso de que la notificación a Telegram falle.

echo 'Gracias, tu mensaje fue enviado correctamente. Te responderemos pronto.';

Y el archivo de configuración, separado para que nunca subas el token por accidente a un repositorio público:

<?php
/**
 * Configuración del bot de Telegram para notificaciones.
 * Reemplaza estos valores por los tuyos.
 */

// Token que te dio BotFather al crear el bot
define('TELEGRAM_TOKEN', 'TU_TOKEN_AQUI');

// Tu chat_id (obtenido en el Paso 1)
define('TELEGRAM_CHAT_ID', 'TU_CHAT_ID_AQUI');

Descargar

Puedes descargar los 4 archivos completos y listos para subir a tu servidor en el paquete adjunto a este artículo (telegram-formulario-php.zip).

Solo tienes que reemplazar el token y el chat_id en config.php.

⬇ Descargar ejemplo (telegram-formulario-php.zip)

Probándolo

Con los 4 archivos (index.html, procesar.php, notificar_telegram.php, config.php) en la misma carpeta de tu servidor:

  1. Reemplaza TU_TOKEN_AQUI y TU_CHAT_ID_AQUI en config.php con tus datos reales.
  2. Abre index.html desde tu navegador.
  3. Llena el formulario y envíalo.
  4. En segundos deberías recibir el mensaje en tu Telegram.

A diferencia del bot con webhook (que sí necesita HTTPS y un servidor público, porque es Telegram quien tiene que poder alcanzarlo), aquí es tu servidor el que llama hacia afuera a la API de Telegram. Eso significa que puedes probar este ejemplo en cualquier entorno donde PHP y cURL puedan salir a internet:

  • En un servidor con dominio público, tal cual, sin nada extra.
  • En localhost, con XAMPP, Laragon, MAMP o el servidor embebido de PHP (php -S localhost:8000) — mientras tu máquina tenga salida a internet, la notificación llega igual.
  • En un formulario dentro de tu red local (por ejemplo, un servidor casero o de oficina sin salida pública), siempre que ese equipo tenga acceso a internet para alcanzar api.telegram.org.

Lo único que no funciona sin HTTPS público es el webhook del bot (el que recibe mensajes). Para notificaciones salientes como esta, no aplica esa restricción.

Ideas para otros proyectos

  • Guardar también en base de datos, no solo notificar — así tienes respaldo aunque falle Telegram.
  • Enviar también un correo como respaldo, usando el mismo patrón que con notificarTelegram().
  • Adaptar el mismo patrón a otros casos de negocio: avisos de stock bajo, confirmación de pedidos, nuevas reservas — la función notificarTelegram() es la misma, solo cambia el mensaje que arma cada caso.
  • Si tu formulario recibe mucho spam a pesar del honeypot, puedes sumarle un captcha simple antes de procesar.

Leave a Reply

Your email address will not be published. Required fields are marked *

Discover more from Evilnapsis

Subscribe now to keep reading and get access to the full archive.

Continue reading