Внимание, этот мануал для тех, кто немного разбирается в коде и у кого уже есть готовый сайт, к которому нужно наладить отправку форм в телеграм чатах.
Зачем вообще Telegram для заявок
- Мгновенные уведомления: видишь заявки сразу, не ждёшь почту.
- Удобно обрабатывать с телефона: ответил — закрепил — поставил реакцию.
- Низкий процент потерь: даже если на хостинге “падает” SMTP, Telegram доставит.
Что понадобится
- Аккаунт в Telegram.
- Бот (создаётся за 1 минуту через @BotFather).
- Токен бота (его даёт BotFather).
- chat_id — куда слать сообщения (это может быть личка, группа или канал).
- Обработчик формы на сервере (PHP-скрипт), который:
- принимает поля из формы,
- валидирует,
- формирует красивое сообщение,
- стучится в Telegram API
sendMessage
, - отдаёт пользователю понятный ответ.
Шаг 1. Создать бота и получить токен
Открой https://telegram.me/botfather @BotFather → пропиши /newbot или нажми Open и в открывшимся окне нажми Create New Bot.

Придумай имя бота и @username. Username обязательно должен заканчиваться на _bot

Сохраним токен формата 123456789:AA...
. Это “ключ” бота для отправки. Вскоре он нам понадобится.

Токен можно получить в любой момент достаточно зайти в чат @BotFather и написать команду /start и потом /token — далее выбрать из меню имя бота от которого нам нужен токен.

Шаг 2. Получить свой chat_id
После того, как мы создали Бота, зайдём с ним в переписку нажав на его имя в переписке с @BotFather и нажмём кнопку Start — либо же пропишем команду /start
дополнительно, напишите любой текст в чате со своим новым ботом, например: привет

Далее добавляем бота в чат. Чтобы это сделать, нужно добавить нашего бота в уже имеющийся чат/канал, либо создать новый чат/канал с нуля и добавить туда нашего бота. В чате Бота нужно назначить администратором.

Далее, напишите пару сообщений в свой чат/канал куда добавили бота — без разницы что. Их можно будет удалить.

Когда вы предоставите права администратора боту в канале/чате, у него появится надпись, что он имеет доступ к сообщениям.
Затем, копируем следующую ссылку и подготовляем ваш токен бота, который мы сохранили до этого.
https://api.telegram.org/bot<Токен вашего бота>/getUpdates
<Токен вашего бота> — вместо этого подставляем ваш токен. Если вы видите только надпись {«ok»:true,»result»:[]} — ничего страшного, просто подождите. Можете написать ещё что-нибудь в свой чат или канал, куда мы добавили нового бота.
Нас интересует значение рядом с ID которая начинается с минуса и содержит 13 символов. Копируем его.

Теперь у нас есть наш token и чат id.
Шаг 3. HTML-форма на лендинге

В нашей форме есть несколько полей и прикрепление фотографии или файла.
Пример формы с картинки выше
<form class="form_upload2" action="mail.php" method="post" enctype="multipart/form-data"> <input type="hidden" name="ajax" value="1"> <div class="prilouder"> <svg viewBox="0 0 417 325" xmlns="http://www.w3.org/2000/svg"> <path d="M159.677 318.278C155.696 322.282 150.266 324.516 144.624 324.516C138.983 324.516 133.552 322.282 129.571 318.278L9.35675 198.044C-3.11892 185.568 -3.11892 165.338 9.35675 152.886L24.4094 137.829C36.889 125.354 57.0957 125.354 69.5713 137.829L144.624 212.886L347.428 10.0784C359.907 -2.39724 380.134 -2.39724 392.59 10.0784L407.642 25.135C420.118 37.6107 420.118 57.8368 407.642 70.293L159.677 318.278Z"></path> </svg> </div> <div class="input_container"> <h3>закажите новую мебель у нас по цене на 15% ниже рыночной</h3> <div class="input_box"> <label for="vid2">Вид мебели </label> <select id="vid2" name="Вид мебели"> <option>Угловой диван (сложной формы)</option> <option>Угловой диван (еврокнига)</option> <option>Кухонный уголок или диван</option> <option>Диван-аккордеон</option> <option>Диван-аккордеон (цельный чехол)</option> <option>Кресло</option> <option>Кресло-кровать</option> <option>Диван-двойка, широкое кресло</option> <option>Стул (со спинкой, кухонный, офисный)</option> <option>Пуфик</option> <option>Тахта</option> </select> </div> <div class="input_box"> <label for="material2">ВЫБЕРИТЕ материал</label> <select id="material2" name="Материал"> <option>Искусственная кожа</option> <option>Экокожа</option> <option>Велюр</option> <option>Флор</option> <option>Жаккард</option> <option>Шенилл</option> <option>Рогожка</option> <option>Не определился</option> </select> </div> <div class="input_box"> <label for="phone2">Ваш номер телефона </label> <input id="phone2" name="phone" placeholder="Ваш телефон" type="text" onkeyup="var yratext=/['a-zA-Zа-яА-Я',':;*<>!?']/; if(yratext.test(this.value)) this.value=''" required=""> </div> <div class="input_box" style="margin-top: 0px;"> <label for="file_v2">загрузите фото</label> <div class="file-upload2"> <label> <input id="file_v2" type="file" name="file"><span id="file2">Выбрать файл </span> </label> </div> </div> <div class="input_box textarea"> <label for="textarea">Описание</label> <textarea id="textarea" rows="4" name="Описание" type="text" placeholder="Описание" onkeyup="var yratext=/[':;*<>!?']/; if(yratext.test(this.value)) this.value=''" required></textarea> </div> <button class="button" type="submit">Рассчитать</button> </div> </form>
Реальность такова: нам нужны имена атрибутов инпутов, которые обработчик действительно ждёт. Часто это что-то вроде:
name
— имяphone
— телефон- whatever — что угодно (опционально)
Главное: поля формы и ожидания в PHP должны совпадать по именам. Если на вашем сайте форма содержит поле name=»name» или name=»phone» — значит в нашем php-обработчике поля должны соответствовать.
Шаг 4. Что делает обработчик (смысловой алгоритм)
- Проверяет метод запроса (только POST).
- Забирает и чистит поля (trim, фильтры, базовая валидация).
- Проверяет “обязательные” поля (телефон).
- Склеивает сообщение для Telegram. Здесь важно:
- Лаконичный, читаемый шаблон.
- Выделяем жирным важное.
- Каждое поле — с новой строки.
- Шлёт запрос в Telegram API:
sendMessage
(текст), опционально —sendPhoto
/sendDocument
.- Передаёт
chat_id
,text
,parse_mode=HTML
.
- Разруливает ответ (успех/ошибка) и возвращает пользователю понятный фидбек:
- Для классической формы — редирект на “спасибо-страницу”.
<?php // ====== CONFIG ====== $BOT_TOKEN = 'СЮДА ВСТАВИТЬ ВАШ ТОКЕН'; $CHAT_ID = 'СЮДА ВСТАВИТЬ ВАШ CHAT ID с - '; // пример: -1001234567990 для канала/группы $THANK_URL = '/thank.html'; // перевод на страницу спасибо $LOG_FILE = __DIR__ . '/error.log'; // ====== УТИЛИТЫ ====== function log_error($msg){ global $LOG_FILE; $line = '['.date('Y-m-d H:i:s')."] ".$msg."\n"; @file_put_contents($LOG_FILE, $line, FILE_APPEND); } function is_ajax(){ // фронт всегда шлёт ajax=1 и ждёт JSON return (isset($_POST['ajax']) && $_POST['ajax']=='1'); } function resp_json($arr){ header('Content-Type: application/json; charset=UTF-8'); echo json_encode($arr, JSON_UNESCAPED_UNICODE); exit; } function tg_api($method, $data, $isMultipart=false){ global $BOT_TOKEN; $url = "https://api.telegram.org/bot{$BOT_TOKEN}/{$method}"; $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_TIMEOUT, 20); if ($isMultipart){ curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: multipart/form-data')); curl_setopt($ch, CURLOPT_POSTFIELDS, $data); } else { curl_setopt($ch, CURLOPT_POSTFIELDS, $data); } $res = curl_exec($ch); if ($res === false){ $err = curl_error($ch); curl_close($ch); log_error("cURL error: ".$err); return array('ok'=>false, 'error'=>$err); } curl_close($ch); $j = json_decode($res, true); if (!$j || !isset($j['ok'])){ log_error("Telegram bad response: ".$res); return array('ok'=>false, 'error'=>'bad_telegram_response'); } return $j; } // ====== ТЕХНИЧЕСКИЕ ПРОВЕРКИ ====== if (isset($_GET['health'])) { // Простой ответ для проверки 200 ОК из браузера header('Content-Type: application/json; charset=UTF-8'); echo json_encode(array('ok'=>true,'php'=>PHP_VERSION,'time'=>date('c'))); exit; } if (isset($_GET['selftest'])) { // Лёгкий self-test: не шлём ничего в чат, просто показываем что скрипт жив header('Content-Type: application/json; charset=UTF-8'); echo json_encode(array('ok'=>true,'curl'=>function_exists('curl_init'),'php'=>PHP_VERSION)); exit; } // ====== СБОР ДАННЫХ ФОРМЫ ====== $name = isset($_POST['name']) ? trim($_POST['name']) : ''; $phone = isset($_POST['phone']) ? trim($_POST['phone']) : ''; $message = isset($_POST['message']) ? trim($_POST['message']) : ''; // если где-то есть // Склеим ВСЕ поля (в т.ч. русские name вроде "Вид мебели", "Материал", чекбоксы и т.д.) $lines = array(); foreach ($_POST as $k=>$v){ if ($k==='ajax') continue; // Нормализуем массивы (на всякий случай) if (is_array($v)) { $v = implode(', ', $v); } $lines[] = $k.': '.$v; } if (!empty($_FILES['file']) && isset($_FILES['file']['name']) && $_FILES['file']['error']===UPLOAD_ERR_OK){ $lines[] = 'Файл: '.$_FILES['file']['name'].' ('.$_FILES['file']['type'].', '.$_FILES['file']['size'].' байт)'; } if ($phone===''){ $msg = 'Ошибка: укажите телефон'; if (is_ajax()) resp_json(array('success'=>false, 'message'=>$msg)); header("HTTP/1.1 400 Bad Request"); echo $msg; exit; } // ====== ОТПРАВКА В TELEGRAM ====== $txt = "🛠 <b>Новая заявка с сайта </b>\n"; $txt .= "📅 <b>Время:</b> " . date('d.m.Y H:i') . "\n\n"; // Сначала выведем телефон и имя отдельно, потом всё остальное $phone_line = ''; $name_line = ''; $other_lines = ''; foreach ($_POST as $k => $v) { if ($k === 'ajax') continue; if (is_array($v)) $v = implode(', ', $v); $v = trim($v); if ($v === '') continue; if (preg_match('/phone|тел/i', $k)) { $phone_line = "☎️ <b>Телефон:</b> " . htmlspecialchars($v, ENT_QUOTES, 'UTF-8') . "\n"; } elseif (preg_match('/name|имя/i', $k)) { $name_line = "👤 <b>Имя:</b> " . htmlspecialchars($v, ENT_QUOTES, 'UTF-8') . "\n"; } elseif (preg_match('/mail|почт/i', $k)) { $other_lines .= "📧 <b>Email:</b> " . htmlspecialchars($v, ENT_QUOTES, 'UTF-8') . "\n"; } else { $other_lines .= "▫️ <b>" . htmlspecialchars($k, ENT_QUOTES, 'UTF-8') . ":</b> " . htmlspecialchars($v, ENT_QUOTES, 'UTF-8') . "\n"; } } $txt .= $phone_line; $txt .= $name_line; $txt .= $other_lines; if (!empty($_FILES['file']) && $_FILES['file']['error'] === UPLOAD_ERR_OK) { $txt .= "\n📎 <b>Файл прикреплён:</b> " . htmlspecialchars($_FILES['file']['name'], ENT_QUOTES, 'UTF-8'); } $r1 = tg_api('sendMessage', array( 'chat_id' => $CHAT_ID, 'text' => $txt, 'parse_mode' => 'HTML' )); if (empty($r1['ok'])){ $msg = 'Не удалось отправить сообщение. Попробуйте позже.'; log_error('sendMessage failed: '.json_encode($r1)); if (is_ajax()) resp_json(array('success'=>false, 'message'=>$msg)); header("HTTP/1.1 500 Internal Server Error"); echo $msg; exit; } // 2) Если есть файл — шлём как документ (универсально) if (!empty($_FILES['file']) && $_FILES['file']['error']===UPLOAD_ERR_OK){ $tmp = $_FILES['file']['tmp_name']; $nameFile = $_FILES['file']['name']; $mime = !empty($_FILES['file']['type']) ? $_FILES['file']['type'] : 'application/octet-stream'; // В PHP 5.6 используем CURLFile if (class_exists('CURLFile')) { $fileObj = new CURLFile($tmp, $mime, $nameFile); } else { // legacy формат — на очень старых сборках PHP/cURL $fileObj = '@'.$tmp.';filename='.$nameFile.';type='.$mime; } $cap = "Файл от: ".($name?:'—')."; Телефон: ".$phone; $r2 = tg_api('sendDocument', array( 'chat_id' => $CHAT_ID, 'caption' => $cap, 'document' => $fileObj ), true); if (empty($r2['ok'])){ log_error('sendDocument failed: '.json_encode($r2)); // Не валим заявку — текст уже ушёл. Просто сообщим фронту «ок, но файл не приложился». } } // ====== ОТВЕТ ФРОНТУ ====== if (is_ajax()){ resp_json(array('success'=>true, 'redirect'=>$THANK_URL)); } else { header('Location: '.$THANK_URL); exit; }
Главное, чтобы у вас был создан файл mail.php и он же задан как обработчик формы через action=»mail.php» method=»post»
Cкопируйте и поставьте код выше в свой mail.php.
Ваши поля должны соответствовать заданным в этом файле.
Итог:
