diff --git a/.editorconfig b/.editorconfig old mode 100644 new mode 100755 diff --git a/.github/workflows/linters.yaml b/.github/workflows/linters.yaml old mode 100644 new mode 100755 diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml old mode 100644 new mode 100755 diff --git a/.gitignore b/.gitignore old mode 100644 new mode 100755 diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml old mode 100644 new mode 100755 diff --git a/.releaserc.yaml b/.releaserc.yaml old mode 100644 new mode 100755 diff --git a/.yamllint.yml b/.yamllint.yml old mode 100644 new mode 100755 diff --git a/LICENSE b/LICENSE old mode 100644 new mode 100755 diff --git a/MANIFEST.in b/MANIFEST.in old mode 100644 new mode 100755 diff --git a/README.md b/README.md old mode 100644 new mode 100755 index 2c01d0a..b81f205 --- a/README.md +++ b/README.md @@ -31,6 +31,8 @@ 1. [درگاه پی ورژن ۱](https://www.pay.ir/) + 1. [درگاه آسان پرداخت ](https://asanpardakht.ir/) + [[_TOC_]]

آموزشی

@@ -96,6 +98,11 @@ "MERCHANT_CODE": "", "X_SANDBOX": 0, # 0 disable, 1 active }, + "ASANPARDAKHT": { # اضافه کردن آسان پرداخت + "MERCHANT_CONFIGURATION_ID": "", + "USERNAME": "", + "PASSWORD": "", + }, }, "IS_SAMPLE_FORM_ENABLE": True, # اختیاری و پیش فرض غیر فعال است "DEFAULT": "BMI", diff --git a/azbankgateways/__init__.py b/azbankgateways/__init__.py old mode 100644 new mode 100755 diff --git a/azbankgateways/admin.py b/azbankgateways/admin.py old mode 100644 new mode 100755 diff --git a/azbankgateways/apps.py b/azbankgateways/apps.py old mode 100644 new mode 100755 diff --git a/azbankgateways/bankfactories.py b/azbankgateways/bankfactories.py old mode 100644 new mode 100755 diff --git a/azbankgateways/banks/__init__.py b/azbankgateways/banks/__init__.py old mode 100644 new mode 100755 diff --git a/azbankgateways/banks/asanpardakht.py b/azbankgateways/banks/asanpardakht.py new file mode 100755 index 0000000..fdb67a3 --- /dev/null +++ b/azbankgateways/banks/asanpardakht.py @@ -0,0 +1,195 @@ +import logging +import requests +from azbankgateways.banks import BaseBank +from azbankgateways.exceptions import ( + BankGatewayConnectionError, + BankGatewayRejectPayment, + SettingDoesNotExist, +) +from azbankgateways.models import BankType, CurrencyEnum, PaymentStatus +from azbankgateways.utils import get_json + + +class AsanPardakht(BaseBank): + _merchant_configuration_id = None + _username = None + _password = None + + def __init__(self, **kwargs): + super(AsanPardakht, self).__init__(**kwargs) + + self.set_gateway_currency(CurrencyEnum.IRR) + self._token_api_url = "https://ipgrest.asanpardakht.ir/v1/Token" + self._payment_url = "https://asan.shaparak.ir" + self._verify_api_url = "https://ipgrest.asanpardakht.ir/v1/Verify" + + def get_bank_type(self): + return BankType.ASANPARDAKHT + + def set_default_settings(self): + required_settings = ["MERCHANT_CONFIGURATION_ID", "USERNAME", "PASSWORD"] + for item in required_settings: + if item not in self.default_setting_kwargs: + raise SettingDoesNotExist(f"{item} is not set in settings.") + setattr(self, f"_{item.lower()}", self.default_setting_kwargs[item]) + + def get_pay_data(self): + data = { + "serviceTypeId": 1, + "merchantConfigurationId": self._merchant_configuration_id, + "localInvoiceId": self.get_tracking_code(), + "amountInRials": self.get_gateway_amount(), + "localDate": self._get_local_date(), + "callbackURL": self._get_gateway_callback_url(), + } + return data + + def prepare_pay(self): + super(AsanPardakht, self).prepare_pay() + + def pay(self): + super(AsanPardakht, self).pay() + data = self.get_pay_data() + headers = { + "Content-Type": "application/json", + "usr": self._username, + "pwd": self._password, + } + response_json = self._send_request(self._token_api_url, data, headers) + + status = response_json.get("ResCode") + + if status == "0": # تراکنش موفق + token = response_json.get("Token") + self._set_reference_number(token) + else: + status_text = self._get_status_text(status) + self._set_transaction_status_text(status_text) + logging.critical(status_text) + raise BankGatewayRejectPayment(self.get_transaction_status_text()) + + def _get_status_text(self, status): + status_codes = { + "0": "Transaction successful", + "1": "Issuer declined transaction", + "2": "Transaction already confirmed", + "3": "Invalid merchant", + "4": "Card captured", + "5": "Transaction not processed", + "6": "Error occurred", + "12": "Invalid transaction", + "13": "Incorrect correction amount", + "14": "Invalid card number", + "15": "Invalid issuer", + "16": "Transaction approved, update track 3", + "19": "Resend transaction", + "23": "Invalid commission amount", + "25": "Original transaction not found", + "30": "Message format error", + "31": "Merchant not supported by switch", + "33": "Card expiration date exceeded", + "34": "Transaction not successfully completed", + "36": "Card restricted", + "38": "Too many incorrect PIN entries", + "39": "Credit card account not found", + "40": "Requested operation not supported", + "41": "Lost card, capture card", + "43": "Stolen card, capture card", + "51": "Insufficient funds", + "54": "Card expiration date exceeded", + "55": "Invalid card PIN", + "57": "Transaction not allowed", + "61": "Transaction amount exceeds limit", + "63": "Security violation", + "65": "Too many transaction attempts", + "75": "Too many incorrect PIN attempts", + "77": "Invalid transaction date", + "78": "Card inactive", + "79": "Invalid linked account", + "80": "Transaction unsuccessful", + "84": "Card issuer not responding", + "86": "Transaction destination in off sign mode", + "90": "Card issuer performing end-of-day operations", + "92": "No routing to destination", + "94": "Duplicate transaction", + "96": "System error occurred", + "97": "Issuer or acquirer performing key change" + } + return status_codes.get(status, "Unknown error") + + def _get_gateway_payment_url_parameter(self): + return self._payment_url + + def _get_gateway_payment_method_parameter(self): + return "POST" + + def _get_gateway_payment_parameter(self): + params = { + "RefId": self.get_reference_number(), + } + return params + + def prepare_verify_from_gateway(self): + super(AsanPardakht, self).prepare_verify_from_gateway() + request = self.get_request() + ref_id = request.POST.get("RefId") + res_code = request.POST.get("ResCode") + self._set_reference_number(ref_id) + self._set_bank_record() + if res_code == "0": + self._bank.extra_information = f"ResCode={res_code}, RefId={ref_id}" + self._bank.save() + else: + logging.error(f"Payment failed with ResCode: {res_code}") + self._set_payment_status(PaymentStatus.CANCEL_BY_USER) + + def verify_from_gateway(self, request): + super(AsanPardakht, self).verify_from_gateway(request) + + def get_verify_data(self): + data = { + "merchantConfigurationId": self._merchant_configuration_id, + "payGateTranId": self.get_reference_number(), + } + return data + + def prepare_verify(self, tracking_code): + super(AsanPardakht, self).prepare_verify(tracking_code) + + def verify(self, transaction_code): + super(AsanPardakht, self).verify(transaction_code) + data = self.get_verify_data() + headers = { + "Content-Type": "application/json", + "usr": self._username, + "pwd": self._password, + } + response_json = self._send_request(self._verify_api_url, data, headers) + if response_json.get("IsSuccess"): + self._set_payment_status(PaymentStatus.COMPLETE) + else: + self._set_payment_status(PaymentStatus.CANCEL_BY_USER) + logging.error("Asan Pardakht verification failed.") + + def _send_request(self, api_url, data, headers): + try: + response = requests.post(api_url, json=data, headers=headers, timeout=10) + response.raise_for_status() + except requests.Timeout: + logging.exception(f"Asan Pardakht gateway timeout: {data}") + raise BankGatewayConnectionError() + except requests.ConnectionError: + logging.exception(f"Asan Pardakht gateway connection error: {data}") + raise BankGatewayConnectionError() + except requests.HTTPError as e: + logging.exception(f"HTTP error occurred: {e}") + raise BankGatewayConnectionError() + + response_json = get_json(response) + self._set_transaction_status_text(response_json.get("Message")) + return response_json + + def _get_local_date(self): + from datetime import datetime + + return datetime.now().strftime("%Y%m%d%H%M%S") diff --git a/azbankgateways/banks/bahamta.py b/azbankgateways/banks/bahamta.py old mode 100644 new mode 100755 diff --git a/azbankgateways/banks/banks.py b/azbankgateways/banks/banks.py old mode 100644 new mode 100755 diff --git a/azbankgateways/banks/bmi.py b/azbankgateways/banks/bmi.py old mode 100644 new mode 100755 diff --git a/azbankgateways/banks/idpay.py b/azbankgateways/banks/idpay.py old mode 100644 new mode 100755 diff --git a/azbankgateways/banks/mellat.py b/azbankgateways/banks/mellat.py old mode 100644 new mode 100755 diff --git a/azbankgateways/banks/payV1.py b/azbankgateways/banks/payV1.py old mode 100644 new mode 100755 diff --git a/azbankgateways/banks/sep.py b/azbankgateways/banks/sep.py old mode 100644 new mode 100755 diff --git a/azbankgateways/banks/zarinpal.py b/azbankgateways/banks/zarinpal.py old mode 100644 new mode 100755 diff --git a/azbankgateways/banks/zibal.py b/azbankgateways/banks/zibal.py old mode 100644 new mode 100755 diff --git a/azbankgateways/default_settings.py b/azbankgateways/default_settings.py index f0436dd..ce09493 100755 --- a/azbankgateways/default_settings.py +++ b/azbankgateways/default_settings.py @@ -17,8 +17,10 @@ "BAHAMTA": "azbankgateways.banks.Bahamta", "MELLAT": "azbankgateways.banks.Mellat", "PAYV1": "azbankgateways.banks.PayV1", + "ASANPARDAKHT": "azbankgateways.banks.AsanPardakht", }, ) + _AZ_IRANIAN_BANK_GATEWAYS = getattr(settings, "AZ_IRANIAN_BANK_GATEWAYS", {}) BANK_PRIORITIES = _AZ_IRANIAN_BANK_GATEWAYS.get("BANK_PRIORITIES", []) BANK_GATEWAYS = _AZ_IRANIAN_BANK_GATEWAYS.get("GATEWAYS", {}) diff --git a/azbankgateways/exceptions/__init__.py b/azbankgateways/exceptions/__init__.py old mode 100644 new mode 100755 diff --git a/azbankgateways/exceptions/exceptions.py b/azbankgateways/exceptions/exceptions.py old mode 100644 new mode 100755 diff --git a/azbankgateways/forms.py b/azbankgateways/forms.py old mode 100644 new mode 100755 diff --git a/azbankgateways/locale/en/LC_MESSAGES/django.mo b/azbankgateways/locale/en/LC_MESSAGES/django.mo old mode 100644 new mode 100755 diff --git a/azbankgateways/locale/en/LC_MESSAGES/django.po b/azbankgateways/locale/en/LC_MESSAGES/django.po old mode 100644 new mode 100755 diff --git a/azbankgateways/locale/fa/LC_MESSAGES/django.mo b/azbankgateways/locale/fa/LC_MESSAGES/django.mo old mode 100644 new mode 100755 diff --git a/azbankgateways/locale/fa/LC_MESSAGES/django.po b/azbankgateways/locale/fa/LC_MESSAGES/django.po old mode 100644 new mode 100755 diff --git a/azbankgateways/migrations/0001_initial.py b/azbankgateways/migrations/0001_initial.py old mode 100644 new mode 100755 diff --git a/azbankgateways/migrations/0002_auto_20210102_0721.py b/azbankgateways/migrations/0002_auto_20210102_0721.py old mode 100644 new mode 100755 diff --git a/azbankgateways/migrations/0003_bank_bank_choose_identifier.py b/azbankgateways/migrations/0003_bank_bank_choose_identifier.py old mode 100644 new mode 100755 diff --git a/azbankgateways/migrations/0004_auto_20211115_1500.py b/azbankgateways/migrations/0004_auto_20211115_1500.py old mode 100644 new mode 100755 diff --git a/azbankgateways/migrations/0005_alter_bank_bank_type_alter_bank_created_at_and_more.py b/azbankgateways/migrations/0005_alter_bank_bank_type_alter_bank_created_at_and_more.py old mode 100644 new mode 100755 diff --git a/azbankgateways/migrations/__init__.py b/azbankgateways/migrations/__init__.py old mode 100644 new mode 100755 diff --git a/azbankgateways/models/__init__.py b/azbankgateways/models/__init__.py old mode 100644 new mode 100755 diff --git a/azbankgateways/models/banks.py b/azbankgateways/models/banks.py old mode 100644 new mode 100755 diff --git a/azbankgateways/models/enum.py b/azbankgateways/models/enum.py old mode 100644 new mode 100755 index ce0f1e5..ec4ed4b --- a/azbankgateways/models/enum.py +++ b/azbankgateways/models/enum.py @@ -11,6 +11,7 @@ class BankType(models.TextChoices): BAHAMTA = "BAHAMTA", _("Bahamta") MELLAT = "MELLAT", _("Mellat") PAYV1 = "PAYV1", _("PayV1") + ASANPARDAKHT = "ASANPARDAKHT", _("AsanPardakht") class CurrencyEnum(models.TextChoices): diff --git a/azbankgateways/readers/__init__.py b/azbankgateways/readers/__init__.py old mode 100644 new mode 100755 diff --git a/azbankgateways/readers/bases.py b/azbankgateways/readers/bases.py old mode 100644 new mode 100755 diff --git a/azbankgateways/readers/defaults.py b/azbankgateways/readers/defaults.py old mode 100644 new mode 100755 diff --git a/azbankgateways/templates/azbankgateways/redirect_to_bank.html b/azbankgateways/templates/azbankgateways/redirect_to_bank.html old mode 100644 new mode 100755 diff --git a/azbankgateways/templates/azbankgateways/samples/base.html b/azbankgateways/templates/azbankgateways/samples/base.html old mode 100644 new mode 100755 diff --git a/azbankgateways/templates/azbankgateways/samples/base_site.html b/azbankgateways/templates/azbankgateways/samples/base_site.html old mode 100644 new mode 100755 diff --git a/azbankgateways/templates/azbankgateways/samples/gateway.html b/azbankgateways/templates/azbankgateways/samples/gateway.html old mode 100644 new mode 100755 diff --git a/azbankgateways/templates/azbankgateways/samples/result.html b/azbankgateways/templates/azbankgateways/samples/result.html old mode 100644 new mode 100755 diff --git a/azbankgateways/types.py b/azbankgateways/types.py old mode 100644 new mode 100755 diff --git a/azbankgateways/urls.py b/azbankgateways/urls.py old mode 100644 new mode 100755 diff --git a/azbankgateways/utils.py b/azbankgateways/utils.py old mode 100644 new mode 100755 diff --git a/azbankgateways/views/__init__.py b/azbankgateways/views/__init__.py old mode 100644 new mode 100755 diff --git a/azbankgateways/views/banks.py b/azbankgateways/views/banks.py old mode 100644 new mode 100755 diff --git a/azbankgateways/views/samples.py b/azbankgateways/views/samples.py old mode 100644 new mode 100755 diff --git a/pyproject.toml b/pyproject.toml old mode 100644 new mode 100755 diff --git a/setup.cfg b/setup.cfg old mode 100644 new mode 100755 diff --git a/tox.ini b/tox.ini old mode 100644 new mode 100755