Управление токенами =================== AmoCRM выдаёт два токена при OAuth-авторизации: * **access_token** — срок жизни 24 часа. * **refresh_token** — срок жизни 3 месяца; обновляется при каждом refresh. Реактивное обновление по 401 ----------------------------- Это базовое поведение SDK: если API вернул ``401 Unauthorized``, клиент автоматически вызывает :meth:`~amocrm.client.AmoCRM._refresh_tokens` и повторяет исходный запрос один раз. Проактивное обновление по истечению срока ------------------------------------------ При каждом запросе клиент проверяет, не истёк ли (или не истекает ли в ближайшие 60 секунд) access_token. Если да — refresh выполняется *до* отправки запроса, без лишнего 401-цикла. Срок жизни токена определяется так: 1. При инициализации клиента из **JWT-payload** access_token — поле ``exp`` декодируется без проверки подписи. 2. После каждого refresh — из поля ``expires_in`` в ответе AmoCRM API (fallback: 86 400 с / 24 ч). .. code-block:: text _request() вызван │ ├─ expires_at known AND now ≥ expires_at − 60s → _refresh_tokens() │ └─ session.request(...) │ ├─ 401 → _refresh_tokens() → повтор запроса └─ OK → вернуть ответ Хранилище токенов ----------------- Интерфейс :class:`~amocrm.auth.TokenStorage` остался неизменным — ``save(access_token, refresh_token)`` и ``load() → tuple[str, str]``. Время истечения хранится только в памяти клиента и восстанавливается из JWT при каждом создании нового экземпляра :class:`~amocrm.client.AmoCRM`. Встроенные реализации хранилища: .. list-table:: :header-rows: 1 :widths: 30 70 * - Класс - Описание * - :class:`~amocrm.auth.InMemoryTokenStorage` - Хранит токены в атрибутах объекта. Подходит для скриптов и тестов. * - :class:`~amocrm.auth.DjangoTokenStorage` - Хранит токены в полях модели Django и вызывает ``instance.save()``.