fake gateway

This commit is contained in:
Sayyid Hamid Mahdavi 2025-05-31 13:36:25 +03:30
parent a1e4fbcc52
commit f0edf10f53
5 changed files with 108 additions and 60 deletions

View file

@ -24,7 +24,7 @@ class BasePGModel(models.Model):
def make_request(self): def make_request(self):
pass pass
def confirm_request(self): def confirm_request(self, request=None):
pass pass
def reverse_request(self): def reverse_request(self):

View file

@ -0,0 +1,26 @@
# Generated by Django 5.1.4 on 2025-05-31 10:03
import django.db.models.deletion
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('pg', '0004_paymentrequest_phone_number_and_more'),
]
operations = [
migrations.CreateModel(
name='Fake',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('created_at', models.DateTimeField(auto_now_add=True, db_index=True)),
('updated_at', models.DateTimeField(auto_now=True, db_index=True)),
('payment_request', models.OneToOneField(on_delete=django.db.models.deletion.PROTECT, related_name='+', to='pg.paymentrequest')),
],
options={
'abstract': False,
},
),
]

View file

@ -2,6 +2,7 @@ import urllib.parse
from mimetypes import guess_all_extensions from mimetypes import guess_all_extensions
from django.conf import settings from django.conf import settings
from django.contrib import messages
from django.db import models from django.db import models
from django.db.models import TextChoices from django.db.models import TextChoices
from django.urls import reverse from django.urls import reverse
@ -20,9 +21,10 @@ from django.utils.translation import gettext_lazy as _
class GatewayChoise(TextChoices): class GatewayChoise(TextChoices):
FAKE = "fake", _("fake") FAKE = "fake", _("fake")
PNA = 'pna' , _('pna') PNA = 'pna', _('pna')
# TODO: use generic relation
class PaymentRequest(models.Model): class PaymentRequest(models.Model):
id = None id = None
uuid = models.UUIDField(primary_key=True, editable=False, default=uuid.uuid4, unique=True, db_index=True) uuid = models.UUIDField(primary_key=True, editable=False, default=uuid.uuid4, unique=True, db_index=True)
@ -42,23 +44,30 @@ class PaymentRequest(models.Model):
updated_at = models.DateTimeField(auto_now=True, db_index=True) updated_at = models.DateTimeField(auto_now=True, db_index=True)
def get_gateway_tools(self): def get_gateway_tools(self):
if self.gateway == 'pna': if self.gateway == GatewayChoise.PNA:
return self.pna return PNA.objects.get(payment_request=self)
if self.gateway == GatewayChoise.FAKE:
return Fake.objects.get(payment_request=self)
def set_gateway(self, data):
if 'fake' in data:
self.gateway = GatewayChoise.FAKE
fake = Fake.objects.create(payment_request=self)
fake.payment_request = self
def set_gateway(self, gateway): elif 'pna' in data:
self.gateway = gateway self.gateway = GatewayChoise.PNA
if gateway == 'pna':
pna = PNA.objects.create(payment_request=self) pna = PNA.objects.create(payment_request=self)
pna.payment_request = self pna.payment_request = self
if gateway == 'fake': else:
pass raise Exception('Unknown gateway')
self.save() self.save()
# TODO: complete and use this # TODO: complete and use this
def change_state(self, from_state, to_state, error_message=None, **data): def change_state(self, from_state, to_state, error_message=None, **data):
if self.state == from_state: if self.state == from_state:
@ -132,7 +141,6 @@ class PaymentRequest(models.Model):
return bool(to_pay_success) return bool(to_pay_success)
class PNA(BasePGModel): class PNA(BasePGModel):
payment_request = models.OneToOneField(PaymentRequest, on_delete=models.PROTECT, related_name='pna') payment_request = models.OneToOneField(PaymentRequest, on_delete=models.PROTECT, related_name='pna')
@ -145,7 +153,6 @@ class PNA(BasePGModel):
pna_status_code = models.IntegerField(null=True, blank=True) pna_status_code = models.IntegerField(null=True, blank=True)
pna_status_message = models.CharField(null=True, blank=True, max_length=255) pna_status_message = models.CharField(null=True, blank=True, max_length=255)
client = PNAClient() client = PNAClient()
def make_request(self): def make_request(self):
@ -166,20 +173,56 @@ class PNA(BasePGModel):
self.save() self.save()
def get_redirect_url(self): def get_pg_page_url(self):
if self.pna_token: if self.pna_token:
return self.client.pg_base_url.format(token=self.pna_token) return self.client.pg_base_url.format(token=self.pna_token)
def confirm_request(self): def confirm_request(self, request=None):
pna_token = self.pna_token print(dict(request.POST))
response = self.client.request_normal_sale_confirm(pna_token) post_dict = dict(request.POST)
# response = {'status': 0, 'cardNumberMasked': '504172******9210', 'rrn': 511629210215, 'appToken': 4101434578524, 'token': 'NDEwMTQzNDU3ODUyNA=='} if post_dict.get('status') in [0, '0', [0], ['0']]:
self.details = response try:
if response['status'] == 0:
self.pna_status = StateChoices.SUCCESS.value pna_token = self.pna_token
self.save() response = self.client.request_normal_sale_confirm(pna_token)
# response = {'status': 0, 'cardNumberMasked': '504172******9210', 'rrn': 511629210215, 'appToken': 4101434578524, 'token': 'NDEwMTQzNDU3ODUyNA=='}
# post = <QueryDict: {'Token': ['NDEwMTI0Nzc0MDMzMA=='], 'OrderId': ['7'], 'TerminalNo': ['31127029'], 'RRN': ['511629156251'], 'status': ['0'], 'TspToken': ['00000000-0000-0000-0000-000000000000'], 'HashCardNumber': ['6008617E6BAB76997499446356F5C8B60288445650DD551FDF32007BCF2B14AF'], 'Amount': ['21,000'], 'SwAmount': [''], 'STraceNo': ['123232']}>
# post = <QueryDict: {'Token': ['NDI2MDY3ODI0MTg1OA=='], 'OrderId': ['47'], 'status': ['-138']}>
self.details = response
if response['status'] == 0:
self.pna_status = StateChoices.SUCCESS.value
self.save()
self.payment_request.charge_wallet_balance()
messages.success(request, 'شارژ انجام شد')
except Exception as e:
print(e)
messages.error(request, str(e))
else:
print(request.POST)
messages.error(request, "نتیجه تراکنش از سمت درگاه دریافت نشد.")
def reverse_request(self): def reverse_request(self):
raise NotImplementedError() raise NotImplementedError()
class Fake(BasePGModel):
payment_request = models.OneToOneField(PaymentRequest, on_delete=models.PROTECT, related_name='+')
def make_request(self):
pass
def get_pg_page_url(self):
return reverse('pg:payment-confirm-view', kwargs={'uuid': self.payment_request.uuid})
def confirm_request(self, request=None):
self.payment_request.charge_wallet_balance()
messages.success(request, 'شارژ انجام شد')
self.save()
def reverse_request(self):
raise NotImplementedError()

View file

@ -48,22 +48,19 @@ class PaymentRequestView(UpdateView):
self.object = form.save() self.object = form.save()
charge_request: PaymentRequest = self.get_object() charge_request: PaymentRequest = self.get_object()
if 'fake' in form.data: charge_request.set_gateway(form.data)
print('fake')
if 'pna' in form.data:
charge_request.set_gateway('pna')
tool = charge_request.get_gateway_tools() tool = charge_request.get_gateway_tools()
# try:
tool.make_request() tool.make_request()
redirect_url = tool.get_redirect_url()
redirect_url = tool.get_pg_page_url()
if redirect_url: if redirect_url:
return HttpResponseRedirect(redirect_url) return HttpResponseRedirect(redirect_url)
else: else:
messages.error(self.request, 'can not redirect to payment gateway') messages.error(self.request, 'can not redirect to payment gateway')
messages.info(self.request, 'در پردازش صفحه خطایی وجود دارد.')
# TODO: redirect to error page # TODO: redirect to error page
return HttpResponseRedirect(reverse('pg:payment-confirm-view', kwargs={'uuid': charge_request.uuid})) return HttpResponseRedirect(reverse('pg:payment-confirm-view', kwargs={'uuid': charge_request.uuid}))
@ -81,13 +78,15 @@ class PaymentConfirmView(UpdateView):
# return Charge.objects.filter(state__in=[StateChoices.CREATED.value, StateChoices.SUCCESS.value]) # return Charge.objects.filter(state__in=[StateChoices.CREATED.value, StateChoices.SUCCESS.value])
def get(self, request, *args, **kwargs): def get(self, request, *args, **kwargs):
print('get') print('get')
print(args) print(args)
print(kwargs) print(kwargs)
self.object = self.get_object() self.object = self.get_object()
context = self.get_context_data() tool = self.object.get_gateway_tools()
messages.info(self.request, 'در پردازش صفحه خطایی وجود دارد.') tool.confirm_request(request)
context = self.get_context_data()
return self.render_to_response(context) return self.render_to_response(context)
def post(self, request, *args, **kwargs): def post(self, request, *args, **kwargs):
@ -95,37 +94,17 @@ class PaymentConfirmView(UpdateView):
print(request.POST) print(request.POST)
print(args) print(args)
print(kwargs) print(kwargs)
self.object = self.get_object()
# post = <QueryDict: {'Token': ['NDEwMTI0Nzc0MDMzMA=='], 'OrderId': ['7'], 'TerminalNo': ['31127029'], 'RRN': ['511629156251'], 'status': ['0'], 'TspToken': ['00000000-0000-0000-0000-000000000000'], 'HashCardNumber': ['6008617E6BAB76997499446356F5C8B60288445650DD551FDF32007BCF2B14AF'], 'Amount': ['21,000'], 'SwAmount': [''], 'STraceNo': ['123232']}>
if 'redirect-to-app' in request.POST: if 'redirect-to-app' in request.POST:
response = HttpResponse(status=302) response = HttpResponse(status=302)
response['Location'] = self.object.callback_url response['Location'] = self.object.callback_url
return response return response
else: self.object = self.get_object()
# post = <QueryDict: {'Token': ['NDEwMTI0Nzc0MDMzMA=='], 'OrderId': ['7'], 'TerminalNo': ['31127029'], 'RRN': ['511629156251'], 'status': ['0'], 'TspToken': ['00000000-0000-0000-0000-000000000000'], 'HashCardNumber': ['6008617E6BAB76997499446356F5C8B60288445650DD551FDF32007BCF2B14AF'], 'Amount': ['21,000'], 'SwAmount': [''], 'STraceNo': ['123232']}> tool = self.object.get_gateway_tools()
# post = <QueryDict: {'Token': ['NDI2MDY3ODI0MTg1OA=='], 'OrderId': ['47'], 'status': ['-138']}> tool.confirm_request(request)
print(dict(request.POST)) context = self.get_context_data(object=self.object)
post_dict = dict(request.POST) return self.render_to_response(context)
if post_dict.get('status') in [0, '0', [0], ['0']]:
try:
payment_request: PaymentRequest = self.get_object()
tool = payment_request.get_gateway_tools()
tool.confirm_request()
payment_request.charge_wallet_balance()
messages.success(self.request, 'شارژ انجام شد')
except Exception as e:
print(e)
messages.error(self.request, str(e))
else:
print(request.POST)
messages.error(self.request, "نتیجه تراکنش از سمت درگاه دریافت نشد.")
context = self.get_context_data(object=self.object)
return self.render_to_response(context)
# def form_valid(self, form): # def form_valid(self, form):

View file

@ -26,9 +26,9 @@
<button type="submit" class="btn mx-auto center-block" name="pna"> <button type="submit" class="btn mx-auto center-block" name="pna">
<img class="img-thumbnail" width="128" height="128" src="{% static "image/pna.png" %}"/> <img class="img-thumbnail" width="128" height="128" src="{% static "image/pna.png" %}"/>
</button> </button>
{# <button type="submit" class="btn mx-auto center-block" name="fake">#} <button type="submit" class="btn mx-auto center-block" name="fake">
{# <img class="img-thumbnail" width="128" height="128" src="{% static "image/fake.png" %}"/>#} <img class="img-thumbnail" width="128" height="128" src="{% static "image/fake.png" %}"/>
{# </button>#} </button>
</div> </div>
</div> </div>
</div> </div>