Vastai-ConnectHub/app/integrations/seeyon.py

81 lines
2.6 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

from __future__ import annotations
import logging
from typing import Any
import httpx
from app.integrations.base import BaseClient
logger = logging.getLogger("connecthub.integrations.seeyon")
class SeeyonClient(BaseClient):
"""
致远 OA REST Client
- POST /seeyon/rest/token 获取 tokenid
- 业务请求 header 自动携带 token
- 遇到 401/Invalid token 自动刷新 token 并重试一次
"""
def __init__(self, *, base_url: str, rest_user: str, rest_password: str, loginName: str | None = None) -> None:
super().__init__(base_url=base_url)
self.rest_user = rest_user
self.rest_password = rest_password
self.loginName = loginName
self._token: str | None = None
def authenticate(self) -> str:
body: dict[str, Any] = {
"userName": self.rest_user,
"password": self.rest_password,
}
if self.loginName:
body["loginName"] = self.loginName
# 文档POST /seeyon/rest/token
resp = super().request(
"POST",
"/seeyon/rest/token",
json=body,
headers={"Accept": "application/json", "Content-Type": "application/json"},
)
data = resp.json()
token = str(data.get("id", "") or "")
if not token or token == "-1":
raise RuntimeError("Seeyon auth failed (token id missing or -1)")
self._token = token
logger.info("Seeyon token acquired")
return token
def _get_token(self) -> str:
return self._token or self.authenticate()
def request(self, method: str, path: str, **kwargs: Any) -> httpx.Response: # type: ignore[override]
token = self._get_token()
headers = dict(kwargs.pop("headers", {}) or {})
headers["token"] = token
try:
return super().request(method, path, headers=headers, **kwargs)
except httpx.HTTPStatusError as e:
# token 失效401 或返回包含 Invalid token
resp = e.response
text = ""
try:
text = resp.text or ""
except Exception:
text = ""
if resp.status_code == 401 or ("Invalid token" in text):
logger.info("Seeyon token invalid, refreshing and retrying once")
self._token = None
token2 = self._get_token()
headers["token"] = token2
# 仅重试一次;仍失败则抛出
return super().request(method, path, headers=headers, **kwargs)
raise