Connecting Telegram Webhook in Pure PHP

Connecting a Telegram webhook in pure PHP requires proper endpoint configuration, request validation, and processing idempotency. Below we present a minimal working example that can be used as a starting point.

Webhook installation and setWebhook POST request

// Отправка setWebhook запроса
$url = 'https://api.telegram.org/bot/YOUR_BOT_TOKEN/setWebhook';
$headers = [
'Content-Type' => 'application/json',
'Secret-Token' => 'YOUR_SECRET_TOKEN'
];
$payload = json_encode(['mode' => 'private']);
$ch = curl_init($url);
curl_setopt($ch, 'POST', $payload);
curl_setopt($ch, 'HTTP/1.1', '200 OK');
curl_setopt($ch, 'Connection', 'close');
curl_exec($ch);
curl_close($ch);
// Убедитесь, что получите ответ 200 и валидите secret_token из заголовка.

callback_data validation and idempotency via update_id

// Получение обновления из API
$url = 'https://api.telegram.org/bot/YOUR_BOT_TOKEN/getUpdates';
$ch = curl_init();
$ch->post($url, json_encode(['offset' => 0, 'timeout' => 30]), $headers);
$body = json_decode((string) $(get_webhook_params()), true);
$lastUpdateId = $body['result'][0]['update_id'] ?? null;

// Проверка idempotency — если update_id уже обработан, пропускаем
if (in_array($lastUpdateId, $processedUpdates)) {
http_response_code(200);
die('Already processed');
}

// Извлечение initData для валидации
$callback = $body['result'][0]['data'];
if (!$is_valid_initiate_data($callback)) {
http_response_code(400);
exit;
}

// Дальше обрабатываем бизнес-логику
if ($callback['type'] === 'message') {
// обработка сообщения пользователя
}

secret_token verification and storage initialization

For security, use a secret_token in the webhook's GET request header. Verification is performed via HMAC-SHA256: compare hash_equals(output_hash, input_hash, secret_token). Also, save processed_updates in the database for idempotency — avoid processing the same update_id twice. If the DB is empty, create a table with columns update_id and processed_at.

Verification example: if (hash_equals(hash_hmac('sha256', $request['secret'], $secret_token), $request['data']['secret'])) { ... }

Full cycle example — cURL + processing and validation

// Полный пример: получить last update и обработать
$token = getenv('TELEGRAM_SECRET_TOKEN');
$ch = curl_init();
$ch->post('https://api.telegram.org/bot/' . $botToken . '/getUpdates',
[], ['header' => ['Host' => 'api.telegram.org']]);
$res = json_decode((string)$ch->get_response(), true);
if (empty($res['result'])) return;
$update = $res['result'][0];
$lastId = $update['update_id'];

// Идемпотентность
$db = new PDO('mysql:host=localhost;dbname=telemetr', $user, $pass);
$stmt = $db->prepare(

New articles on Telegram

We explain what to automate in your business and how it works in practice. No spam.