Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Jibit Gateway #106

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 14 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,19 +17,20 @@

1. [درگاه پرداخت بانک ملی ایران (BMI)](https://mmp.sadadpsp.ir/Browse/MerchantRequestForm?@TermType_Shaparakabbr=INT)

1. [درگاه پرداخت بانک سامان (SEP)](https://www.sep.ir/iemerchantregister)
2. [درگاه پرداخت بانک سامان (SEP)](https://www.sep.ir/iemerchantregister)

1. [درگاه پرداخت زرین پال](https://next.zarinpal.com/auth/register)
3. [درگاه پرداخت زرین پال](https://next.zarinpal.com/auth/register)

1. [درگاه پرداخت آی دی پی (IDPay)](https://idpay.ir/s/664153)
4. [درگاه پرداخت آی دی پی (IDPay)](https://idpay.ir/s/664153)

1. [درگاه پرداخت زیبال](https://zibal.ir)
5. [درگاه پرداخت زیبال](https://zibal.ir)

1. [درگاه پرداخت باهمتا](https://webpay.bahamta.com?rc=Sv7oH)
6. [درگاه پرداخت باهمتا](https://webpay.bahamta.com?rc=Sv7oH)

1. [درگاه به پرداخت](http://www.behpardakht.com/)
7. [درگاه به پرداخت](http://www.behpardakht.com/)

1. [درگاه پی ورژن ۱](https://www.pay.ir/)
8. [درگاه پی ورژن ۱](https://www.pay.ir/)
9. [درگاه جیبیت](https://www.jibit.ir/)

[[_TOC_]]

Expand Down Expand Up @@ -96,6 +97,10 @@ AZ_IRANIAN_BANK_GATEWAYS = {
'MERCHANT_CODE': '<YOUR MERCHANT CODE>',
'X_SANDBOX': 0, # 0 disable, 1 active
},
'JIBIT': {
'API_KEY': '<YOUR API KEY>',
'SECRET_KEY': '<YOUR SECRET KEY>'
},
},
'IS_SAMPLE_FORM_ENABLE': True, # اختیاری و پیش فرض غیر فعال است
'DEFAULT': 'BMI',
Expand Down Expand Up @@ -413,6 +418,8 @@ for item in bank_models.Bank.objects.filter_return_from_bank():
- [X] Add Bahamta support
- [X] Add BehPardakht support
- [X] Add Pay.ir V1 support
- [X] Add Jibit support
- [ ] Add Vandar support
- [ ] Add Pay.ir V2 support
- [ ] Add nextpay-ir support (need MERCHANT_CODE & etc.)
- [ ] Add Paystar support (need MERCHANT_CODE & etc.)
Expand Down
4 changes: 3 additions & 1 deletion azbankgateways/bankfactories.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,13 +44,15 @@ def create(self, bank_type: BankType = None, identifier: str = "1") -> BaseBank:
logging.debug("Create bank")
return bank

def auto_create(self, identifier: str = "1", amount=None) -> BaseBank:
def auto_create(self, identifier: str = "1", amount=None,request=None) -> BaseBank:
logging.debug("Request create bank automatically")
bank_list = self._secret_value_reader.get_bank_priorities(identifier)
errors = []
for bank_type in bank_list:
try:
bank = self.create(bank_type, identifier)
if request:
bank.set_request(request)
bank.check_gateway(amount)
return bank
except Exception as e:
Expand Down
1 change: 1 addition & 0 deletions azbankgateways/banks/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@
from .sep import SEP # noqa
from .zarinpal import Zarinpal # noqa
from .zibal import Zibal # noqa
from .jibit import Jibit # noqa
172 changes: 172 additions & 0 deletions azbankgateways/banks/jibit.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
import json
import logging

import requests

from azbankgateways.banks import BaseBank
from azbankgateways.exceptions import BankGatewayConnectionError, SettingDoesNotExist
from azbankgateways.exceptions.exceptions import BankGatewayRejectPayment
from azbankgateways.models import BankType, CurrencyEnum, PaymentStatus
from azbankgateways.utils import get_json


class Jibit(BaseBank):
_api_key = None
_secret_key = None

def __init__(self, **kwargs):
super(Jibit, self).__init__(**kwargs)
self.set_gateway_currency(CurrencyEnum.IRR)
self._token_api_url = "https://napi.jibit.ir/ppg/v3/purchases"
self._jwt_token_api_url = "https://napi.jibit.ir/ppg/v3/tokens"
self._payment_url = "https://napi.jibit.ir/ppg/v3/purchases/{}/payments"
self._verify_api_url = "https://napi.jibit.ir/ppg/v3/purchases/{}/verify"

def get_bank_type(self):
return BankType.JIBIT

def set_default_settings(self):
for item in ["API_KEY", "SECRET_KEY"]:
if item not in self.default_setting_kwargs:
raise SettingDoesNotExist()
setattr(self, f"_{item.lower()}", self.default_setting_kwargs[item])

"""
gateway
"""

def _get_gateway_payment_url_parameter(self):
return self._payment_url.format(self.get_reference_number())

def _get_gateway_payment_parameter(self):
params = {}
return params

def _get_gateway_payment_method_parameter(self):
return "GET"

"""
pay
"""

def get_pay_data(self):
description = "خرید با شماره پیگیری - {}".format(self.get_tracking_code())
data = {
'additionalData': {},
'amount': self.get_gateway_amount(),
'callbackUrl': self._get_gateway_callback_url(),
'checkPayerNationalCode': False,
'userIdentifier': self.get_mobile_number(),
'clientReferenceNumber': self.get_tracking_code(),
'currency': 'IRR',
'description': description,
'payerMobileNumber': self.get_mobile_number(),
'wage': 0,
}

return data

def prepare_pay(self):
super(Jibit, self).prepare_pay()

def pay(self):
super(Jibit, self).pay()
data = self.get_pay_data()
response_json = self._send_data(self._token_api_url, data)
if response_json.get('purchaseId'):
token = response_json["purchaseId"]
self._set_reference_number(token)
else:
logging.critical("Jibit gateway reject payment")
raise BankGatewayRejectPayment(self.get_transaction_status_text())

"""
verify from gateway
"""

def prepare_verify_from_gateway(self):
super(Jibit, self).prepare_verify_from_gateway()
token = self.get_request().POST.get("purchaseId", None)

self._set_reference_number(token)
self._set_bank_record()

extra_information = {
"payer_ip": self.get_request().POST.get("payerIp", None),
"psp_reference_number": self.get_request().POST.get("pspReferenceNumber", None),
"psp_RRN": self.get_request().POST.get("pspRRN", None),
"payer_masked_card_number": self.get_request().POST.get("payerMaskedCardNumber", None),
"psp_name": self.get_request().POST.get("pspName", None),
"psp_hashed_card_number": self.get_request().POST.get("pspHashedCardNumber", None),
"fail_reason": self.get_request().POST.get("failReason", None),
}

self._bank.extra_information = extra_information
self._bank.save()

def verify_from_gateway(self, request):
super(Jibit, self).verify_from_gateway(request)

"""
verify
"""

def get_verify_data(self):
super(Jibit, self).get_verify_data()
return self.get_reference_number()

def prepare_verify(self, tracking_code):
super(Jibit, self).prepare_verify(tracking_code)

def verify(self, transaction_code):
super(Jibit, self).verify(transaction_code)
data = self.get_verify_data()
response_json = self._send_data(self._verify_api_url.format(data), data)
if response_json["status"] == "SUCCESSFUL":
self._set_payment_status(PaymentStatus.COMPLETE)
self._bank.save()
else:
self._set_payment_status(PaymentStatus.CANCEL_BY_USER)
logging.debug("Jibit gateway unapprove payment")

def __generate_token(self):
url = self._jwt_token_api_url

payload = json.dumps({
"apiKey": self._api_key,
"secretKey": self._secret_key
})
headers = {
'accept': 'application/json',
'Content-Type': 'application/json'
}
response = requests.post(url=url, headers=headers, data=payload)
if response.status_code == 200:
return response.json()['accessToken']
else:
self._set_payment_status(PaymentStatus.ERROR)
logging.critical("Can not get JWT token from Jibit")
raise BankGatewayRejectPayment(self.get_transaction_status_text())

def _send_data(self, api, data):

access_token = self.__generate_token()
headers = {
'accept': 'application/json',
'Content-Type': 'application/json',
'Authorization': 'Bearer {}'.format(access_token)
}
try:
response = requests.post(api, headers=headers, json=data, timeout=5)
except requests.Timeout:
logging.exception("Jibit time out gateway {}".format(data))
raise BankGatewayConnectionError()
except requests.ConnectionError:
logging.exception("Jibit time out gateway {}".format(data))
raise BankGatewayConnectionError()
print(response.content)
response_json = get_json(response)

if response.status_code != 200:
self._set_transaction_status_text(response_json["errors"][0]['code'])
return response_json
8 changes: 5 additions & 3 deletions azbankgateways/default_settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@
"ZIBAL": "azbankgateways.banks.Zibal",
"BAHAMTA": "azbankgateways.banks.Bahamta",
"MELLAT": "azbankgateways.banks.Mellat",
"PAYV1": "azbankgateways.banks.PayV1",
"PAYV1": "azbankgateways.banks.PayV1",
"JIBIT": "azbankgateways.banks.Jibit",
},
)
_AZ_IRANIAN_BANK_GATEWAYS = getattr(settings, "AZ_IRANIAN_BANK_GATEWAYS", {})
Expand All @@ -45,10 +46,11 @@
GO_TO_BANK_GATEWAY_NAMESPACE = f"{CUSTOM_APP}:{AZIranianBankGatewaysConfig.name}:go-to-bank-gateway"
SAMPLE_RESULT_NAMESPACE = f"{CUSTOM_APP}:{AZIranianBankGatewaysConfig.name}:sample-result"
else:
CALLBACK_NAMESPACE = _AZ_IRANIAN_BANK_GATEWAYS.get("CALLBACK_NAMESPACE", f"{AZIranianBankGatewaysConfig.name}:callback")
CALLBACK_NAMESPACE = _AZ_IRANIAN_BANK_GATEWAYS.get("CALLBACK_NAMESPACE",
f"{AZIranianBankGatewaysConfig.name}:callback")
GO_TO_BANK_GATEWAY_NAMESPACE = _AZ_IRANIAN_BANK_GATEWAYS.get(
"GO_TO_BANK_GATEWAY_NAMESPACE", f"{AZIranianBankGatewaysConfig.name}:go-to-bank-gateway"
)
SAMPLE_RESULT_NAMESPACE = _AZ_IRANIAN_BANK_GATEWAYS.get(
"SAMPLE_RESULT_NAMESPACE", f"{AZIranianBankGatewaysConfig.name}:sample-result"
)
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# Generated by Django 4.1.7 on 2024-01-15 19:45

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('azbankgateways', '0004_auto_20211115_1500'),
]

operations = [
migrations.AlterField(
model_name='bank',
name='bank_type',
field=models.CharField(choices=[('BMI', 'BMI'), ('SEP', 'SEP'), ('ZARINPAL', 'Zarinpal'), ('IDPAY', 'IDPay'), ('ZIBAL', 'Zibal'), ('BAHAMTA', 'Bahamta'), ('MELLAT', 'Mellat'), ('PAYV1', 'PayV1'), ('JIBIT', 'Jibit')], max_length=50, verbose_name='Bank'),
),
migrations.AlterField(
model_name='bank',
name='created_at',
field=models.DateTimeField(auto_now_add=True, verbose_name='Created at'),
),
migrations.AlterField(
model_name='bank',
name='status',
field=models.CharField(choices=[('Waiting', 'Waiting'), ('Redirect to bank', 'Redirect To Bank'), ('Return from bank', 'Return From Bank'), ('Cancel by user', 'Cancel By User'), ('Expire gateway token', 'Expire Gateway Token'), ('Expire verify payment', 'Expire Verify Payment'), ('Complete', 'Complete'), ('Unknown error acquired', 'Error')], max_length=50, verbose_name='Status'),
),
migrations.AlterField(
model_name='bank',
name='update_at',
field=models.DateTimeField(auto_now=True, verbose_name='Updated at'),
),
]
1 change: 1 addition & 0 deletions azbankgateways/models/enum.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ class BankType(settings.TEXT_CHOICES):
BAHAMTA = "BAHAMTA", _("Bahamta")
MELLAT = "MELLAT", _("Mellat")
PAYV1 = "PAYV1", _("PayV1")
JIBIT = "JIBIT", _("Jibit")


class CurrencyEnum(settings.TEXT_CHOICES):
Expand Down