유효하지 않은 KEY 가 설정되어 있어도, 일단 UI 페이지가 나오도록 수정.
This commit is contained in:
BIN
app/core/__pycache__/__init__.cpython-313.pyc
Normal file
BIN
app/core/__pycache__/__init__.cpython-313.pyc
Normal file
Binary file not shown.
BIN
app/core/__pycache__/auth.cpython-313.pyc
Normal file
BIN
app/core/__pycache__/auth.cpython-313.pyc
Normal file
Binary file not shown.
BIN
app/core/__pycache__/config.cpython-313.pyc
Normal file
BIN
app/core/__pycache__/config.cpython-313.pyc
Normal file
Binary file not shown.
BIN
app/core/__pycache__/database.cpython-313.pyc
Normal file
BIN
app/core/__pycache__/database.cpython-313.pyc
Normal file
Binary file not shown.
BIN
app/core/__pycache__/logger.cpython-313.pyc
Normal file
BIN
app/core/__pycache__/logger.cpython-313.pyc
Normal file
Binary file not shown.
BIN
app/core/__pycache__/rate_limiter.cpython-313.pyc
Normal file
BIN
app/core/__pycache__/rate_limiter.cpython-313.pyc
Normal file
Binary file not shown.
@@ -28,12 +28,21 @@ class TokenManager:
|
||||
self._rate_limiter = RateLimiter(requests_per_second=1.0)
|
||||
self._lock = asyncio.Lock()
|
||||
self._client = httpx.AsyncClient(timeout=10.0)
|
||||
self._authenticated: bool = False
|
||||
|
||||
@property
|
||||
def is_authenticated(self) -> bool:
|
||||
return self._authenticated
|
||||
|
||||
@property
|
||||
def is_vps(self) -> bool:
|
||||
return settings.kis.server_mode == "vps"
|
||||
|
||||
async def _request_token(self) -> None:
|
||||
if not settings.kis.app_key or not settings.kis.app_secret:
|
||||
logger.debug("API 키가 설정되지 않음")
|
||||
return
|
||||
|
||||
url = f"{get_base_url()}{_TOKEN_URL}"
|
||||
payload = {
|
||||
"grant_type": "client_credentials",
|
||||
@@ -41,15 +50,22 @@ class TokenManager:
|
||||
"appsecret": settings.kis.app_secret,
|
||||
}
|
||||
resp = await self._client.post(url, json=payload)
|
||||
resp.raise_for_status()
|
||||
data = resp.json()
|
||||
|
||||
if resp.status_code != 200 or "access_token" not in data:
|
||||
logger.warning("토큰 발급 실패: %s", data.get("message", resp.status_code))
|
||||
return
|
||||
|
||||
self._access_token = data["access_token"]
|
||||
expires_in = int(data.get("expires_in", 7776000))
|
||||
self._token_expires_at = datetime.now() + timedelta(seconds=expires_in)
|
||||
self._authenticated = True
|
||||
logger.info("REST access_token 발급 완료 (만료: %s)", self._token_expires_at)
|
||||
|
||||
async def _request_approval_key(self) -> None:
|
||||
if not settings.kis.app_key or not settings.kis.app_secret:
|
||||
return
|
||||
|
||||
url = f"{get_base_url()}{_APPROVAL_URL}"
|
||||
payload = {
|
||||
"grant_type": "client_credentials",
|
||||
@@ -57,9 +73,12 @@ class TokenManager:
|
||||
"secretkey": settings.kis.app_secret,
|
||||
}
|
||||
resp = await self._client.post(url, json=payload)
|
||||
resp.raise_for_status()
|
||||
data = resp.json()
|
||||
|
||||
if resp.status_code != 200 or "approval_key" not in data:
|
||||
logger.warning("approval_key 발급 실패: %s", data.get("message", resp.status_code))
|
||||
return
|
||||
|
||||
self._approval_key = data["approval_key"]
|
||||
self._approval_expires_at = datetime.now() + timedelta(hours=23, minutes=50)
|
||||
logger.info("WebSocket approval_key 발급 완료 (만료: %s)", self._approval_expires_at)
|
||||
@@ -85,7 +104,8 @@ class TokenManager:
|
||||
"appsecret": settings.kis.app_secret,
|
||||
}
|
||||
resp = await self._client.post(url, json=data, headers=headers)
|
||||
resp.raise_for_status()
|
||||
if resp.status_code != 200:
|
||||
raise RuntimeError(f"hashkey 생성 실패: {resp.status_code}")
|
||||
return resp.json()["HASH"]
|
||||
|
||||
def get_auth_headers(self, tr_id: str) -> dict[str, str]:
|
||||
|
||||
Reference in New Issue
Block a user