from decimal import Decimal from contextlib import suppress from urllib.parse import urljoin import requests from django.conf import settings class CurrencyAPIClient: CONVERT_ENDPOINT = 'currency/convert' MAX_RETRIES = 2 def __init__(self, api_key: str): self.api_url = 'https://api.getgeoapi.com/v2/' self.api_key = api_key self.session = requests.Session() def request(self, method, url, *args, **kwargs): params = kwargs.pop('params', {}) params.update({"api_key": self.api_key}) joined_url = urljoin(self.api_url, url) request = requests.Request(method, joined_url, params=params, *args, **kwargs) retries = 0 while retries < self.MAX_RETRIES: retries += 1 prepared = self.session.prepare_request(request) r = self.session.send(prepared, timeout=settings.EXTERNAL_API_TIMEOUT_SEC) # TODO: handle/log errors return r def get_rate(self, currency1: str, currency2: str, amount=1): params = { 'from': currency1, 'to': currency2, 'amount': amount, 'format': 'json' } r = self.request('GET', self.CONVERT_ENDPOINT, params=params) if not r or r.json().get('status') == 'failed': return None with suppress(KeyError): rate = r.json()['rates'][currency2.upper()]['rate'] return Decimal(rate) return None def get_cny_rate(self): return self.get_rate('cny', 'rub') client = CurrencyAPIClient(settings.CURRENCY_GETGEOIP_API_KEY)