Внимание, этот мануал для тех, кто немного разбирается в коде и у кого уже есть готовый сайт, к которому нужно наладить отправку форм в телеграм чатах.
Зачем вообще 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.
Ваши поля должны соответствовать заданным в этом файле.
Итог:








