Клиент Moysklad API
Базовый URL: https://api.moysklad.ru/api/remap/1.2/
Vendor API: https://apps-api.moysklad.ru/api/vendor/1.0/
Синхронный клиент
Низкоуровневый (src/moysklad/base.py)
- HTTP-обёртки:
_get,_post,_put,_deleteчерезrequests. - Авторизация: Bearer token (из
Install.access_token) или Basic Auth (login/password). - Заголовок
X-Lognex-Accept-Regionдля узбекской локации. - Обработка ошибок:
MoyskladException,MoyskladUnauthorized,MoyskladTokenExpiredException,MoyskladDocumentNotFoundException,MoyskladFewDocumentsFoundException. - Утилиты:
retry_with_backoff(экспоненциальная задержка, особенно для 429),chain_get(безопасный доступ к dict),chunks(разбиение на пачки по 1000),get_meta/get_href(генерация meta-объектов МойСклад). - Глобальный exception handler в
backend.pyиgui.pyотлавливаетMoyskladTokenExpiredException/MoyskladUnauthorizedи возвращает пользователю сообщение «Переустановите приложение!».
High-level (src/moysklad/entities/base.py)
Обёртки над base.py для CRUD документов: get_document, create_document, update_document, delete_document, get_rows, append_rows, get_documents. Интегрирован с Celery (@app.task).
Асинхронный клиент
src/moysklad/async_/base.py
Класс AsyncMoyskladClient на базе aiohttp.ClientSession. Реализует те же операции (get_documents, create_document, update_document, delete_document, append_rows, get_rows, get_or_create_contract), но полностью асинхронно. Умеет автоматически "докидывать" позиции (>1000 шт.) чанками.
Используется в GUI-страницах и сервисах, где нужен async/await.
Входящие запросы МойСклад: проверка JWT
МойСклад подписывает запросы к эндпоинтам решений JWT HS256 секретом решения
(app.secret_key). Проверка — src/endpoints/vendor_auth.py:
- запросы жизненного цикла (PUT установка, GET статус, DELETE удаление) —
вызов из хендлеров
src/endpoints/vendor.py; - нажатия кнопок (
POST .../apps/{appId}/{accountId}/button, любые решения) — middlewaresrc/endpoints/button/jwt_check.py.
Проверяются подпись, сроки (не дольше 300 с, допуск 60 с) и одноразовость jti
(Redis, ключ vendor-jwt-replay:{app}:{jti}, помечается после успешного ответа).
Результат — строка лога vendor jwt: <результат> <lifecycle|button> <метод> app_uuid=…
и метрика Logfire vendor_jwt_checks (result, kind, app_uuid, from_dev_id, enforce).
| Переменная | По умолчанию | Что делает |
|---|---|---|
VENDOR_JWT_ENFORCE |
выключена | отказ для запросов жизненного цикла: 401 на невалидную подпись, 503 при недоступности проверки |
VENDOR_JWT_ENFORCE_BUTTONS |
выключена | то же для нажатий кнопок, независимо от первой |
Пока переменная выключена, запросы не отклоняются никогда (в том числе при сбое
БД/Redis и по таймауту 3 с) — только пишется результат. Включать после того, как
в логе по всем решениям этого вида только ok: задать переменную в apps.env и
поочерёдно пересоздать backend0 и backend1. Откат — убрать переменную и так же
пересоздать.