Webhook — це основний спосіб отримання оновлень Telegram-бот та у виробництві: швидше, ніж довге опитування, не підтримує постійного зв 'язку та зазвичай живе за балансувальником навантаження. У Yii2 отримання оновлень здійснюється в одній дії, але саме в ній найчастіше ламаються три речі: перевірка CSRF, повторна обробка одного і того ж оновлення та тайм-аути на важку логіку. Давайте розберемо робочу зв' язку.
1. Реєстрація вебхука та змінні середовища
Спочатку зафіксуйте токен і секрет у params.php або в ENV. Немає літералів в коді:
Створіть секрет один раз і зберігайте поруч з маркером. Встановлення вебхука:
allowed_updates обмежує потік: менше типів — менше шуму. Після зміни URL-адреси або секрету setWebhook викликається знову, інакше Telegram продовжить надсилати оновлення на стару адресу.
2. Маршрутизація CSRF та вимкнення для маршрутизації ботів
Кінцева точка вебхука повинна бути POST і не повинна проходити через стандартний фільтр Yii2 CSRF, інакше Yii просто не дозволить запит, оскільки Telegram не має токена CSRF. Правильний шлях — вимкнути CSRF точково для певної дії, а не глобально:
Глобальний обсяг enableCsrfValidation = false вам не потрібно його встановлювати — це вимкне захист форм всього сайту.
3. Перевірка X-Telegram-Bot-Api-Secret-Token
Telegram надсилає заголовок X-Telegram-Bot-Api-Secret-Token з кожним оновленням, якщо ви запитали secret_token в setWebhook. Порівнюйте суворо та послідовно з плином часу, інакше будь-хто зможе змінити вашу URL-адресу:
hash_equals — обов 'язково: в нормі === теоретично вразливі до часових атак на короткі секрети.
4. Ідемпотентність за update_id
Telegram обіцяє, що update_id унікальний і монотонно зростаючий, і забезпечить той самий update_id. Без подвійного захисту ви подвоїте дебетування грошей, надішлете два однакових повідомлення та генеруватимете потенційних клієнтів. Створюється таблиця processed_Updates:
Немає необхідності зберігати «один глобальний курсор» — PK для update_id більш надійно вирішує проблему ідемпотенції. Періодично очищайте старі записи, наприклад, раз на день видаляйте все, що старше 7 днів.
5. Черга: черга Yii для важкої обробки
Telegram чекає відповіді на вебхук не більше ~60 секунд і постійно підтримує зв 'язок. Якщо ви пишете в базу даних в дії, надсилаєте HTTP в CRM, розраховуєте аналітику і відповідаєте користувачеві, легко спіймати тайм-аут і повторити спробу. Рішення: у дії лише підтвердьте зустріч і поставте обробку в чергу.
Запис у processed_Updates а поштовх до черги в одній транзакції — це захист від втрати: якщо черга випала разом з фіксацією, працівник забере запис; якщо фіксація не пройшла, оновлення прийде знову з Telegram.
6. Client to Bot API: cURL, check ok:false
Окрема розмова — як правильно витягнути з Yii2 api.telegram.org. file_get_contents потік http перешкоджає нормальному контролю тайм-ауту та HTTP-коду, а Telegram іноді повертає 5xx без тіла. Шаблон клієнта:
Не забувайте про обмеження: не більше ~30 повідомлень в секунду на одного бота в цілому і не більше 1 повідомлення в секунду в одному чаті. На масових розсилках ставити затримки та обробляти 429 з retry_after.
7. Контрольний список перед запуском
- CSRF вимкнено тільки для дій webhook, всі інші форми захищені.
- Секрет встановлено в setWebhook і порівняли в
hash_equals. - У дії спочатку закріплюється update_id, потім завдання ставиться в чергу, потім повертається 200 OK.
- Відповідь Telegram займає ≤ 1 секунди, вся важка логіка знаходиться в Yii Queue worker.
- Використовує cURL, перевіряє HTTP-код і
ok:falseв JSON. - Токени та секрет — лише в
"params": {/ ENV, а не в сховищі.
Такий бандл переживає Telegram-ретрити, довгі CRM-дзвінки та випадкові дублікати, а головне — не перетворює дію на тонке місце всієї програми.
Якщо вам потрібен готовий фреймворк контролера веб-перехоплювача на Yii2 з чергою та панеллю адміністратора для бота, див. BotCreator.