علی زاهدی گل
علی زاهدی گل
خواندن ۷ دقیقه·۴ سال پیش

پیاده سازی درگاه پرداخت بانک های مختلف با پایتون

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

البته که بعضی از بانک ها هستند که در حال حاضر روی این پروژه پورت نشدن که شما می تونید خودتون در توسعه اش نقش داشته باشید و یا اگر وقت و حوصله کافی برای این کار رو ندارید می تونید از طریق قسمت Issues یک Issue مرتبط باز کنید تا بانک مورد نظر اضافه بشه.

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

درگاه پرداخت بانک ملی ایران (BMI)

درگاه پرداخت بانک سامان (SEP)

درگاه پرداخت زرین پال

درگاه پرداخت آی دی پی (IDPay)

درگاه پرداخت زیبال

درگاه پرداخت باهمتا

درگاه پرداخت بانک ملت (‌به پرداخت)

برای پیاده سازی و اتصال به درگاه بانک ها کافی ه که پکیج رو نصب کنید و اون رو به عنوان یک اپ در پروژه جنگو تون معرفی کنید.

pip install az-iranian-bank-gateways

بعد از نصب توسط پکیج منیجر اون رو در فایل ستینگ پروژه به عنوان اپ نصب شده معرفی می کنیم.

INSTALLED_APPS = [ # .... 'azbankgateways', # ... ]

در فایل تنظیمات، درگاه های مورد نظرمون رو تنظیم می کنیم.

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

AZ_IRANIAN_BANK_GATEWAYS = { 'GATEWAYS': { 'BMI': { 'MERCHANT_CODE': '<YOUR MERCHANT CODE>', 'TERMINAL_CODE': '<YOUR TERMINAL CODE>', 'SECRET_KEY': '<YOUR SECRET CODE>', }, 'SEP': { 'MERCHANT_CODE': '<YOUR MERCHANT CODE>', 'TERMINAL_CODE': '<YOUR TERMINAL CODE>', }, }, 'DEFAULT': 'BMI', 'BANK_PRIORITIES': [ 'BMI', 'SEP', # and so on ... ], }

البته که ممکنه توی پروژه من از واحد ریال یا تومان استفاده کنم که اون هم قابل تنظیم هست و فقط باید یک پارامتر دیگه رو به فایل تنظیماتم اضافه کنم.

'CURRENCY': 'IRR',

تنظیمات دیگه ای هم هست که واقعا از حوصله ی این پست خارجه که البته سعی کردم در مستندات خود پروژه بهشون اشاره بکنم. البته که باز هم بنظرم یک سری بخش ها مثل خوندن از طریق یک کلاس دیگر که هر کسی بتونه اون رو به هر روشی که دوست داره شخصی سازی کنه، مثلا شما دوست ندارید که کلید های امنیتی رو از اینجا تعیین کنید، می تونید اون ها رو از طریق کلاسی که خودتون تعریفش می کنید بخونه، پس در بخش تنظیمات معرفی کنید و پکیج می ره سراغ اون کلاس و از اون سوال می کنه، یا اینکه بتونید به ازای هر پرداخت تنظیمات مختلفی رو بدید مثل اینکه ممکن ه شما دو درگاه بانک ملی داشته باشید یا حالت هایی از این قبیل که احتمالا موارد کم کاربردی هستند ولی در پروژه پیش بینی شده که البته این ها رو در مستندات پروژه خیلی خلاصه نوشتم که در آینده اگر زمان بود حتما سعی می کنم یک ویدئو آماده کنم و به اشتراک بگذارم.

از بحث دور نشیم.

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

from django.contrib import admin from django.urls import path from azbankgateways.urls import az_bank_gateways_urls admin.autodiscover() urlpatterns = [ path('admin/', admin.site.urls), path('bankgateways/', az_bank_gateways_urls()), ]

تنها کاری که موند این هست که به دیتا بیس بگیم خودش و آماده کنه برای درگاه ها.

python manage.py migrate

حالا میخوایم کاربر رو به بانک بفرستیم چیکار کنیم؟

می گیم این مبلغ و پرداخت کن. البته که می تونم شماره موبایل کاربر رو هم بفرستم که اگر روی شماره موبایلش کارتی تنظیم شده بود لیست کارت ها رو بانک در زمان پرداخت بهش نمایش بده.

from django.urls import reverse from azbankgateways import bankfactories, models as bank_models, default_settings as settings def go_to_gateway_view(request): # خواندن مبلغ از هر جایی که مد نظر است amount = 1000 # تنظیم شماره موبایل کاربر از هر جایی که مد نظر است user_mobile_number = '+989112221234' # اختیاری factory = bankfactories.BankFactory() bank = factory.create() bank.set_request(request) bank.set_amount(amount) # یو آر ال بازگشت به نرم افزار برای ادامه فرآیند bank.set_client_callback_url(reverse('callback-gateway')) bank.set_mobile_number(user_mobile_number) # اختیاری bank_record = bank.ready() # هدایت کاربر به درگاه بانک return bank.redirect_gateway()

البته که باید یه آدرس برگشت هم بهش بدیم که بدونه بعد از اینکه پرداخت تموم شد و عملیات تایید و این ها اتفاق افتاد کجا برگرده و بهمون خبر بده. که از این bank.set_client_callback_url(reverse('callback-gateway')) استفاده کردیم.

همینجا این رو هم اضافه کنم که، فرض کنیم کاربر گفته می خوام از بین چند بانکی که داری به بانک سامان من و متصل کن و پرداخت و از اون طریق انجام بده، کافیه که به جای

bank = factory.create()

کد زیر رو بزاریم

factory.create(bank_models.BankType.SEP)

و اون موقع است که به جای بانک پیش فرض، مستقیم به بانک سامان متصل میشه.


حالا اگر می خواستیم خودش به ترتیبی که توی تنظیمات، تنظیمات و انجام داده بودیم به درگاه ها متصل می شد تا اولین درگاه در دسترس رو پیدا کنه کافی بود به جای این

bank = factory.create()

کد زیر رو میزاشتیم.

bank = factory.auto_create()


حالا فکر کنید از بانک برگشتیم چه طوری میفهیم که پرداخت انجام شده یا نه، خیلی راحت.

import logging from django.http import HttpResponse, Http404 from django.urls import reverse from azbankgateways import bankfactories, models as bank_models, default_settings as settings def callback_gateway_view(request): tracking_code = request.GET.get(settings.TRACKING_CODE_QUERY_PARAM, None) if not tracking_code: logging.debug(&quotاین لینک معتبر نیست.&quot) raise Http404 try: bank_record = bank_models.Bank.objects.get(tracking_code=tracking_code) except bank_models.Bank.DoesNotExist: logging.debug(&quotاین لینک معتبر نیست.&quot) raise Http404 # در این قسمت باید از طریق داده هایی که در بانک رکورد وجود دارد، رکورد متناظر یا هر اقدام مقتضی دیگر را انجام دهیم if bank_record.is_success: # پرداخت با موفقیت انجام پذیرفته است و بانک تایید کرده است. # می توانید کاربر را به صفحه نتیجه هدایت کنید یا نتیجه را نمایش دهید. return HttpResponse(&quotپرداخت با موفقیت انجام شد.&quot) # پرداخت موفق نبوده است. اگر پول کم شده است ظرف مدت ۴۸ ساعت پول به حساب شما بازخواهد گشت. return HttpResponse(&quotپرداخت با شکست مواجه شده است. اگر پول کم شده است ظرف مدت ۴۸ ساعت پول به حساب شما بازخواهد گشت.&quot)

و تمام!


البته که شما می تونین این قسمت ها رو با سناریوی خودتون بنویسید، من سعی کردم تا جای ممکن ساده و بدون پیچیدگی بنویسم.


امیدوارم در زمان و انرژی تون صرفه جویی کرده باشه و بتونین تمرکز بیشتری رو روی کارهای خودتون بزارین.

اگر درگاهی رو پشتیبانی نکردیم یا اگر موردی رو دیدید خیلی خوبه که رفعش کنید یا اضافه اش کنید ولی اگر به هر دلیلی وقتش رو ندارید حداقل می تونید از طریق Issue ها در گیت های پروژه بقیه رو از وجود اون ها مطلع کنید.


آدرس پروژه https://github.com/ali-zahedi/az-iranian-bank-gateways

آدرس ویدئو آموزشی در آکادمی ژاک

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