Files
2026-08-20 04:18:29 +09:00

11 KiB

BotShop — панель управления несколькими Telegram-магазинами

Однопользовательская веб-панель на PHP, из которой обслуживается сразу несколько Telegram-ботов-магазинов. Каждому боту заводятся свои города, районы, товары, варианты и платёжные реквизиты; покупатель проходит в боте цепочку «город → район → товар → вариант → подтверждение» и получает карточку заказа с уникальной суммой к оплате (цена плюс случайная надбавка), оператор подтверждает поступление оплаты вручную в панели, после чего бот сообщает покупателю о подтверждении. Автоматической сверки платежей и приёма чеков нет по замыслу — решение принимает человек.

Проект не связан с радиотематикой остальных репозиториев владельца и стоит отдельно.

Стек

  • PHP 8 без фреймворка и без Composer: один файл-роутер public/index.php (панель + webhook), PDO/MySQL.
  • MySQL/MariaDB, схема в database/schema.sql.
  • Nginx + php-fpm (настраивается установщиком), systemd-юнит для polling-воркера.
  • Telegram Bot API (https://api.telegram.org) — два режима: webhook и long polling через getUpdates.
  • Frontend: серверный HTML со встроенным CSS прямо в index.php, без JS-сборки.

Структура

Путь Назначение
install.sh Автоустановщик для Ubuntu/Debian: пакеты, MySQL, база и пользователь, импорт схемы, storage/config.php, учётка администратора, vhost Nginx, systemd-сервис botshop-polling. Разбирает опции --local, --dir, --db-*, --admin-*, --no-polling.
public/index.php Всё приложение: сессии, вход, дашборд, разделы «Боты / Города / Районы / Товары / Варианты / Реквизиты / Заказы / Логи», страница установки /install, обработчик Telegram-webhook /webhook/<секрет>.
public/.htaccess Rewrite всех запросов на index.php (для Apache; установщик настраивает Nginx, где то же делается через try_files).
scripts/polling.php Демон для работы без домена и SSL: раз за разом опрашивает getUpdates по всем активным ботам, повторяет логику диалога из index.php, хранит offset'ы в storage/polling_offsets.json, помечает просроченные заказы.
database/schema.sql 15 таблиц: users, bots, bot_users, balance_ledger, shop_cities, shop_districts, shop_products, shop_product_variants, shop_stock_items, shop_payment_methods, shop_orders, shop_payments, support_tickets, telegram_updates, audit_logs, admin_logs.
VERSION Версия панели (0.1.1).
storage/ Создаётся установщиком, в git не хранится: config.php с реквизитами БД, логи, offset'ы polling.
README.upstream.md Прежний README автора: описание сценария заказа, статусов и заявленного «безопасного scope» магазина.

Как запустить

Установка на чистый сервер (от root):

sudo apt update
sudo apt install -y git curl
git clone <адрес репозитория> botshop-installer
cd botshop-installer
sudo bash install.sh --local

В конце установщик печатает адрес админки (http://IP/login), email и сгенерированный пароль администратора, имя базы и пароль БД — их нужно сохранить.

Ручная установка без install.sh: создать базу, залить database/schema.sql, направить веб-сервер на каталог public/, открыть /install и заполнить форму — страница сама создаст storage/config.php и администратора.

Локальный режим (без домена и SSL) работает через polling:

systemctl status botshop-polling --no-pager
journalctl -u botshop-polling -f

Режим webhook: добавить бота в разделе «Боты» и нажать «Установить webhook» — панель вызовет setWebhook на адрес <схема>://<хост>/webhook/<webhook_secret>. Telegram требует HTTPS, поэтому этот режим применим только на домене с сертификатом; в репозитории настройки SSL нет.

Важно: install.sh не устанавливает код из текущего каталога — он клонирует и обновляет https://github.com/viktor138irk/bot.git. После переезда на Gitea переменную REPO_URL в начале install.sh нужно поменять, иначе установка и git pull будут тянуть старый репозиторий с GitHub.

Конфигурация

Переменных окружения нет. Настройки задаются двумя способами.

  1. Файл storage/config.php (создаётся установщиком или страницей /install, в git не попадает):
Ключ Назначение Пример
db_host Хост MySQL localhost
db_name Имя базы botshop
db_user Пользователь БД botshop_user
db_pass Пароль БД см. storage/config.php
  1. Параметры установщика (install.sh): --dir (каталог установки, по умолчанию /var/www/botshop), --db-name, --db-user, --db-pass, --admin-email (по умолчанию admin@local.test), --admin-pass, --no-polling. Пароли БД и администратора при отсутствии генерируются из 24 символов.

  2. Настройки бота — в панели, раздел «Боты», хранятся в таблице bots:

Поле Назначение Значение по умолчанию
token Токен Telegram-бота, хранится в базе в открытом виде
webhook_secret Случайный сегмент URL webhook генерируется
status active / paused / error; polling-воркер берёт только active paused
welcome_text Первое сообщение бота «Выберите город:»
min_add, max_add Диапазон случайной надбавки к сумме заказа, рублей 1 и 19
order_ttl_minutes Срок жизни заказа до статуса expired 30
referral_percent, *_pay_enabled, referral_enabled Поля в схеме есть, кодом не используются

Состояние

Прототип, заброшенный на ранней стадии. Все 14 коммитов сделаны в один день — 2026-05-18, последний коммит 2026-05-18.

Рабочей является только базовая ветка сценария: добавление бота, справочники, оформление заказа, ручное подтверждение оплаты оператором. Схема базы (коммит «Расширена схема под баланс рефералку и автовыдачу») ушла заметно дальше кода: баланс, рефералы, склад цифровых товаров, платежи и тикеты поддержки описаны в SQL, но ни панель, ни воркер с этими таблицами не работают. VERSION содержит 0.1.1, README.upstream.md0.2.1; фактическому коду соответствует 0.1.1.

Что не доделано

  • Расхождение статусов заказа между кодом и схемой. В schema.sql статус называется waiting_payment, а public/index.php и scripts/polling.php фильтруют по status='waiting_pay'. Из-за этого не работают: пометка просроченных заказов, счётчик «Ожидают оплату» на дашборде, кнопки «Оплачено»/«Отклонить» в списке заказов (условие $r['status']==='waiting_pay' никогда не выполняется) и проверка уникальности суммы в generateAmount(). Это первое, что нужно чинить.
  • Статусы payment_review, delivered, refunded, rejected из схемы кодом не выставляются; после paid заказ никуда не двигается, автовыдача товара из shop_stock_items не реализована.
  • Не реализованы: баланс (balance_ledger), реферальная программа, поддержка (support_tickets), журнал audit_logs/admin_logs, оплата с баланса и BTC, оплата картой через провайдера. В боте нет главного меню, команды /start не различаются — любое сообщение сбрасывает диалог на выбор города.
  • В панели нет редактирования и удаления записей: разделы городов, районов, товаров, вариантов и реквизитов умеют только добавлять и показывать список. Нет пагинации (жёсткие LIMIT 200/LIMIT 300), нет поиска и фильтров.
  • Действия «Оплачено» и «Отклонить» выполняются GET-ссылками без CSRF-проверки, тогда как формы токен проверяют.
  • Ролей нет: поле users.role есть, но код проверяет только факт входа; учётка администратора одна.
  • Логи storage/logs/ создаются, но приложение в них ничего не пишет; ошибки polling идут в journald, ошибки панели — в лог PHP.
  • Тестов, CI, линтеров и файла зависимостей нет. Маркеров TODO/FIXME в коде нет.
  • Токены ботов и платёжные реквизиты (номера карт, телефон СБП) хранятся в базе в открытом виде.