1. Introducción
Telegram permite desarrollar bots capaces de recibir mensajes, procesar órdenes y responder automáticamente a los usuarios. Mediante su API oficial, es posible conectar un bot con una página web y utilizarlo como herramienta de automatización, monitorización o asistencia técnica.
En esta guía se explica cómo crear un bot de Telegram con PHP y conectarlo a cualquier página web que disponga de un alojamiento compatible con PHP y HTTPS. El procedimiento es aplicable a WordPress, páginas web desarrolladas a medida, servidores virtuales, hosting compartido y otros entornos que permitan ejecutar scripts PHP.
El ejemplo desarrollado implementa un bot privado que reconoce tres órdenes:
hola: comprueba que el bot responde correctamente.estado: muestra la versión de PHP y el estado básico del servicio.ejecuta fecha: devuelve la fecha y la hora del servidor.
El sistema utiliza un webhook para que Telegram envíe las actualizaciones a una dirección HTTPS de la página web. El código comprueba un secreto de autenticación, limita el acceso a un usuario autorizado y devuelve las respuestas mediante la API de Telegram.
Además, se explican los pasos necesarios para activar y desactivar el webhook, administrar el bot desde Telegram, diagnosticar errores y ampliar la funcionalidad sin comprometer la seguridad del servidor.
2. ¿Cómo funciona un bot de Telegram conectado a una web?
Un bot de Telegram no necesita ejecutarse continuamente en un ordenador. Puede utilizar un servidor web que procese las solicitudes recibidas cuando Telegram comunica una nueva actualización.
La arquitectura está formada por cuatro componentes:
- Telegram: recibe los mensajes enviados al bot.
- Webhook: una dirección HTTPS de la página web a la que Telegram envía las actualizaciones.
- PHP: procesa las solicitudes, comprueba los permisos y genera las respuestas.
- API de Telegram: permite que el código PHP envíe mensajes al chat correspondiente.
El flujo de comunicación es el siguiente:
Usuario → Telegram → webhook de la web → código PHP → API de Telegram → respuesta al usuario.
Por ejemplo, cuando un usuario autorizado envía hola, Telegram transmite el mensaje al archivo PHP configurado como webhook. El script comprueba el secreto de la petición y el identificador del remitente. Si la solicitud está autorizada, genera la respuesta y la envía mediante la API de Telegram.
No es necesario mantener una conexión abierta entre el navegador y Telegram ni ejecutar un proceso permanente en el alojamiento. El servidor web procesa las peticiones que recibe.
3. Requisitos previos
Antes de comenzar, necesitas los siguientes elementos.
3.1. Una cuenta de Telegram
Debes disponer de una cuenta de Telegram para crear el bot, administrarlo y realizar las pruebas.
Puedes utilizar Telegram en el móvil, en el ordenador o mediante su versión web.
3.2. Un alojamiento web compatible con PHP
El alojamiento debe permitir ejecutar scripts PHP y exponer una URL pública mediante HTTPS.
Puede tratarse de un hosting compartido, un VPS, un servidor dedicado, una instalación propia o un alojamiento administrado.
3.3. Un dominio con HTTPS
La dirección del webhook debe ser accesible desde los servidores de Telegram.
En los ejemplos se utilizará:
https://www.tudominio.com/tg_webhook.php
Sustituye www.tudominio.com por tu dominio y adapta la ruta a la ubicación real del archivo.
El certificado TLS debe ser válido. Si utilizas una URL que redirige a otra dirección, comprueba que la URL definitiva funciona correctamente.
3.4. Extensiones de PHP
El código utiliza PHP 8 o posterior y requiere las extensiones mbstring y json. Para enviar mensajes, utiliza cURL cuando está disponible y una alternativa basada en streams de PHP cuando no lo está.
La disponibilidad de las extensiones depende del proveedor y de la versión de PHP seleccionada.
3.5. Acceso para subir archivos
Puedes utilizar cualquiera de estos métodos, según las posibilidades de tu alojamiento:
- Administrador de archivos del panel de hosting.
- FTP o SFTP.
- SSH y herramientas de terminal.
- Sistema de despliegue de tu proyecto.
- Herramientas de administración de archivos de WordPress, cuando permitan trabajar de forma segura con los archivos PHP.
No necesitas utilizar todos los métodos. Basta con disponer de una forma de instalar los archivos en el servidor.
4. Crear el bot desde Telegram con BotFather
4.1. Abrir BotFather
En Telegram, busca @BotFather o accede directamente a:
BotFather es la herramienta oficial que permite crear y configurar bots de Telegram.
Comprueba que estás hablando con la cuenta oficial antes de realizar operaciones de administración.
4.2. Crear un nuevo bot
Envía el siguiente mensaje:
/newbot
BotFather solicitará dos datos.
Nombre del bot
Es el nombre visible que aparecerá en Telegram. Puedes elegir, por ejemplo:
Asistente Web PHP
Nombre de usuario
Debe ser único y terminar en bot. Por ejemplo:
asistente_web_php_bot
Si el nombre está disponible, BotFather creará el bot y mostrará un token de acceso.
4.3. Guardar el token
El token es una credencial que permite utilizar la API en nombre del bot. Debe tratarse como una contraseña.
No lo publiques en WordPress, GitHub, foros, capturas de pantalla ni registros de errores.
Si ya has compartido un token real, revócalo y genera uno nuevo desde las opciones de administración del bot en BotFather antes de continuar.
4.4. Configurar la descripción del bot
Puedes personalizar el perfil utilizando los comandos de BotFather:
| Comando | Función |
|---|---|
/setdescription | Establece la descripción del bot. |
/setabouttext | Configura el texto informativo del perfil. |
/setuserpic | Permite cambiar la imagen del bot. |
/setcommands | Configura el menú de comandos. |
/mybots | Muestra los bots administrados y sus opciones. |
Para el ejemplo, puedes registrar este menú mediante /setcommands:
start - Iniciar el bot
hola - Comprobar funcionamiento
estado - Consultar estado
fecha - Consultar fecha del servidor
Debes seleccionar el bot correspondiente y enviar la lista cuando BotFather la solicite.
Importante: configurar el menú no programa las acciones. Para que /estado o /fecha funcionen, también deben estar implementados en el código PHP.
5. Obtener el identificador del usuario autorizado
En este ejemplo, el bot estará restringido a un único usuario.
Para ello se necesita el identificador numérico de Telegram, que no debe confundirse con el nombre de usuario.
Puedes obtenerlo mediante un bot de consulta de identificadores, como @userinfobot, verificando que sea el servicio que deseas utilizar. También puedes obtenerlo mediante el campo from.id de una actualización recibida por la API de Telegram.
Un identificador ilustrativo podría ser:
123456789
Debes sustituirlo por el identificador real de tu cuenta.
El código comparará el identificador del remitente con el valor configurado. Si no coincide, ignorará el mensaje.
Esta medida es importante porque conocer el nombre público de un bot permite que otras personas le envíen mensajes. La autorización evita que esos mensajes ejecuten las funciones privadas del ejemplo.
6. Preparar los archivos de la página web
La implementación utiliza dos archivos PHP:
tg_webhook.php
config_telegram.php
El primero contiene la lógica del bot. El segundo almacena las credenciales.
La estructura recomendada es:
proyecto/
├── public/
│ └── tg_webhook.php
└── private/
└── config_telegram.php
La carpeta public representa el directorio accesible desde Internet. La carpeta private debe encontrarse fuera de la raíz pública.
La estructura concreta dependerá del proveedor. En algunos alojamientos, el directorio público se denomina public_html, htdocs, httpdocs o de otra forma.
Si no puedes guardar el archivo de configuración fuera del directorio público, tendrás que protegerlo mediante la configuración del servidor y verificar que no se puede descargar directamente. No des por hecho que un archivo PHP siempre estará protegido: una configuración incorrecta puede exponer su contenido.
7. Crear el archivo de configuración
Crea un archivo denominado config_telegram.php en una ubicación privada del servidor.
Su contenido será:
<?php
declare(strict_types=1);
return [
'token' => 'TOKEN_NUEVO_DE_BOTFATHER',
'user_id' => 'TU_ID_NUMERICO',
'webhook_secret' => 'SECRETO_WEBHOOK_NUEVO',
];
Sustituye los tres valores por tus credenciales reales.
token: token actual del bot proporcionado por BotFather.user_id: identificador numérico del usuario autorizado.webhook_secret: secreto aleatorio utilizado para comprobar las peticiones del webhook.
7.1. Generar un secreto aleatorio
Si dispones de PHP en un terminal, ejecuta:
php -r 'echo bin2hex(random_bytes(32)), PHP_EOL;'
El comando genera un valor hexadecimal de 64 caracteres.
También puedes generar el secreto mediante un generador criptográficamente seguro disponible en tu entorno de administración. No utilices contraseñas previsibles, nombres de usuario ni el propio token del bot.
Guarda el secreto de forma privada y evita publicarlo.
7.2. Proteger el archivo
En un servidor Unix o Linux, si tienes permisos suficientes, puedes restringir los permisos del archivo:
chmod 600 config_telegram.php
Comprueba que el usuario que ejecuta PHP puede leerlo.
Si tu alojamiento no permite modificar permisos mediante SSH, utiliza las opciones del panel de administración o coloca el archivo fuera del directorio público.
La mejor solución es mantener las credenciales fuera de la web pública y no incorporarlas al repositorio del proyecto.
8. Crear el webhook en PHP
Crea el archivo tg_webhook.php dentro del directorio público de la web.
El siguiente código implementa el bot de ejemplo, valida el secreto recibido de Telegram, comprueba el usuario autorizado y envía las respuestas a través de la API oficial.
La ruta del archivo de configuración debe adaptarse a la estructura real de tu alojamiento.
<?php
declare(strict_types=1);
// Adaptar esta ruta a la ubicación privada del archivo.
$config = require dirname(__DIR__) . '/private/config_telegram.php';
$token = $config['token'];
$miId = (string) $config['user_id'];
$secreto = $config['webhook_secret'];
function responder(int $codigo, string $texto): never
{
http_response_code($codigo);
header('Content-Type: text/plain; charset=utf-8');
exit($texto);
}
// Validar el secreto del webhook.
$recibido = $_SERVER[
'HTTP_X_TELEGRAM_BOT_API_SECRET_TOKEN'
] ?? '';
if (
$secreto === '' ||
!hash_equals($secreto, $recibido)
) {
responder(403, 'No autorizado');
}
// Leer la actualización recibida.
$contenido = file_get_contents('php://input');
if ($contenido === false || $contenido === '') {
responder(400, 'Peticion vacia');
}
$update = json_decode($contenido, true);
if (!is_array($update)) {
responder(400, 'JSON no valido');
}
// Este ejemplo procesa mensajes de texto privados.
$mensaje = $update['message'] ?? null;
if (
!is_array($mensaje) ||
!isset(
$mensaje['from']['id'],
$mensaje['chat']['id'],
$mensaje['text']
)
) {
responder(200, 'OK');
}
// Comprobar el usuario autorizado.
if ((string) $mensaje['from']['id'] !== $miId) {
responder(200, 'Ignorado');
}
// Rechazar mensajes que no procedan de un chat privado.
if (($mensaje['chat']['type'] ?? '') !== 'private') {
responder(200, 'Ignorado');
}
$chatId = $mensaje['chat']['id'];
$texto = trim((string) $mensaje['text']);
// Normalizar los comandos que se utilizarán.
$comando = mb_strtolower($texto, 'UTF-8');
switch ($comando) {
case '/start':
$respuesta = "Bot iniciado correctamente.\n"
. "Escribe hola, estado o ejecuta fecha.";
break;
case 'hola':
case '/hola':
$respuesta = '¡Hola! El bot PHP funciona correctamente.';
break;
case 'estado':
case '/estado':
$respuesta = "Bot activo.\n"
. 'PHP: ' . PHP_VERSION . "\n"
. 'Recepción de mensajes: correcta.';
break;
case 'fecha':
case '/fecha':
case 'ejecuta fecha':
$respuesta = 'Fecha del servidor: '
. date('Y-m-d H:i:s T');
break;
default:
$respuesta = "Comandos disponibles:\n"
. "- hola\n"
. "- estado\n"
. "- fecha\n"
. "- ejecuta fecha";
break;
}
// Preparar la petición a Telegram.
$url = "https://api.telegram.org/bot{$token}/sendMessage";
$datos = json_encode([
'chat_id' => $chatId,
'text' => $respuesta,
], JSON_UNESCAPED_UNICODE);
if ($datos === false) {
error_log('No se pudo codificar la respuesta del bot');
responder(200, 'OK');
}
$resultado = false;
$codigoHttp = 0;
if (function_exists('curl_init')) {
$curl = curl_init($url);
curl_setopt_array($curl, [
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => $datos,
CURLOPT_HTTPHEADER => [
'Content-Type: application/json',
],
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CONNECTTIMEOUT => 5,
CURLOPT_TIMEOUT => 10,
]);
$resultado = curl_exec($curl);
$codigoHttp = (int) curl_getinfo(
$curl,
CURLINFO_HTTP_CODE
);
$errorCurl = curl_error($curl);
curl_close($curl);
if ($resultado === false) {
error_log('Error de conexión con Telegram: ' . $errorCurl);
responder(200, 'OK');
}
} else {
$opciones = [
'http' => [
'method' => 'POST',
'header' => "Content-Type: application/json\r\n",
'content' => $datos,
'timeout' => 10,
'ignore_errors' => true,
],
];
$contexto = stream_context_create($opciones);
$resultado = @file_get_contents(
$url,
false,
$contexto
);
if ($resultado === false) {
error_log('Error enviando el mensaje a Telegram');
responder(200, 'OK');
}
// Recuperar el código HTTP de la respuesta.
if (isset($http_response_header[0])) {
if (
preg_match(
'/\s(\d{3})\s/',
$http_response_header[0],
$coincidencias
)
) {
$codigoHttp = (int) $coincidencias[1];
}
}
}
// Comprobar la respuesta JSON de la API.
$datosRespuesta = json_decode(
(string) $resultado,
true
);
if (
$codigoHttp < 200 ||
$codigoHttp >= 300 ||
!is_array($datosRespuesta) ||
($datosRespuesta['ok'] ?? false) !== true
) {
error_log(
'Telegram no confirmó el envío del mensaje. HTTP '
. $codigoHttp
);
}
responder(200, 'OK');
8.1. Adaptar la ruta de configuración
En el ejemplo anterior se utiliza:
$config = require dirname(__DIR__) . '/private/config_telegram.php';
Esta ruta corresponde a una estructura en la que tg_webhook.php se encuentra dentro de public y el archivo de configuración está en private.
Si el alojamiento utiliza otra estructura, modifica la ruta para apuntar a la ubicación real del archivo.
Por ejemplo, si la configuración está en el directorio padre del archivo público, podría utilizarse:
$config = require dirname(__DIR__) . '/config_telegram.php';
No copies una ruta sin comprobar que corresponde a tu instalación.
8.2. Qué hace el código
El script realiza las siguientes operaciones:
- Carga el archivo de configuración.
- Comprueba el secreto enviado en la cabecera HTTP.
- Lee el cuerpo JSON de la actualización.
- Comprueba que se trata de un mensaje de texto.
- Verifica el identificador numérico del remitente.
- Comprueba que el mensaje procede de un chat privado.
- Interpreta el texto recibido.
- Envía una respuesta mediante la API de Telegram.
- Registra un error si la API no confirma el envío.
El código no ejecuta órdenes del sistema operativo. Los mensajes recibidos se interpretan como órdenes predefinidas dentro de un switch.
9. Instalar el bot en cualquier alojamiento web
El procedimiento depende del panel y de las herramientas que ofrezca el proveedor. No es necesario utilizar SSH si puedes subir los archivos y configurar el webhook de otra manera.
9.1. Opción A: administrador de archivos del hosting
Accede al panel de control del proveedor y abre su administrador de archivos.
Localiza el directorio público de la página web y sube:
tg_webhook.php
Después, guarda config_telegram.php fuera del directorio público si el alojamiento lo permite.
Si el administrador de archivos permite acceder a directorios privados, utiliza esa función para mantener separadas las credenciales.
Comprueba que la dirección pública del script coincide con la URL que utilizarás en Telegram.
9.2. Opción B: FTP o SFTP
Si tu proveedor permite transferencia de archivos, puedes utilizar un cliente compatible con FTP o SFTP.
Conecta con las credenciales proporcionadas por el alojamiento y sube el archivo PHP a la ubicación pública.
Es preferible utilizar SFTP cuando esté disponible, ya que cifra la conexión de administración.
Guarda el archivo de configuración en una ubicación privada y verifica los permisos de lectura.
9.3. Opción C: SSH
Si tienes acceso SSH, entra en el servidor con las credenciales del proveedor.
Comprueba la ubicación actual:
pwd
Revisa los archivos:
ls -la
Comprueba la versión de PHP:
php -v
Una vez instalados los archivos, puedes verificar la sintaxis:
php -l /ruta/real/tg_webhook.php
php -l /ruta/real/config_telegram.php
Sustituye las rutas por las de tu instalación.
9.4. Comprobar que la web ejecuta PHP
Abre la dirección pública del webhook en el navegador:
https://www.tudominio.com/tg_webhook.php
Si el script está correctamente protegido, una petición directa sin la cabecera de autenticación puede devolver:
No autorizado
con un código HTTP 403.
Esto es esperable en este ejemplo y no significa que el webhook esté averiado.
No publiques un archivo con phpinfo() para comprobar el funcionamiento de PHP. Si necesitas verificar la configuración, utiliza las herramientas de diagnóstico del proveedor o un script temporal protegido que elimines después.
10. Configurar el webhook de Telegram
Subir los archivos no activa automáticamente el bot. Debes registrar la URL pública mediante la API de Telegram.
La operación puede realizarse desde un terminal, una aplicación administrativa o cualquier entorno capaz de realizar una solicitud HTTPS a la API.
10.1. Definir las credenciales en el terminal
Si tienes acceso a un terminal compatible con variables de entorno, define:
export TELEGRAM_TOKEN='TOKEN_NUEVO_DE_BOTFATHER'
export TELEGRAM_WEBHOOK_SECRET='SECRETO_WEBHOOK_NUEVO'
Sustituye ambos valores por los reales.
Estas variables son temporales y estarán disponibles en la sesión actual. Evita incluir las credenciales directamente en scripts que vayas a publicar.
10.2. Registrar el webhook
Ejecuta:
curl -sS -X POST \
"https://api.telegram.org/bot${TELEGRAM_TOKEN}/setWebhook" \
--data-urlencode \
"url=https://www.tudominio.com/tg_webhook.php" \
--data-urlencode \
"secret_token=${TELEGRAM_WEBHOOK_SECRET}"
Sustituye el dominio y la ruta por la URL pública real del archivo.
Si Telegram acepta la configuración, la respuesta tendrá una estructura similar a esta:
{
"ok": true,
"result": true,
"description": "Webhook was set"
}
Comprueba que ok sea true.
La llamada registra la URL y el secreto que Telegram enviará en la cabecera X-Telegram-Bot-Api-Secret-Token.
El secreto debe coincidir exactamente con el que has guardado en config_telegram.php.
10.3. Consultar el estado del webhook
Ejecuta:
curl -sS \
"https://api.telegram.org/bot${TELEGRAM_TOKEN}/getWebhookInfo"
Revisa estos campos:
url: dirección configurada para recibir las actualizaciones.pending_update_count: cantidad de actualizaciones pendientes.last_error_message: información sobre el último error de entrega, cuando exista.
Si la URL está vacía, el webhook no está configurado.
Si hay errores, comprueba la conectividad, el certificado HTTPS, la ruta PHP, los permisos y la respuesta del servidor.
10.4. ¿Se puede configurar sin SSH?
Sí. El terminal es solo una de las opciones.
También puedes utilizar una aplicación administrativa que realice la solicitud a setWebhook. Si desarrollas esa función dentro de una página web, protégela con autenticación, autorización y medidas contra solicitudes no deseadas.
No crees una página pública que permita modificar el webhook sin comprobar quién realiza la operación.
11. Probar el bot desde Telegram
Abre la conversación con el bot creado mediante BotFather.
Pulsa Iniciar o envía:
/start
Si todo está correctamente configurado, el código de esta guía responderá con un mensaje de bienvenida.
A continuación, realiza las siguientes pruebas.
11.1. Comprobar la respuesta
Envía:
hola
Respuesta esperada:
¡Hola! El bot PHP funciona correctamente.
11.2. Consultar el estado
Envía:
estado
El bot mostrará la versión de PHP del servidor y un mensaje indicando que la recepción de mensajes funciona.
11.3. Consultar la fecha
Envía:
ejecuta fecha
También puedes utilizar:
/fecha
El bot responderá con la fecha y la hora del servidor.
El resultado depende del reloj y de la zona horaria configurada en el alojamiento.
11.4. Comprobar un mensaje desconocido
Envía:
prueba
El bot mostrará una lista de las órdenes disponibles.
11.5. Probar el control de acceso
Si otra persona envía mensajes al bot, el script ignorará las peticiones cuyo identificador numérico no coincida con el usuario autorizado.
Este comportamiento es adecuado para un bot privado. Si necesitas admitir varios usuarios, puedes ampliar la configuración para utilizar una lista de identificadores permitidos.
12. Administrar los comandos desde BotFather
Los comandos registrados en BotFather aparecen en el menú de Telegram, pero la lógica de cada comando debe programarse en PHP.
Para editar el menú, abre @BotFather, envía:
/setcommands
Selecciona el bot y utiliza una lista como esta:
start - Iniciar el bot
hola - Comprobar funcionamiento
estado - Consultar estado
fecha - Consultar fecha del servidor
El código de esta guía reconoce /start, /hola, /estado y /fecha, además de los mensajes de texto correspondientes.
Si añades nuevos comandos, debes implementar su comportamiento en el código PHP y comprobar que solo los usuarios autorizados puedan ejecutarlos.
13. Activar y desactivar el bot
Es importante distinguir entre iniciar una conversación y activar el webhook.
Enviar /start inicia la interacción con el bot, pero no registra el webhook. La configuración técnica se realiza mediante la API de Telegram.
13.1. Activar el bot
Para registrar el webhook o volver a activarlo después de haberlo eliminado, ejecuta de nuevo setWebhook con la URL y el secreto correctos.
curl -sS -X POST \
"https://api.telegram.org/bot${TELEGRAM_TOKEN}/setWebhook" \
--data-urlencode \
"url=https://www.tudominio.com/tg_webhook.php" \
--data-urlencode \
"secret_token=${TELEGRAM_WEBHOOK_SECRET}"
Comprueba el resultado y consulta getWebhookInfo.
13.2. Desactivar el webhook
Para eliminar el webhook configurado, utiliza:
curl -sS -X POST \
"https://api.telegram.org/bot${TELEGRAM_TOKEN}/deleteWebhook"
Esta operación elimina el mecanismo de entrega de actualizaciones a la URL configurada.
No borra el bot, no elimina los archivos de la web y no revoca el token.
Si deseas descartar las actualizaciones pendientes, puedes utilizar drop_pending_updates=true, pero ten en cuenta que perderás esos mensajes.
13.3. ¿Qué sucede al desactivar el webhook?
Telegram dejará de enviar las nuevas actualizaciones a tu página web mediante ese webhook.
Si posteriormente quieres volver a utilizar el bot, registra otra vez la URL mediante setWebhook.
La desactivación no equivale a borrar el bot desde BotFather ni a eliminar el archivo PHP del servidor.
14. Integrar el bot en WordPress
También puedes utilizar este sistema en una instalación de WordPress.
Hay dos posibilidades principales.
14.1. Utilizar un archivo PHP independiente
Puedes alojar tg_webhook.php como un punto de entrada independiente de WordPress, siempre que la configuración del hosting permita ejecutar ese archivo y que la ruta esté correctamente protegida.
Esta opción separa el bot de las páginas y entradas de WordPress. No requiere modificar el núcleo de la plataforma.
Comprueba que las actualizaciones de WordPress o del tema no sobrescriban los archivos personalizados.
14.2. Crear un plugin propio
Otra posibilidad consiste en desarrollar un plugin de WordPress que registre una ruta mediante la API REST de WordPress y procese las actualizaciones recibidas.
En ese caso, el webhook apuntaría a una dirección como:
https://www.tudominio.com/wp-json/mi-bot/v1/webhook
El plugin tendría que validar el secreto, comprobar el usuario autorizado, interpretar los mensajes y enviar las respuestas mediante la API de Telegram.
Esta arquitectura puede facilitar la integración con usuarios, contenidos y otras funciones de WordPress, pero requiere adaptar la implementación al sistema de rutas, permisos y carga de plugins.
No debes colocar el token en el código JavaScript que se ejecuta en el navegador ni exponerlo mediante una página pública.
15. Solución de problemas
15.1. El bot no responde
Comprueba, por este orden:
- Que el token sea válido.
- Que el webhook esté configurado.
- Que la URL pública corresponda al archivo correcto.
- Que HTTPS funcione con un certificado válido.
- Que el servidor pueda ejecutar PHP.
- Que el secreto del webhook coincida.
- Que el usuario esté autorizado.
- Que la API de Telegram acepte el envío de mensajes.
Consulta getWebhookInfo para comprobar los errores de entrega y revisa los registros PHP disponibles en tu alojamiento.
15.2. Error 403: No autorizado
Este error indica que el secreto recibido no coincide con el configurado o que no se ha enviado la cabecera esperada.
Comprueba el valor de webhook_secret y vuelve a registrar el webhook si has cambiado el secreto.
No elimines la comprobación de autenticación para conseguir que el bot responda.
15.3. Error 404: archivo no encontrado
Comprueba que la ruta del webhook sea correcta y que el archivo esté en el directorio público.
Verifica también las reglas de reescritura, las rutas configuradas en el hosting y la URL registrada en Telegram.
15.4. Error 500: error interno
Puede deberse a un error de sintaxis, una ruta incorrecta, permisos insuficientes o una extensión PHP no disponible.
Si tienes acceso a PHP desde un terminal, ejecuta:
php -l /ruta/real/tg_webhook.php
Consulta los registros de errores del servidor para conocer el motivo concreto.
15.5. El webhook está configurado, pero Telegram no confirma el envío
Un webhook puede recibir correctamente las actualizaciones y, aun así, fallar al enviar respuestas.
Comprueba que el servidor pueda conectarse a api.telegram.org, que el token siga siendo válido y que la respuesta de sendMessage contenga ok: true.
El código de esta guía registra un mensaje de error si Telegram no confirma el envío, pero no incluye el token ni la respuesta completa en el registro.
La lista de BotFather no implementa las acciones. Debes añadir cada comando al código PHP y volver a probarlo desde Telegram.
Si modificas el menú, comprueba que el texto recibido coincide con el que reconoce el código.
16. Medidas de seguridad para producción
Antes de utilizar el bot de forma permanente, conviene revisar los siguientes aspectos.
Protección del token: almacénalo fuera del directorio público y revócalo si queda expuesto.
Secreto del webhook: utiliza un valor aleatorio y comprueba la cabecera de cada petición.
Control de acceso: limita las operaciones privadas a los identificadores autorizados.
HTTPS: utiliza un certificado válido y no desactives la verificación TLS.
Archivos privados: evita que el archivo de configuración pueda descargarse directamente.
Registro de errores: registra información suficiente para diagnosticar problemas, sin incluir credenciales.
Limitación de acciones: utiliza órdenes predefinidas y evita ejecutar directamente comandos del sistema operativo a partir de mensajes recibidos.
Control de duplicados: si incorporas operaciones que modifican datos o generan efectos externos, considera implementar mecanismos de idempotencia para evitar repetir acciones cuando una actualización se procesa más de una vez.
Actualizaciones no textuales: si amplías el bot para recibir fotografías, documentos, grupos u otros tipos de eventos, adapta la validación a esos formatos y conserva los controles de autorización.