
Многие VPN-сервисы продают через Telegram: клиент уже в чате, значит, и покупка должна проходить там же. В этом гайде — как запустить готового бота на своём сервере: клиент выбирает тариф, платит в USDT в сетях TRC20, ERC20 или BEP20 или другой монетой, а бот создаёт или продлевает пользователя в вашей панели Marzban, 3x-ui или Remnawave и присылает ссылку на подписку в тот же чат. Свой кошелёк и нода блокчейна не нужны — деньги приходят на баланс мерчанта SnapEX Pay.
Как проходит продажа
клиент → /start → нажимает тариф
бот → SnapEX Pay: счёт → кнопка «Pay»
клиент → платит на странице SnapEX Pay
SnapEX Pay → подписанный вебхук → бот
бот → GET счёта через API → paid?
бот → панель: создать или продлить
бот → клиент: ссылка на подписку
/startпоказывает ваши тарифы кнопками. Каждое нажатие создаёт счёт SnapEX Pay, и бот отвечает кнопкой Pay («Оплатить»).- Клиент выбирает монету на странице оплаты и платит. Когда счёт оплачен, SnapEX Pay шлёт боту подписанный вебхук.
- Бот проверяет подпись, запрашивает счёт через API SnapEX Pay и выдаёт доступ, только если там статус
paidи счёт относится к заказу, который создал сам бот.
Имя пользователя в панели — tg<telegram_id>, поэтому каждому аккаунту Telegram соответствует ровно один пользователь VPN.
Что нужно
- Токен бота от @BotFather.
- Доступ администратора к панели Marzban, 3x-ui (MHSanaei) или Remnawave (2.x или 3.x). Без панели бот умеет только принимать оплату (
PANEL_TYPE=none), а доступ вы выдаёте сами. - Сервер с Docker Compose (или Python 3.12).
- Публичный HTTPS-адрес для вебхука: SnapEX Pay доставляет вебхуки только на адреса
https://. - Аккаунт мерчанта SnapEX Pay: регистрация на pay.snapex.pro.
Бот работает через long polling, поэтому Telegram не нужен открытый порт на вашем сервере — снаружи должен быть доступен только порт вебхука за HTTPS.
Шаг 1. Скачайте бота
Скачайте архив snapexpay-telegram-vpn-bot-1.1.0.zip (MIT, бесплатно) и создайте файл настроек:
curl -fsSLO https://pay.snapex.pro/downloads/telegram-vpn-bot/snapexpay-telegram-vpn-bot-1.1.0.zip
unzip snapexpay-telegram-vpn-bot-1.1.0.zip
cd snapexpay-telegram-vpn-bot-1.1.0
cp .env.example .env
Все настройки лежат в .env. Впишите токен бота в TELEGRAM_BOT_TOKEN, а название магазина — в SHOP_NAME: оно показывается в сообщении /start и в описании счёта.
Шаг 2. Получите API-ключ
В кабинете мерчанта SnapEX Pay откройте «Разработчикам» и выпустите API-ключ. Он показывается один раз — сразу скопируйте его в SNAPEX_API_KEY. Ключ из кабинета получает все права Merchant API, в том числе нужные боту invoices.read и invoices.write. Перевыпуск сразу отзывает старый ключ, поэтому меняйте .env в тот же момент.
Ещё две настройки оплаты:
SNAPEX_FEE_ON—merchant(по умолчанию): клиент платит ровно цену тарифа, а комиссии вычитаются из того, что получаете вы;customer: комиссии добавляются сверху. Подробно: Кто платит комиссию за криптоплатёж.SNAPEX_EXPIRES_MINUTES— сколько минут счёт можно оплатить, по умолчанию 60 (от 1 до 1440).
Шаг 3. Опишите тарифы
Тарифы задаются одной строкой в PLANS: id:days:price_usd:traffic_bytes через запятую. 0 байт — безлимитный трафик.
PLANS=week:7:2.00:0,month:30:5.00:0,quarter:90:12.00:107374182400
Здесь quarter — 90 дней со 100 ГиБ трафика. id показывается на кнопке («month — $5.00 / 30d»), поэтому делайте его коротким: латинские буквы, цифры, _ и -. Цены — в USD; минимальный счёт — 0.50 USD.
Каждый заказ хранит копию своего тарифа, так что цены можно менять потом, не затрагивая уже оплаченные заказы.
Шаг 4. Подключите панель
Задайте PANEL_TYPE и данные доступа к вашей панели.
Marzban — PANEL_TYPE=marzban:
MARZBAN_URL,MARZBAN_USERNAME,MARZBAN_PASSWORD— адрес панели и логин администратора (или готовый токен администратора вMARZBAN_TOKEN).MARZBAN_SUB_URL— только если Marzban отдаёт относительные ссылки/sub/<token>(пустойXRAY_SUBSCRIPTION_URL_PREFIX): публичная база для ссылки.
3x-ui — PANEL_TYPE=3xui:
XUI_URL— адрес панели вместе с базовым путём веб-интерфейса, если вы его задали (https://xui.example.com:2053/secretpath).XUI_USERNAME,XUI_PASSWORD— у этой учётной записи двухфакторная аутентификация должна быть выключена.XUI_INBOUND_ID— inbound, в который добавляются новые клиенты (vless, vmess, trojan или shadowsocks).XUI_SUB_URL— база подписки, напримерhttps://xui.example.com:2096/sub. Без неё бот присылает толькоsubId.
Remnawave — PANEL_TYPE=remnawave:
REMNAWAVE_URLиREMNAWAVE_TOKEN— адрес панели и API-токен из раздела API Tokens.REMNAWAVE_SQUAD_UUIDS— внутренние сквады для новых пользователей, через запятую. Без сквада у нового пользователя нет серверов.
Шаг 5. Запустите бота за HTTPS
docker compose up -d --build
docker compose logs -f bot
Бот слушает порт 8080: /webhook — для SnapEX Pay, /health — для проверок. Поставьте перед ним обратный прокси с TLS, например Caddy:
pay-bot.example.com {
reverse_proxy 127.0.0.1:8080
}
Прокси должен передавать тело запроса без изменений — подпись считается по сырому телу.
Шаг 6. Настройте вебхук
В кабинете на странице «Разработчикам» укажите адрес вебхука https://pay-bot.example.com/webhook и сохраните. Секрет подписи whsec_… показывается один раз, сразу после первого сохранения, — скопируйте его в SNAPEX_WEBHOOK_SECRET и перезапустите бота: docker compose up -d.
В кабинете один адрес вебхука на аккаунт, и туда приходят все события. Бот обрабатывает только события счетов, а на остальные просто отвечает подтверждением.
Как бот проверяет уведомление:
- заголовок
Webhook-Signature: HMAC-SHA256 от{Webhook-Timestamp}.{сырое тело запроса}с вашим секретом; неподписанные или подменённые запросы получают401; Webhook-Timestampв пределах 5 минут от часов сервера — держите NTP включённым;- сам счёт, перечитанный через API SnapEX Pay вашим ключом: доступ выдаётся, только если там статус
paid.
Если панель или API SnapEX Pay в этот момент недоступны, бот отвечает 502, и SnapEX Pay повторяет доставку (до 5 попыток). Повторные и одновременные доставки выдают доступ по счёту один раз. Подробнее о подписи и повторах: Вебхуки криптоплатежей.
Шаг 7. Тестовая покупка без реальных денег
- Поставьте
SNAPEX_ENVIRONMENT=testи перезапустите:docker compose up -d. - Отправьте
/startсвоему боту со своего аккаунта Telegram и нажмите тариф. - Нажмите Pay. На странице SnapEX Pay будет метка Test. Выберите любую монету и сеть: страница покажет тестовый адрес, и примерно через 10 секунд оплата подтвердится сама. Ничего отправлять не нужно.
- Бот должен прислать «Payment received» («Оплата получена») и ссылку на подписку, а в панели должен появиться пользователь
tg<ваш telegram id>. Если нет — смотритеdocker compose logs -f botи журнал доставок на странице «Разработчикам». - Поставьте
SNAPEX_ENVIRONMENT=liveи перезапустите.
Пока бот в режиме test, любой тариф, купленный через него, выдаётся без денег — поэтому не затягивайте тест. Подробнее: Как протестировать криптоплатежи без реальных денег.
Что видит клиент
/start— название вашего магазина, строку об оплате в USDT (TRC20 / ERC20 / BEP20) или другими монетами и кнопки тарифов.- После нажатия — тариф, число дней, цену и номер счёта, плюс кнопку «Pay $5.00 with crypto» («Оплатить $5.00 криптовалютой»).
- Страницу SnapEX Pay с выбором монеты: USDT в TRC20, ERC20 и BEP20 и другие монеты (всего 50+), если SnapEX Pay предлагает их для суммы счёта.
- После оплаты — «Payment received» и ссылку на подписку в том же чате. При
PANEL_TYPE=noneв сообщении сказано, что администратор скоро пришлёт доступ.
Сообщения самого бота — на английском; ваши — только название магазина и названия тарифов.
Постоянный клиент платит с того же аккаунта Telegram, и его пользователь продлевается от текущей даты окончания (или от текущего момента, если она уже прошла); тариф с лимитом трафика начинает новую квоту. Подробно: Продление VPN-подписок за крипту.
Если клиент прислал меньше суммы, доступ не выдаётся: бот выдаёт его только по счёту в статусе paid. Полученное придёт на ваш баланс SnapEX Pay, остаток вы решаете с клиентом сами. Как работают недоплаты: Клиент прислал меньше суммы счёта.
Если что-то не работает
- «Payment is unavailable right now» («Оплата сейчас недоступна») после нажатия тарифа. Бот не смог создать счёт: проверьте
SNAPEX_API_KEY(ключ неверный или отозван) и логи. - Вебхук получает 401 «bad webhook signature». Не совпадает
SNAPEX_WEBHOOK_SECRET, или прокси меняет тело запроса. Проверьте также, что часы сервера синхронизированы. - Клиент оплатил, но ничего не получил. Ищите
provision failedв логах. SnapEX Pay продолжает повторять доставку; как только панель снова заработает, следующая доставка выдаст доступ — или повторите доставку из журнала в кабинете. - Marzban присылает ссылку без хоста. Задайте
XRAY_SUBSCRIPTION_URL_PREFIXв Marzban илиMARZBAN_SUB_URLв боте. - 3x-ui: «login failed». Проверьте
XUI_URL(с базовым путём веб-интерфейса) и логин и выключите двухфакторную аутентификацию для этой учётной записи. - Remnawave: пользователь создаётся, но подписка пустая. Укажите в
REMNAWAVE_SQUAD_UUIDSсквады с вашими нодами. - Несколько копий бота. Запускайте один экземпляр на
DATA_DIR: защита от дублей работает в пределах одного процесса и его файла SQLite.
Сколько стоит
1% с платежа, без платы за подключение и абонентской платы. Бот бесплатный.
Страница бота: Telegram-бот для VPN. Продаёте через встроенный магазин панели? Смотрите Криптоплатежи в Xboard и V2Board. Обзор для VPN-сервисов: Криптоплатежи для VPN-сервисов. Регистрация: pay.snapex.pro.