ساخت یک API تبدیل ارز با پایتون
ﺯﻣﺎﻥ ﻣﻄﺎﻟﻌﻪ: 8 دقیقه

ساخت یک API تبدیل ارز با پایتون

یک فروشگاه آنلاین را در نظر بگیرید که کاربر وارد صفحه محصول می‌شود و قیمت را هم به تومان می‌بیند، هم به دلار، هم به یورو. پشت این ظاهر ساده، یک مسئله جدی وجود دارد: این نرخ‌ها از کجا می‌آیند و چطور همیشه به‌روز می‌مانند؟

در دنیای واقعی، این داده‌ها از سرویس‌های خارجی دریافت می‌شوند، APIهایی که نرخ ارز را از بازارهای مختلف جمع‌آوری و در اختیار توسعه‌دهنده‌ها قرار می‌دهند. اما مشکل اصلی اینجاست که این APIها به‌تنهایی برای استفاده در یک اپلیکیشن کافی نیستند. چرا که نیاز است یک لایه واسط ساخته شود، سرویسی که داده خام را بگیرد، آن را پردازش کند و به شکلی ساده و قابل استفاده در اختیار کلاینت قرار دهد.

در این مطلب قصد داریم دقیقا همین کار را انجام می‌دهیم: یک API تبدیل ارز با پایتون می‌سازیم که به یک سرویس خارجی متصل می‌شود و آن را به یک سرویس تمیز، قابل استفاده و مناسب برای پروژه‌های واقعی تبدیل می‌کند.

طراحی API تبدیل ارز

پیش از نوشتن کد، بهتر است مشخص کنیم API قرار است چه کاری انجام دهد. در این پروژه، هدف ساخت یک سرویس ساده است که مقدار مشخصی از یک ارز را دریافت کند و معادل آن را بر اساس نرخ روز در ارز دیگری برگرداند.

برای این منظور، یک Endpoint با متد GET در نظر می‌گیریم:

GET /convert?from=USD&to=EUR&amount=100

در این درخواست، سه پارامتر از کاربر دریافت می‌شود:

  • from: ارز مبدا

  • to: ارز مقصد

  • amount: مبلغی که باید تبدیل شود

در صورت موفقیت، API پاسخی مشابه نمونه زیر برمی‌گرداند:

{
  "from": "USD",
  "to": "EUR",
  "amount": 100,
  "rate": 0.86,
  "result": 86
}

جریان پردازش این درخواست نیز بسیار ساده است. پس از دریافت پارامترها، API یک درخواست به سرویس نرخ ارز ارسال می‌کند، نرخ تبدیل را از پاسخ استخراج می‌کند، مبلغ نهایی را محاسبه کرده و نتیجه را در قالب JSON به کلاینت بازمی‌گرداند.

با مشخص شدن ورودی‌ها، خروجی‌ها و نحوه پردازش درخواست، می‌توان وارد مرحله راه‌اندازی پروژه و پیاده‌سازی API شد.

انتخاب سرویس دریافت نرخ ارز

مهم‌ترین بخش این پروژه، انتخاب یک سرویس معتبر برای دریافت نرخ ارز است. این سرویس باید API ساده، مستندات مناسب و محدودیت‌های منطقی برای نسخه رایگان داشته باشد تا بتوان از آن در پروژه‌های آموزشی و شخصی استفاده کرد.

چند سرویس محبوب در این زمینه عبارت‌اند از:

سرویس نسخه رایگان نیاز به API Key ویژگی
ExchangeRate-API دارد خیر راه‌اندازی سریع و مناسب برای پروژه‌های آموزشی
Fixer دارد بله داده‌های دقیق و امکانات بیشتر
Open Exchange Rates دارد بله مناسب برای پروژه‌های حرفه‌ای و تجاری

در این مطلب از ExchangeRate-API استفاده می‌کنیم. این سرویس برای شروع نیازی به پیکربندی پیچیده ندارد و با ارسال یک درخواست HTTP، نرخ تبدیل بین ارزهای مختلف را در قالب JSON برمی‌گرداند.

نمونه درخواست:

GET https://open.er-api.com/v6/latest/USD

نمونه پاسخ:

{
  "result": "success",
  "base_code": "USD",
  "rates": {
    "EUR": 0.86,
    "GBP": 0.74,
    "JPY": 146.53
  }
}

در ادامه پروژه، API پایتون این اطلاعات را از سرویس دریافت می‌کند، نرخ ارز موردنظر را استخراج کرده و نتیجه نهایی تبدیل را در قالب یک API ساده در اختیار کلاینت قرار می‌دهد.

راه‌اندازی پروژه

در این مقاله از FastAPI برای ساخت API استفاده می‌کنیم. FastAPI علاوه بر عملکرد بالا، امکاناتی مانند اعتبارسنجی خودکار داده‌ها، تولید مستندات API و پشتیبانی از برنامه‌نویسی ناهمگام را نیز در اختیار ما قرار می‌دهد.

ابتدا یک پوشه برای پروژه ایجاد کرده و محیط مجازی را فعال کنید:

mkdir currency-api
cd currency-api

python -m venv venv

سپس محیط مجازی را فعال کنید:

Windows

venv\Scripts\activate

Linux / macOS

source venv/bin/activate

اکنون پکیج‌های موردنیاز را نصب کنید:

pip install fastapi uvicorn requests

ساختار پروژه نیز به شکل زیر خواهد بود:

currency-api/
│── main.py
│── requirements.txt
└── venv/

در این ساختار، تمام منطق API را در فایل main.py پیاده‌سازی می‌کنیم. پس از آماده شدن محیط توسعه، در مرحله بعد اولین Endpoint را ایجاد کرده و آن را به سرویس دریافت نرخ ارز متصل خواهیم کرد.

پیاده‌سازی API تبدیل ارز

اکنون زمان ساخت اولین Endpoint است. این Endpoint سه پارامتر from ،to و amount را از کاربر دریافت می‌کند، نرخ ارز را از سرویس خارجی می‌خواند و نتیجه تبدیل را به‌صورت JSON برمی‌گرداند.

ابتدا فایل main.py را ایجاد کرده و کد زیر را در آن قرار دهید:

from fastapi import FastAPI, HTTPException
import requests

app = FastAPI()


@app.get("/convert")
def convert(from_currency: str, to_currency: str, amount: float):

    url = f"https://open.er-api.com/v6/latest/{from_currency}"

    response = requests.get(url)

    if response.status_code != 200:
        raise HTTPException(status_code=500, detail="Failed to fetch exchange rates")

    data = response.json()

    rate = data["rates"].get(to_currency)

    if rate is None:
        raise HTTPException(status_code=404, detail="Currency not found")

    return {
        "from": from_currency,
        "to": to_currency,
        "amount": amount,
        "rate": rate,
        "result": round(amount * rate, 2)
    }

اکنون سرور را اجرا کنید:

uvicorn main:app --reload

پس از اجرای برنامه، می‌توانید درخواست زیر را ارسال کنید:

GET http://127.0.0.1:8000/convert?from_currency=USD&to_currency=EUR&amount=100

در صورت موفقیت، پاسخی مشابه نمونه زیر دریافت خواهید کرد:

{
  "from": "USD",
  "to": "EUR",
  "amount": 100,
  "rate": 0.86,
  "result": 86
}

اگر دقت کنید، تمام منطق تبدیل ارز در چند مرحله ساده خلاصه می‌شود: دریافت پارامترها، ارسال درخواست به سرویس خارجی، استخراج نرخ تبدیل و محاسبه مبلغ نهایی. در پروژه‌های واقعی، معمولا این کد در لایه‌های مختلف مانند Service و Repository سازمان‌دهی می‌شود، اما برای درک فرآیند، پیاده‌سازی آن در یک فایل کافی است.

مدیریت خطاها و اعتبارسنجی درخواست‌ها

یک API نباید تنها در شرایط ایده‌آل کار کند، بلکه باید بتواند خطاها را نیز به‌درستی مدیریت کند. برای مثال، ممکن است کاربر کد ارزی نامعتبر ارسال کند، سرویس خارجی در دسترس نباشد یا درخواست با تاخیر مواجه شود.

یکی از اولین بهبودها، تعیین زمان انتظار (Timeout) برای درخواست به سرویس خارجی است تا در صورت عدم پاسخ‌گویی، برنامه برای مدت طولانی متوقف نشود:

response = requests.get(url, timeout=5)

همچنین بهتر است خطاهای مربوط به ارتباط با سرویس خارجی را مدیریت کنیم:

try:
    response = requests.get(url, timeout=5)
    response.raise_for_status()
except requests.RequestException:
    raise HTTPException(
        status_code=503,
        detail="Exchange rate service is unavailable"
    )

اعتبارسنجی ورودی‌ها نیز اهمیت زیادی دارد. برای مثال، مبلغ تبدیل نباید صفر یا منفی باشد. FastAPI این کار را با استفاده از Query به‌سادگی انجام می‌دهد:

from fastapi import Query

@app.get("/convert")
def convert(
    from_currency: str,
    to_currency: str,
    amount: float = Query(gt=0)
):
    ...

با این تغییر، اگر مقدار amount کمتر یا مساوی صفر باشد، FastAPI به‌صورت خودکار یک پاسخ با وضعیت 400 برمی‌گرداند و نیازی به نوشتن کد اضافی برای این اعتبارسنجی نخواهد بود.

مدیریت خطاها و اعتبارسنجی ورودی‌ها باعث می‌شود API قابل اعتمادتر باشد و کلاینت‌ها نیز در صورت بروز مشکل، پاسخ‌های استاندارد و قابل پیش‌بینی دریافت کنند.

بهینه‌سازی API

نسخه‌ای که تا اینجا ساختیم، برای هر درخواست یک بار به سرویس خارجی متصل می‌شود. این روش در پروژه‌های کوچک قابل قبول است، اما با افزایش تعداد درخواست‌ها، هم زمان پاسخ‌گویی بیشتر می‌شود و هم احتمال رسیدن به محدودیت تعداد درخواست‌های API خارجی افزایش پیدا می‌کند.

یکی از راهکارهای رایج، کش کردن نرخ ارزها است. به‌جای دریافت نرخ‌ها در هر درخواست، می‌توان آن‌ها را برای چند دقیقه در حافظه نگه داشت و تا پایان اعتبار کش، همان داده‌ها را به کاربران بازگرداند. این کار تعداد درخواست‌ها به سرویس خارجی را به‌شدت کاهش می‌دهد.

اگر API از کاربران زیادی درخواست دریافت می‌کند، استفاده از درخواست‌های ناهمگام (Asynchronous) نیز می‌تواند عملکرد آن را بهبود دهد. در FastAPI می‌توان به‌جای کتابخانه requests از httpx استفاده کرد تا برنامه هنگام انتظار برای پاسخ سرویس خارجی، بتواند درخواست‌های دیگری را نیز پردازش کند.

در نهایت، اگر قرار است این API در محیط Production اجرا شود، بهتر است اطلاعاتی مانند آدرس سرویس خارجی، API Key و مدت‌زمان اعتبار کش را در متغیرهای محیطی نگهداری کنید. این کار علاوه بر افزایش امنیت، مدیریت تنظیمات پروژه را نیز ساده‌تر می‌کند.

با همین چند تغییر، API از یک نمونه آموزشی ساده به سرویسی نزدیک‌تر به استانداردهای پروژه‌های واقعی تبدیل می‌شود.

تست API

پس از پیاده‌سازی، بهتر است عملکرد API را در سناریوهای مختلف بررسی کنید. این کار کمک می‌کند مطمئن شوید Endpoint تنها در شرایط عادی نیست، بلکه در مواجهه با ورودی‌های نامعتبر و خطاهای احتمالی نیز رفتار درستی دارد.

اگر سرور را اجرا کرده باشید، مستندات تعاملی FastAPI در آدرس زیر در دسترس خواهد بود:

http://127.0.0.1:8000/docs

در این صفحه می‌توانید Endpointها را بدون نیاز به ابزار جانبی اجرا کنید، پارامترهای مختلف را تغییر دهید و پاسخ API را مشاهده کنید.

علاوه بر آن، تست API با ابزارهایی مانند Postman یا curl نیز امکان‌پذیر است. برای مثال، دستور زیر یک درخواست برای تبدیل ۱۰۰ دلار به یورو ارسال می‌کند:

curl "http://127.0.0.1:8000/convert?from_currency=USD&to_currency=EUR&amount=100"

در کنار تست موفق، بهتر است سناریوهای زیر را نیز بررسی کنید:

  • ارسال کد ارز نامعتبر مانند ABC

  • ارسال مبلغ صفر یا منفی

  • قطع بودن سرویس دریافت نرخ ارز

  • ارسال پارامترهای ناقص یا با نوع داده اشتباه

بررسی این سناریوها کمک می‌کند پیش از انتشار API، خطاهای احتمالی شناسایی شوند و کلاینت‌ها در هر شرایطی پاسخ‌های قابل پیش‌بینی و استاندارد دریافت کنند.

جمع‌بندی

در این مقاله یک API تبدیل ارز با FastAPI ساختیم که به یک سرویس خارجی متصل می‌شود، نرخ ارز را دریافت می‌کند و نتیجه را به‌صورت یک API ساده در اختیار کلاینت قرار می‌دهد.

این پروژه نمونه‌ای از الگوی رایج در توسعه بک‌اند است: دریافت داده از سرویس خارجی، پردازش آن و ارائه خروجی استاندارد. همین ساختار در بسیاری از سرویس‌های واقعی استفاده می‌شود. در صورت توسعه بیشتر، این API می‌تواند به یک سرویس پایدارتر با قابلیت‌هایی مثل کش، احراز هویت و مدیریت چند منبع داده تبدیل شود.

چه امتیازی برای این مقاله میدهید؟

خیلی بد
بد
متوسط
خوب
عالی
در انتظار ثبت رای

/@arastoo
ارسطو عباسی
کارشناس تست نرم‌افزار و مستندات

...

دیدگاه و پرسش
برای ارسال دیدگاه لازم است وارد شده یا ثبت‌نام کنید ورود یا ثبت‌نام

در حال دریافت نظرات از سرور، لطفا منتظر بمانید

در حال دریافت نظرات از سرور، لطفا منتظر بمانید

ارسطو عباسی

کارشناس تست نرم‌افزار و مستندات