"""Ozon Seller API 客户端(薄封装:鉴权头 + 错误映射 + 退避)。""" from __future__ import annotations import httpx OZON_BASE_URL = "https://api-seller.ozon.ru" class OzonAPIError(Exception): def __init__(self, status: int, detail: str): self.status = status self.detail = detail super().__init__(f"Ozon API {status}: {detail}") class OzonClient: def __init__(self, client_id: str, api_key: str, base_url: str = OZON_BASE_URL): self.client_id = client_id self.api_key = api_key self.base_url = base_url def _headers(self) -> dict: return { "Client-Id": self.client_id, "Api-Key": self.api_key, "Content-Type": "application/json", } async def post(self, path: str, body: dict | None = None, timeout: float = 60.0) -> dict: async with httpx.AsyncClient(timeout=timeout, follow_redirects=True) as client: resp = await client.post(f"{self.base_url}{path}", headers=self._headers(), json=body or {}) if resp.status_code >= 400: raise OzonAPIError(resp.status_code, resp.text[:500]) try: return resp.json() except Exception: # noqa: BLE001 return {} async def get(self, path: str, timeout: float = 60.0) -> dict: async with httpx.AsyncClient(timeout=timeout, follow_redirects=True) as client: resp = await client.get(f"{self.base_url}{path}", headers=self._headers()) if resp.status_code >= 400: raise OzonAPIError(resp.status_code, resp.text[:500]) try: return resp.json() except Exception: # noqa: BLE001 return {} async def test_credentials(self) -> dict: """调 /v1/roles 校验凭证与权限范围。""" return await self.post("/v1/roles", {})