TKBK Studio
TKBK Studio
Статусы СДЭК клиенту в Telegram или SMS и алерт менеджеру, если посылка застряла
Сервис для интернет-магазина, который возит заказы через СДЭК: подписывается на вебхук ORDER_STATUS, а на случай потерянных вебхуков сам опрашивает заказы по API v2. Клиент получает сообщение, когда посылка принята, в пути, прибыла в город, ждёт в пункте выдачи, передана курьеру или вручена.
Сообщения уходят только при смене этапа, без спама на каждый транзитный склад. Клиент подписывается на заказ в Telegram-боте по ссылке из письма, а для тех, кто не подписался, есть интерфейс SMS — подключите любого провайдера.
Менеджер получает алерты о проблемах: «не вручена», возврат, удалённый заказ и посылки без движения дольше заданного числа дней — меньше звонков «где мой заказ» и меньше потерянных посылок.
Для кого: Интернет-магазины и селлеры, отправляющие заказы через СДЭК
Ключи и токены не вводятся на сайте — их кладут в файл .env на своём сервере.
CDEK_CLIENT_IDAccount СДЭК — lk.cdek.ru → Интеграция → Ключи APICDEK_CLIENT_SECRETSecure password СДЭК — lk.cdek.ru → Интеграция → Ключи APIPUBLIC_URLПубличный адрес сервиса — https://track.example.ru — для подписки на вебхукWEBHOOK_SECRETСекрет в адресе вебхука — Длинная случайная строкаTELEGRAM_BOT_TOKENТокен Telegram-бота — @BotFather → /newbotMANAGER_CHAT_IDID чата менеджера для алертов — Добавьте бота в чатADMIN_TOKENТокен для API заказов — Длинная случайная строка# Уведомления о доставке СДЭК — {{SHOP_NAME}}
Сервис следит за заказами СДЭК и сам пишет клиентам, когда посылка принята, в пути, прибыла в город,
ждёт в пункте выдачи, передана курьеру или вручена. Менеджер получает алерты о проблемах: «не вручена»,
возврат, удалённый заказ и «застрял» — нет движения дольше {{STUCK_DAYS}} дней.
## Что умеет
- OAuth `client_credentials` к API СДЭК v2 с кэшем токена (обновляется заранее и при 401).
- Подписка на вебхук `ORDER_STATUS` (`POST /v2/webhooks`, без дублей) и приём статусов по секретному адресу.
- Фолбэк-опрос `GET /v2/orders?cdek_number=…` каждые {{POLL_MINUTES}} мин. — если вебхук потерялся, статус всё равно придёт.
- Клиенту — только при смене этапа (а не на каждый транзитный склад); устаревшие и повторные статусы игнорируются.
- Клиент подписывается на заказ в Telegram по ссылке `https://t.me/{{BOT_USERNAME}}?start=<номер>` или
просто присылает номер боту.
- SMS — через интерфейс `SmsSender` (сейчас заглушка, пишет в лог): подключите своего провайдера в `app/notify.py`.
- Алерт менеджеру «застрял > N дней» — один раз на каждый статус.
## Запуск за 5 минут
### С Docker
```bash
cp .env.example .env # ключи СДЭК, PUBLIC_URL, WEBHOOK_SECRET, Telegram, ADMIN_TOKEN
docker compose up -d --build
curl -X POST https://ваш-домен/api/cdek/subscribe -H "Authorization: Bearer <ADMIN_TOKEN>"
```
### Без Docker (Python 3.12)
```bash
python -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
pip install -r requirements.txt
cp .env.example .env
python -m app
```
СДЭК отправляет вебхуки на публичный адрес — разместите сервис на сервере с доменом и HTTPS. Без
публичного адреса работает только опрос по расписанию.
## Где взять ключи СДЭК
1. Личный кабинет СДЭК (lk.cdek.ru) → **Интеграция** → **«Ключи API»** (нужен договор с СДЭК).
2. **Account** → `CDEK_CLIENT_ID`, **Secure password** → `CDEK_CLIENT_SECRET`.
3. Для проверки без договора: `CDEK_TEST=yes` и тестовые ключи из документации СДЭК
(раздел «Протокол обмена данными → Тестовая среда»).
## Как добавить заказ на отслеживание
```bash
curl -X POST http://localhost:8000/api/orders \
-H "Authorization: Bearer <ADMIN_TOKEN>" -H "Content-Type: application/json" \
-d '{"cdek_number": "1106207236", "phone": "+79991234567"}'
```
В ответе — `telegram_link`: отправьте её клиенту (в письме или SMS), он нажмёт «Старт» и будет получать
статусы в Telegram. Заказы, о которых СДЭК пришлёт вебхук, добавляются автоматически.
## Настройки из мастера
`app/config.py` (константы `WIZARD_*`): название магазина, имя бота, «застрял через N дней», интервал опроса,
SMS. Переопределяются в `.env`: `SHOP_NAME`, `BOT_USERNAME`, `STUCK_DAYS`, `POLL_MINUTES`, `SMS_ENABLED`.
Тексты для клиентов и группировка статусов — в `app/statuses.py`.
## Подключение SMS
Создайте класс с методом `async def send(self, phone: str, text: str) -> None` (например, запрос к API
SMS.ru или SMSC через httpx) и передайте его вместо `LogSmsSender()` в `app/main.py`. Включите `SMS_ENABLED=yes`.
SMS уходит, только если клиент не подписан в Telegram.
## Тесты
```bash
pip install pytest==9.1.1
pytest
```
Тесты не ходят в сеть: СДЭК и Telegram подменены `httpx.MockTransport`.
## FAQ
**Вебхуки не приходят.** Проверьте `PUBLIC_URL` (должен открываться снаружи по HTTPS) и повторите
`POST /api/cdek/subscribe`. Неверный секрет в адресе → 404.
**Клиент не получает сообщения в Telegram.** Клиент должен сам нажать «Старт» у бота — писать первым
Telegram-боты не могут. Без подписки сработает SMS (если подключено).
**Почему не на каждый статус?** Клиенту приходит сообщение при смене этапа (принят → в пути → в городе →
в пункте выдачи → вручён), транзитные склады внутри этапа не спамят.
## Ограничения API
- Токен СДЭК живёт около часа — сервис обновляет его сам.
- Опрос идёт с паузой между заказами; для тысяч активных заказов увеличьте `POLL_MINUTES` и опирайтесь на вебхуки.
- Вебхуки СДЭК не подписываются — защита держится на секрете в адресе; не публикуйте его.
Услуги, мастера, свободные окна на 14 дней, напоминания за сутки и за 2 часа, предоплата и отзывы
Оценка 0–10 после заказа: довольных — на Яндекс Карты, 2ГИС и WB, недовольных — сразу к менеджеру
Оплата звёздами или картой, одноразовые ссылки, напоминания о продлении и автоисключение по окончании