"""Python 3.10+. Standard library only; use on your server.""" import json import os import re from urllib.error import HTTPError from urllib.request import Request, urlopen API = "https://api.sendwich.kr" class SendwichError(Exception): def __init__(self, status, code, request_id): super().__init__(f"sendwich: {code} ({status})") self.status, self.code, self.request_id = status, code, request_id def _request(path, method="GET", body=None, idempotency_key=None): key = os.environ["SENDWICH_API_KEY"] headers = {"Authorization": f"Bearer {key}"} if body is not None: headers["Content-Type"] = "application/json" if idempotency_key: headers["Idempotency-Key"] = idempotency_key data = json.dumps(body).encode("utf-8") if body is not None else None try: with urlopen(Request(API + path, data=data, headers=headers, method=method), timeout=10) as response: return json.load(response) except HTTPError as error: with error: try: detail = json.load(error).get("error", {}) except (ValueError, AttributeError): detail = {} raise SendwichError(error.code, detail.get("code", "request_failed"), detail.get("request_id") or error.headers.get("X-Request-ID")) from None def create_verification(body, idempotency_key): if not re.fullmatch(r"[A-Za-z0-9_.:-]{8,128}", idempotency_key): raise ValueError("Provide a stable Idempotency-Key for this attempt") return _request("/v1/verifications", "POST", body, idempotency_key) def _session_path(verification_id): if not re.fullmatch(r"vrf_[A-Za-z0-9_-]+", verification_id): raise ValueError("Invalid verification ID") return "/v1/verifications/" + verification_id def get_verification(verification_id): return _request(_session_path(verification_id)) def cancel_verification(verification_id): return _request(_session_path(verification_id) + "/cancel", "POST")