"""카페24 연동 공통 계층 (상품관리 + 향후 주문관리 공유). 구성 config.py 환경변수 → Cafe24Config (하드코딩 금지) crypto.py 토큰 Fernet 암복호화 oauth.py 인증 URL / code→token / refresh tokens.py TokenService — 저장·만료판정·자동갱신(행 잠금) client.py Cafe24Client — 전송·재시도·429/5xx·API 로그 products.py 상품 엔드포인트 래퍼 errors.py 공통 예외 사용 예 (모듈 라우터에서): from app.integrations.cafe24 import build_cafe24_api api = build_cafe24_api(store) # store = Cafe24Store html = products.get_description(api.client, 123) CAFE24_* 환경변수가 없어도 import 는 성공한다. 실제 호출 시점에 Cafe24ConfigError 가 나며, 라우터가 "설정 필요" 안내를 보여준다. """ from __future__ import annotations from dataclasses import dataclass from typing import Any from . import products from .client import Cafe24Client from .config import ( ORDER_SCOPES, PRODUCT_SCOPES, Cafe24Config, load_config, ) from .errors import ( Cafe24ApiError, Cafe24AuthError, Cafe24ConfigError, Cafe24Error, Cafe24RateLimitError, ) from .oauth import TokenBundle, build_authorize_url, exchange_code, new_state, refresh_tokens from .tokens import TokenService __all__ = [ "Cafe24Api", "build_cafe24_api", "Cafe24Client", "Cafe24Config", "TokenService", "TokenBundle", "load_config", "build_authorize_url", "exchange_code", "refresh_tokens", "new_state", "products", "PRODUCT_SCOPES", "ORDER_SCOPES", "Cafe24Error", "Cafe24ConfigError", "Cafe24AuthError", "Cafe24RateLimitError", "Cafe24ApiError", ] @dataclass(frozen=True) class Cafe24Api: """설정 + 토큰서비스 + 클라이언트 묶음. 라우터/worker 가 이것만 들고 다닌다.""" config: Cafe24Config tokens: TokenService client: Cafe24Client def build_cafe24_api(store: Any, *, scopes: tuple[str, ...] = PRODUCT_SCOPES) -> Cafe24Api: """Cafe24Store 를 저장소로 쓰는 API 묶음 생성. store 는 토큰 3개 메서드(get_token_row/save_token_row/token_lock)와 API 로그 기록용 log_api_call 을 제공해야 한다. """ config = load_config(scopes=scopes) token_service = TokenService(store, config) client = Cafe24Client( config, token_service, api_logger=getattr(store, "log_api_call", None), ) return Cafe24Api(config=config, tokens=token_service, client=client)