chore: rename model
This commit is contained in:
+2
-2
@@ -1,10 +1,10 @@
|
||||
from django.contrib import admin
|
||||
from tpv.models import PaymentTPV
|
||||
from tpv.models import PaymentTransaction
|
||||
from unfold.admin import ModelAdmin
|
||||
|
||||
|
||||
# Register your models here.
|
||||
@admin.register(PaymentTPV)
|
||||
@admin.register(PaymentTransaction)
|
||||
class PaymentTPVAdmin(ModelAdmin):
|
||||
list_display = (
|
||||
"hash",
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# Generated by Django 5.0.3 on 2024-03-21 22:43
|
||||
# Generated by Django 5.0.3 on 2024-03-24 19:19
|
||||
|
||||
import tpv.models
|
||||
import uuid
|
||||
@@ -14,7 +14,7 @@ class Migration(migrations.Migration):
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name="PaymentTPV",
|
||||
name="PaymentTransaction",
|
||||
fields=[
|
||||
(
|
||||
"id",
|
||||
|
||||
+1
-5
@@ -8,7 +8,7 @@ def set_default_metadata():
|
||||
return {"items": [], "response": None}
|
||||
|
||||
|
||||
class PaymentTPV(models.Model):
|
||||
class PaymentTransaction(models.Model):
|
||||
class StatusChoices(models.TextChoices):
|
||||
PAID = "PAI", _("Pagado")
|
||||
PENDING = "PEN", _("Pendiente")
|
||||
@@ -62,10 +62,6 @@ class PaymentTPV(models.Model):
|
||||
}
|
||||
"""
|
||||
|
||||
def regenerate_uuid(self):
|
||||
self.hash = uuid4()
|
||||
self.save()
|
||||
|
||||
@property
|
||||
def amount_integer(self) -> int:
|
||||
return int(self.amount * 100)
|
||||
|
||||
+24
-26
@@ -3,7 +3,7 @@ import json
|
||||
|
||||
from django.conf import settings
|
||||
from django.urls import reverse
|
||||
from tpv.models import PaymentTPV
|
||||
from tpv.models import PaymentTransaction
|
||||
from tpv.utils import compute_signature
|
||||
|
||||
|
||||
@@ -43,16 +43,16 @@ class RedsysClient:
|
||||
def get_currency_code(self) -> str:
|
||||
return settings.REDSYS_CURRENCY_CODE
|
||||
|
||||
def get_merchant_url_ok_for_order(self, order: PaymentTPV) -> str:
|
||||
path = reverse("tpv:ok", kwargs={"order": order.hash})
|
||||
def get_merchant_url_ok_for_transaction(self, transaction: PaymentTransaction) -> str:
|
||||
path = reverse("tpv:ok", kwargs={"transaction": transaction.hash})
|
||||
return f"{settings.REDSYS_TPV_DOMAIN}{path}"
|
||||
|
||||
def get_merchant_url_ko_for_order(self, order: PaymentTPV) -> str:
|
||||
path = reverse("tpv:ko", kwargs={"order": order.hash})
|
||||
def get_merchant_url_ko_for_transaction(self, transaction: PaymentTransaction) -> str:
|
||||
path = reverse("tpv:ko", kwargs={"transaction": transaction.hash})
|
||||
return f"{settings.REDSYS_TPV_DOMAIN}{path}"
|
||||
|
||||
def get_webhook_url_for_order(self, order: PaymentTPV) -> str:
|
||||
path = reverse("tpv:webhook", kwargs={"order": order.hash})
|
||||
def get_webhook_url_for_transaction(self, transaction: PaymentTransaction) -> str:
|
||||
path = reverse("tpv:webhook", kwargs={"transaction": transaction.hash})
|
||||
return f"{settings.REDSYS_TPV_DOMAIN}{path}"
|
||||
|
||||
def get_shared_secret(self) -> str:
|
||||
@@ -62,41 +62,39 @@ class RedsysClient:
|
||||
key = self.get_shared_secret()
|
||||
return compute_signature(str(hash), payload, key).decode()
|
||||
|
||||
def get_merchant_parameters_for_order(
|
||||
self, order: PaymentTPV, transaction_type: int = TransactionTypes.AUTHORIZATION
|
||||
def get_merchant_parameters_for_transaction(
|
||||
self, transaction: PaymentTransaction, transaction_type: int = TransactionTypes.AUTHORIZATION
|
||||
) -> dict:
|
||||
merchant_code = self.get_merchant_code()
|
||||
|
||||
return {
|
||||
"DS_MERCHANT_AMOUNT": str(order.amount_integer),
|
||||
"DS_MERCHANT_AMOUNT": str(transaction.amount_integer),
|
||||
"DS_MERCHANT_CURRENCY": self.get_currency_code(),
|
||||
"DS_MERCHANT_MERCHANTCODE": merchant_code,
|
||||
"DS_MERCHANT_MERCHANTURL": self.get_webhook_url_for_order(order), # Webhook
|
||||
"DS_MERCHANT_ORDER": order.hash.hex,
|
||||
"DS_MERCHANT_MERCHANTURL": self.get_webhook_url_for_transaction(transaction), # Webhook
|
||||
"DS_MERCHANT_ORDER": transaction.hash.hex,
|
||||
"DS_MERCHANT_TERMINAL": self.get_terminal(),
|
||||
"DS_MERCHANT_TRANSACTIONTYPE": transaction_type,
|
||||
"DS_MERCHANT_URLKO": self.get_merchant_url_ko_for_order(
|
||||
order
|
||||
), # Página informativa al usuario - Pago erróneo
|
||||
"DS_MERCHANT_URLOK": self.get_merchant_url_ok_for_order(
|
||||
order
|
||||
), # Página informativa al usuario - Pago confirmado
|
||||
# Página informativa al usuario - Pago erróneo
|
||||
"DS_MERCHANT_URLKO": self.get_merchant_url_ko_for_transaction(transaction),
|
||||
# Página informativa al usuario - Pago confirmado
|
||||
"DS_MERCHANT_URLOK": self.get_merchant_url_ok_for_transaction(transaction),
|
||||
}
|
||||
|
||||
def get_encoded_merchant_parameters_for_order(
|
||||
self, order: PaymentTPV, transaction_type: int = TransactionTypes.AUTHORIZATION
|
||||
def get_encoded_merchant_parameters_for_transaction(
|
||||
self, transaction: PaymentTransaction, transaction_type: int = TransactionTypes.AUTHORIZATION
|
||||
) -> str:
|
||||
body = self.get_merchant_parameters_for_order(order, transaction_type)
|
||||
body = self.get_merchant_parameters_for_transaction(transaction, transaction_type)
|
||||
stringified_body = json.dumps(body)
|
||||
return base64.b64encode(stringified_body.encode()).decode("utf-8")
|
||||
|
||||
def get_body_for_order(
|
||||
self, order: PaymentTPV, transaction_type: int = TransactionTypes.AUTHORIZATION
|
||||
def get_body_for_transaction(
|
||||
self, transaction: PaymentTransaction, transaction_type: int = TransactionTypes.AUTHORIZATION
|
||||
) -> dict:
|
||||
merchant_parameters = self.get_encoded_merchant_parameters_for_order(
|
||||
order, transaction_type
|
||||
merchant_parameters = self.get_encoded_merchant_parameters_for_transaction(
|
||||
transaction, transaction_type
|
||||
)
|
||||
signature = self.get_signature(order.hash.hex, merchant_parameters)
|
||||
signature = self.get_signature(transaction.hash.hex, merchant_parameters)
|
||||
|
||||
return {
|
||||
"Ds_MerchantParameters": merchant_parameters,
|
||||
|
||||
+25
-25
@@ -6,7 +6,7 @@ from rest_framework import status
|
||||
from rest_framework.test import APITestCase
|
||||
from django.conf import settings
|
||||
|
||||
from tpv.models import PaymentTPV
|
||||
from tpv.models import PaymentTransaction
|
||||
from tpv.redsys import RedsysClient
|
||||
from tpv.settings import ERROR_CODES
|
||||
|
||||
@@ -14,7 +14,7 @@ from tpv.settings import ERROR_CODES
|
||||
class TestRedsysTPV(APITestCase):
|
||||
def test_redsys_client(self):
|
||||
amount_to_pay = Decimal("10.00")
|
||||
order = PaymentTPV.objects.create(amount=amount_to_pay)
|
||||
transaction = PaymentTransaction.objects.create(amount=amount_to_pay)
|
||||
|
||||
items = [
|
||||
{
|
||||
@@ -26,13 +26,13 @@ class TestRedsysTPV(APITestCase):
|
||||
}
|
||||
]
|
||||
|
||||
order.metadata["items"] = items
|
||||
order.save()
|
||||
transaction.metadata["items"] = items
|
||||
transaction.save()
|
||||
|
||||
client = RedsysClient()
|
||||
merchant_parameters = client.get_merchant_parameters_for_order(order)
|
||||
merchant_parameters = client.get_merchant_parameters_for_transaction(transaction)
|
||||
|
||||
assert merchant_parameters.get("DS_MERCHANT_ORDER") == order.hash.hex
|
||||
assert merchant_parameters.get("DS_MERCHANT_ORDER") == transaction.hash.hex
|
||||
assert merchant_parameters.get("DS_MERCHANT_AMOUNT") == str(
|
||||
int(amount_to_pay) * 100
|
||||
)
|
||||
@@ -44,11 +44,11 @@ class TestRedsysTPV(APITestCase):
|
||||
== settings.REDSYS_MERCHANT_CODE
|
||||
)
|
||||
|
||||
client.get_body_for_order(order)
|
||||
client.get_body_for_transaction(transaction)
|
||||
|
||||
def test_redsys_webhook(self):
|
||||
amount_to_pay = Decimal("10.00")
|
||||
order = PaymentTPV.objects.create(amount=amount_to_pay)
|
||||
transaction = PaymentTransaction.objects.create(amount=amount_to_pay)
|
||||
|
||||
items = [
|
||||
{
|
||||
@@ -59,19 +59,19 @@ class TestRedsysTPV(APITestCase):
|
||||
"amount_to_pay": str(amount_to_pay),
|
||||
}
|
||||
]
|
||||
order.metadata["items"] = items
|
||||
order.save()
|
||||
transaction.metadata["items"] = items
|
||||
transaction.save()
|
||||
|
||||
response = self.client.get(
|
||||
reverse("tpv:order_created", kwargs={"order": order.hash})
|
||||
reverse("tpv:order_created", kwargs={"transaction": transaction.hash})
|
||||
)
|
||||
assert response.status_code == status.HTTP_200_OK
|
||||
|
||||
redsys_response_data = {
|
||||
"Ds_MerchantCode": "999008881",
|
||||
"Ds_Terminal": "001",
|
||||
"Ds_Order": order.hash.hex,
|
||||
"Ds_Amount": str(order.amount_integer),
|
||||
"Ds_Order": transaction.hash.hex,
|
||||
"Ds_Amount": str(transaction.amount_integer),
|
||||
"Ds_Currency": "978",
|
||||
"Ds_Date": "01/01/2024",
|
||||
"Ds_Hour": "00:00",
|
||||
@@ -94,7 +94,7 @@ class TestRedsysTPV(APITestCase):
|
||||
).decode()
|
||||
|
||||
response = self.client.post(
|
||||
reverse("tpv:webhook", kwargs={"order": order.hash}),
|
||||
reverse("tpv:webhook", kwargs={"transaction": transaction.hash}),
|
||||
data={
|
||||
"Ds_MerchantParameters": b64_merchant_params,
|
||||
"Ds_Signature": settings.REDSYS_SHARED_SECRET,
|
||||
@@ -105,13 +105,13 @@ class TestRedsysTPV(APITestCase):
|
||||
assert response.status_code == status.HTTP_200_OK
|
||||
|
||||
response = self.client.get(
|
||||
reverse("tpv:ok", kwargs={"order": order.hash})
|
||||
reverse("tpv:ok", kwargs={"transaction": transaction.hash})
|
||||
)
|
||||
assert response.status_code == status.HTTP_200_OK
|
||||
|
||||
def test_redsys_webhook_payment_error(self):
|
||||
amount_to_pay = Decimal("10.00")
|
||||
order = PaymentTPV.objects.create(amount=amount_to_pay)
|
||||
transaction = PaymentTransaction.objects.create(amount=amount_to_pay)
|
||||
|
||||
items = [
|
||||
{
|
||||
@@ -123,19 +123,19 @@ class TestRedsysTPV(APITestCase):
|
||||
}
|
||||
]
|
||||
|
||||
order.metadata["items"] = items
|
||||
transaction.metadata["items"] = items
|
||||
|
||||
order.save()
|
||||
transaction.save()
|
||||
|
||||
response = self.client.get(
|
||||
reverse("tpv:order_created", kwargs={"order": order.hash})
|
||||
reverse("tpv:order_created", kwargs={"transaction": transaction.hash})
|
||||
)
|
||||
assert response.status_code == status.HTTP_200_OK
|
||||
|
||||
redsys_response_data = {
|
||||
"Ds_MerchantCode": "999008881",
|
||||
"Ds_Terminal": "001",
|
||||
"Ds_Order": order.hash.hex,
|
||||
"Ds_Order": transaction.hash.hex,
|
||||
"Ds_Amount": "1000",
|
||||
"Ds_Currency": "978",
|
||||
"Ds_Date": "01/01/2024",
|
||||
@@ -160,7 +160,7 @@ class TestRedsysTPV(APITestCase):
|
||||
).decode()
|
||||
|
||||
response = self.client.post(
|
||||
reverse("tpv:webhook", kwargs={"order": order.hash}),
|
||||
reverse("tpv:webhook", kwargs={"transaction": transaction.hash}),
|
||||
data={
|
||||
"Ds_MerchantParameters": b64_merchant_params,
|
||||
"Ds_Signature": settings.REDSYS_SHARED_SECRET,
|
||||
@@ -169,11 +169,11 @@ class TestRedsysTPV(APITestCase):
|
||||
)
|
||||
|
||||
assert response.status_code == status.HTTP_409_CONFLICT
|
||||
order.refresh_from_db()
|
||||
assert str(ERROR_CODES.get("0184")) in order.observations
|
||||
assert order.status == PaymentTPV.StatusChoices.ERROR
|
||||
transaction.refresh_from_db()
|
||||
assert str(ERROR_CODES.get("0184")) in transaction.observations
|
||||
assert transaction.status == PaymentTransaction.StatusChoices.ERROR
|
||||
|
||||
response = self.client.get(
|
||||
reverse("tpv:ko", kwargs={"order": order.hash})
|
||||
reverse("tpv:ko", kwargs={"transaction": transaction.hash})
|
||||
)
|
||||
assert response.status_code == status.HTTP_200_OK
|
||||
|
||||
+5
-5
@@ -1,12 +1,12 @@
|
||||
from django.urls import path
|
||||
from tpv.views import order_created, webhook, payment_accepted, payment_rejected
|
||||
from tpv.views import transaction_created, webhook, payment_accepted, payment_rejected
|
||||
|
||||
app_name = "tpv"
|
||||
|
||||
|
||||
urlpatterns = [
|
||||
path("order/<str:order>/", order_created, name="order_created"),
|
||||
path("order/<str:order>/webhook/", webhook, name="webhook"),
|
||||
path("order/<str:order>/ok/", payment_accepted, name="ok"),
|
||||
path("order/<str:order>/ko/", payment_rejected, name="ko"),
|
||||
path("transaction/<str:transaction>/", transaction_created, name="order_created"),
|
||||
path("transaction/<str:transaction>/webhook/", webhook, name="webhook"),
|
||||
path("transaction/<str:transaction>/ok/", payment_accepted, name="ok"),
|
||||
path("transaction/<str:transaction>/ko/", payment_rejected, name="ko"),
|
||||
]
|
||||
|
||||
+8
-8
@@ -10,7 +10,7 @@ from decimal import Decimal
|
||||
from django.utils.text import gettext_lazy as _
|
||||
|
||||
from tpv.exceptions import RedsysValidationException, RedsysPaymentException
|
||||
from tpv.models import PaymentTPV
|
||||
from tpv.models import PaymentTransaction
|
||||
from tpv.settings import ERROR_CODES
|
||||
|
||||
|
||||
@@ -39,7 +39,7 @@ def compare_signatures(signature_1, signature_2):
|
||||
return sig1safe == sig2safe
|
||||
|
||||
|
||||
def validate_payment_for_order(request, order: PaymentTPV) -> Decimal:
|
||||
def validate_payment_for_transaction(request, transaction: PaymentTransaction) -> Decimal:
|
||||
"""
|
||||
example_response_data = {
|
||||
'Ds_MerchantCode': '999008881',
|
||||
@@ -64,7 +64,7 @@ def validate_payment_for_order(request, order: PaymentTPV) -> Decimal:
|
||||
}
|
||||
|
||||
:param request:
|
||||
:param order:
|
||||
:param transaction:
|
||||
:return:
|
||||
"""
|
||||
data = request.POST
|
||||
@@ -79,8 +79,8 @@ def validate_payment_for_order(request, order: PaymentTPV) -> Decimal:
|
||||
merchant_params = base64.b64decode(merchant_parameters).decode()
|
||||
result = json.loads(merchant_params)
|
||||
|
||||
order_hex = result.get("Ds_Order")
|
||||
assert order_hex == order.hash.hex
|
||||
transaction_hex = result.get("Ds_Order")
|
||||
assert transaction_hex == transaction.hash.hex
|
||||
|
||||
status_code = result.get("Ds_Response")
|
||||
|
||||
@@ -94,6 +94,6 @@ def validate_payment_for_order(request, order: PaymentTPV) -> Decimal:
|
||||
return amount
|
||||
|
||||
|
||||
def pay_order(order: PaymentTPV, amount_paid: Decimal):
|
||||
order.status = PaymentTPV.StatusChoices.PAID
|
||||
order.save()
|
||||
def pay_transaction(transaction: PaymentTransaction, amount_paid: Decimal):
|
||||
transaction.status = PaymentTransaction.StatusChoices.PAID
|
||||
transaction.save()
|
||||
|
||||
+23
-23
@@ -4,68 +4,68 @@ from django.shortcuts import render, get_object_or_404, redirect
|
||||
from django.http.response import HttpResponse
|
||||
|
||||
from tpv.forms import UpdateEmailForm
|
||||
from tpv.models import PaymentTPV
|
||||
from tpv.models import PaymentTransaction
|
||||
from tpv.redsys import RedsysClient
|
||||
from tpv.utils import pay_order, validate_payment_for_order
|
||||
from tpv.utils import pay_transaction, validate_payment_for_transaction
|
||||
from tpv.signals import redsys_payment_accepted, redsys_payment_rejected
|
||||
|
||||
|
||||
def payment_accepted(request, order):
|
||||
order = get_object_or_404(PaymentTPV, hash=order)
|
||||
def payment_accepted(request, transaction):
|
||||
transaction = get_object_or_404(PaymentTransaction, hash=transaction)
|
||||
|
||||
return render(
|
||||
request,
|
||||
template_name="tpv/order_created.html",
|
||||
context={
|
||||
"order": order,
|
||||
"order": transaction,
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
def payment_rejected(request, order):
|
||||
order = get_object_or_404(PaymentTPV, hash=order)
|
||||
def payment_rejected(request, transaction):
|
||||
transaction = get_object_or_404(PaymentTransaction, hash=transaction)
|
||||
|
||||
return render(
|
||||
request,
|
||||
template_name="tpv/order_created.html",
|
||||
context={
|
||||
"order": order,
|
||||
"order": transaction,
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
@csrf_exempt
|
||||
def webhook(request, order):
|
||||
order = get_object_or_404(PaymentTPV, hash=order)
|
||||
def webhook(request, transaction):
|
||||
transaction = get_object_or_404(PaymentTransaction, hash=transaction)
|
||||
|
||||
try:
|
||||
amount_paid = validate_payment_for_order(request, order)
|
||||
pay_order(order, amount_paid)
|
||||
redsys_payment_accepted.send_robust(PaymentTPV.__class__, hash=order.hash)
|
||||
amount_paid = validate_payment_for_transaction(request, transaction)
|
||||
pay_transaction(transaction, amount_paid)
|
||||
redsys_payment_accepted.send_robust(PaymentTransaction.__class__, hash=transaction.hash)
|
||||
|
||||
return HttpResponse(status=200)
|
||||
except Exception as e:
|
||||
order.status = PaymentTPV.StatusChoices.ERROR
|
||||
order.observations = str(e)
|
||||
order.save()
|
||||
redsys_payment_rejected.send_robust(PaymentTPV.__class__, hash=order.hash)
|
||||
transaction.status = PaymentTransaction.StatusChoices.ERROR
|
||||
transaction.observations = str(e)
|
||||
transaction.save()
|
||||
redsys_payment_rejected.send_robust(PaymentTransaction.__class__, hash=transaction.hash)
|
||||
|
||||
return HttpResponse(status=409)
|
||||
|
||||
|
||||
def order_created(request, order):
|
||||
order = get_object_or_404(PaymentTPV, hash=order)
|
||||
def transaction_created(request, transaction):
|
||||
transaction = get_object_or_404(PaymentTransaction, hash=transaction)
|
||||
|
||||
client = RedsysClient()
|
||||
parameters = client.get_body_for_order(order)
|
||||
parameters = client.get_body_for_transaction(transaction)
|
||||
|
||||
return render(
|
||||
request,
|
||||
template_name="tpv/order_created.html",
|
||||
context={
|
||||
"form": UpdateEmailForm({"contact_email": order.contact_email}),
|
||||
"action": reverse("tpv:order_created", kwargs={"order": order.hash}),
|
||||
"order": order,
|
||||
"form": UpdateEmailForm({"contact_email": transaction.contact_email}),
|
||||
"action": reverse("tpv:order_created", kwargs={"transaction": transaction.hash}),
|
||||
"order": transaction,
|
||||
"signature_version": parameters.get("Ds_SignatureVersion"),
|
||||
"merchant_parameters": parameters.get("Ds_MerchantParameters"),
|
||||
"signature": parameters.get("Ds_Signature"),
|
||||
|
||||
Reference in New Issue
Block a user