Авторизация в API Авито устроена привычно для любого, кто работал с внешними сервисами: у приложения есть постоянная пара «идентификатор и секрет», а для запросов используется временный токен, который выдаётся в обмен на эту пару и живёт ограниченное время. Секрет вы храните и никому не показываете, токен — обновляете.
Практическая сложность не в схеме, а в том, что токен истекает не тогда, когда вам удобно. Он истекает в момент, когда покупатель ждёт ответа. Всё, что написано ниже, — про то, как сделать этот момент незаметным для покупателя.
Что именно вы получаете
После создания приложения в кабинете продавца у вас на руках два значения. Идентификатор клиента можно считать публичным. Секрет клиента — это пароль: кто им владеет, тот действует от имени вашего магазина в пределах выданных прав.
Дальше эта пара меняется на токен доступа. В ответе, помимо самого токена, приходит срок его жизни. Точные адреса, названия полей и типы токенов смотрите в официальной документации Авито — состав может отличаться для разных разделов API и меняться со временем. Общая картина того, зачем всё это нужно продавцу, есть в разборе API мессенджера Авито, а последовательность подключения — в статье как подключить API Авито.
Где хранить секреты
Правила простые и нарушаются одинаково у всех.
- Не в репозитории. Даже в приватном. История коммитов живёт дольше, чем ваша уверенность в том, кто имеет к ней доступ.
- Не в коде «на время отладки». Это самая долгоживущая временная мера в индустрии.
- В переменных окружения или менеджере секретов. Файл с переменными — в исключениях системы контроля версий, с правами только для владельца.
- Не в логах. Проверьте, что ваш HTTP-клиент не печатает заголовки запроса в режиме отладки. Печатает — токен уже в логах, а логи уходят в систему сбора.
- Разные ключи для разных сред. Тестовый код не должен ходить теми же ключами, что боевой.
Если секрет всё же утёк, порядок действий один: отозвать доступ в кабинете и выпустить новую пару. Не «поменять пароль от аккаунта и надеяться» — выданный доступ живёт своей жизнью.
Как обновлять токен
Работающая схема состоит из двух независимых механизмов, и оба нужны.
Обновление заранее. Вы храните не только токен, но и момент, когда он перестанет действовать. Перед каждым запросом проверяете: если до истечения осталось меньше запаса — скажем, нескольких минут, — обновляете. Запас нужен, потому что часы вашего сервера и часы площадки не совпадают идеально, а сам запрос идёт по сети не мгновенно.
Обновление по факту отказа. Даже с запасом вы иногда получите ответ «не авторизован»: токен могли отозвать вручную, права могли измениться, сервер мог проспать в состоянии паузы. Значит, обёртка над запросом должна уметь один раз получить новый токен и повторить.
def call(method, url, body=None):
token = tokens.get_fresh() # обновит, если срок близко
r = http(method, url, token, body)
if r.status == 401: # токен не принят
token = tokens.force_refresh() # получить новый принудительно
r = http(method, url, token, body)
return r
Ключевое слово в этом псевдокоде — «один раз». Цикл «пока не получится» при отозванном доступе превращается в бесконечный поток запросов на авторизацию и заканчивается упором в лимиты, а иногда и временной блокировкой.
Гонка при обновлении
Неочевидная деталь: обновлять токен одновременно из нескольких потоков — плохая идея. Три параллельных обработчика сообщений увидят истёкший токен, и все три пойдут за новым. В лучшем случае вы потратите лишние запросы, в худшем — часть выданных токенов окажется неактуальной, и запросы начнут падать по кругу.
Лечится блокировкой вокруг обновления: первый поток обновляет, остальные ждут и берут готовый результат. Если бот живёт в нескольких процессах, блокировка должна быть общей — в базе или в кеше, а не внутри процесса.
В готовых сервисах эта обвязка уже написана: «Папа БУ» держит доступ сам, а если площадка перестала его принимать, показывает это явно, а не молчаливым зелёным статусом.
Истечение посреди диалога
Самый неприятный сценарий выглядит так. Покупатель написал, вебхук пришёл, ответ сгенерирован, а на отправке — отказ по авторизации. Если отправка была разовой попыткой в обработчике, ответ просто исчезает: покупатель не получил ничего, а в логах строчка, которую никто не читает.
Правильное устройство: отправка ответа — это задача в очереди, а не действие «на лету». У задачи есть статус и счётчик попыток. Отказ по авторизации переводит её в повтор, а не в мусор. Тогда истечение токена стоит покупателю нескольких секунд ожидания вместо потерянного диалога. Ровно из-за таких мелочей продавцы теряют обращения — тема разобрана в статье про то, как не терять клиентов на Авито.
Права и отзыв доступа
Полезная привычка — понимать, какие права вы запросили и зачем. Чем уже набор, тем меньше ущерб при утечке и тем спокойнее продавец, который этот доступ выдаёт.
Отзыв доступа должен быть простым и односторонним: владелец аккаунта в любой момент отключает приложение в кабинете, и оно перестаёт работать. Ваш код должен это переживать корректно — отличать «доступ отозван» от «сеть моргнула» и сообщать человеку, а не пытаться чинить себя повторами.
Когда всё это можно упростить
- Скрипт для разовой выгрузки. Получили токен, отработали двадцать минут, закончили. Механизм обновления не понадобится, достаточно понятной ошибки.
- Один процесс и один поток. Блокировка вокруг обновления не нужна, хватит простой проверки срока.
- Готовый сервис вместо своего кода. Тогда вопрос авторизации сводится к одному действию продавца в кабинете и к возможности так же легко доступ отозвать.
А вот чего упрощать нельзя ни при каком размере: хранения секретов и ограничения на число повторов. Эти две вещи ломают систему одинаково больно и в прототипе, и в бою.
Коротко
Авторизация в API Авито — это постоянная пара ключей, временный токен и ваша дисциплина вокруг них. Храните секрет вне кода, обновляйте токен заранее и дополнительно по факту отказа, повторяйте запрос ровно один раз, защищайте обновление от гонки и делайте отправку ответов через очередь с повтором. Тогда истечение токена перестанет быть событием, о котором узнаёт покупатель.
Если писать и поддерживать этот слой не хочется, посмотрите, как выглядит подключение по официальному доступу без единой строчки кода — здесь.
Если решение под свой бизнес нужно, а разбираться самому некогда — напишите мне в Telegram: @artem_sergeevic. Я делаю такие сервисы на заказ: обсудим задачу и честно разберём, что в ней действительно нужно, а что можно не делать вовсе.