diff --git a/README.md b/README.md index 588d01e..9c7ba11 100644 --- a/README.md +++ b/README.md @@ -95,8 +95,28 @@ Puedes crear un archivo `.env` con las siguientes variables de entorno. | AWS_SECRET_ACCESS_KEY | | Clave secreta de S3 | | AWS_STORAGE_BUCKET_NAME | | Nombre del bucket de S3 | | AWS_S3_ENDPOINT_URL | | Endpoint de S3 | -| REDSYS_SHARED_SECRET | sq7HjrUOBfKmC576ILgskD5srU870gJ7 | Clave privada de Redsys | -| REDSYS_MERCHANT_CODE | 999008881 | Código de negocio de Redsys | -| REDSYS_TERMINAL | 001 | Terminal de Redsys | -| REDSYS_CURRENCY_CODE | 978 | Código de moneda de Redsys | -| REDSYS_TPV_DOMAIN | | Dominio del TPV para redirección de Redsys | + + +## Depurar pagos TPV con Redsys + +Para poder usar el TPV en la máquina local necesitaremos instalar y configurar [`ngrok`](https://ngrok.com/), +siguiendo los pasos que nos indican en la web al crear nuestra cuenta + +Arrancaremos ngrok con el siguiente comando: + +```bash +ngrok http http://localhost:8000 +``` + +Ngrok nos dará una URL accesible desde fuera, que tendremos que guardar en los `Ajustes de la tienda` +como `Dominio del TPV` + +Tendremos que establecer también los siguientes ajustes de la cuenta con estos valores para desarrollo. + +| Variable | Valor para desarrollo | Descripción | +|------------------------|----------------------------------|------------------------------------------------------------------------------| +| `redsys_shared_secret` | sq7HjrUOBfKmC576ILgskD5srU870gJ7 | Clave privada de Redsys | +| `merchant_code` | 999008881 | Código de negocio de Redsys | +| `terminal` | 001 | Terminal de Redsys | +| `currency_code` | 978 | Código de moneda de Redsys | +| `tpv_domain` | | Dominio del TPV para redirección de Redsys (en local lo obtenemos por ngrok) | diff --git a/shop/migrations/0004_shopsettings_tpv_domain.py b/shop/migrations/0004_shopsettings_tpv_domain.py new file mode 100644 index 0000000..cc196ab --- /dev/null +++ b/shop/migrations/0004_shopsettings_tpv_domain.py @@ -0,0 +1,20 @@ +# Generated by Django 5.1.4 on 2025-01-13 08:05 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ("shop", "0003_order_shipping_method_alter_payment_order"), + ] + + operations = [ + migrations.AddField( + model_name="shopsettings", + name="tpv_domain", + field=models.URLField( + blank=True, max_length=128, null=True, verbose_name="dominio del tpv" + ), + ), + ] diff --git a/shop/models.py b/shop/models.py index 00ae41b..603c07e 100644 --- a/shop/models.py +++ b/shop/models.py @@ -631,6 +631,9 @@ class ShopSettings(SingletonModel): ) # 978 == EURO terminal = models.CharField(max_length=8, verbose_name=_("Terminal")) shared_secret = models.CharField(max_length=100, verbose_name=_("Clave de Redsys")) + tpv_domain = models.URLField( + max_length=128, blank=True, null=True, verbose_name=_("dominio del tpv") + ) class Meta: verbose_name = _("ajustes de la tienda") diff --git a/shop/redsys.py b/shop/redsys.py index 8199823..ec11219 100644 --- a/shop/redsys.py +++ b/shop/redsys.py @@ -7,7 +7,7 @@ from django.conf import settings from django.urls import reverse from shop.exceptions import RedsysPaymentException -from shop.models import Order +from shop.models import Order, ShopSettings from shop.settings import TransactionTypes from shop.utils import compute_signature, decode_b64_dict @@ -21,6 +21,9 @@ class RedsysClient: ) REST_PROD_ENVIRONMENT_URL = "https://sis.redsys.es/sis/rest/trataPeticionREST" + def __init__(self): + self.settings = ShopSettings.load() + def get_target_url(self): if settings.DEBUG: return self.DEBUG_ENVIRONMENT_URL @@ -32,31 +35,31 @@ class RedsysClient: return self.REST_PROD_ENVIRONMENT_URL def get_merchant_code(self) -> str: - return settings.REDSYS_MERCHANT_CODE + return self.settings.merchant_code def get_terminal(self) -> str: - return settings.REDSYS_TERMINAL + return self.settings.terminal def get_currency_code(self) -> str: - return settings.REDSYS_CURRENCY_CODE + return self.settings.currency_code def get_merchant_url_ok_for_order(self, order: Order) -> str: path = reverse("web:order", kwargs={"uuid": order.uuid}) - return f"{settings.REDSYS_TPV_DOMAIN}{path}" + return f"{self.settings.tpv_domain}{path}" def to_integer(self, value: Decimal): return int(value * 100) def get_merchant_url_ko_for_order(self, order: Order) -> str: path = reverse("web:order", kwargs={"uuid": order.uuid}) - return f"{settings.REDSYS_TPV_DOMAIN}{path}" + return f"{self.settings.tpv_domain}{path}" def get_webhook_url_for_order(self, order: Order) -> str: path = reverse("shop:webhook", kwargs={"uuid": order.uuid}) - return f"{settings.REDSYS_TPV_DOMAIN}{path}" + return f"{self.settings.tpv_domain}{path}" def get_shared_secret(self) -> str: - return settings.REDSYS_SHARED_SECRET + return self.settings.shared_secret def get_signature(self, hash, payload: str): key = self.get_shared_secret() diff --git a/shop/signals.py b/shop/signals.py index 92d3d99..9950053 100644 --- a/shop/signals.py +++ b/shop/signals.py @@ -1,5 +1,4 @@ from django.core.signals import Signal - clear_cart = Signal() send_order_email = Signal() diff --git a/shop/tests/test_redsys.py b/shop/tests/test_redsys.py index 72a1537..d368a71 100644 --- a/shop/tests/test_redsys.py +++ b/shop/tests/test_redsys.py @@ -2,14 +2,13 @@ import base64 import json from decimal import Decimal -from django.conf import settings from django.contrib.auth import get_user_model from django.urls import reverse from django.utils import timezone from rest_framework import status from rest_framework.test import APITestCase -from shop.models import CustomerAddress, Order, Tax +from shop.models import CustomerAddress, Order, ShopSettings, Tax from shop.redsys import RedsysClient from shop.tests.mixins import CreateProductsMixin from shop.utils import create_order, create_order_line_for_product, validate_expiry_date @@ -26,7 +25,7 @@ class TestRedsysTPV(APITestCase, CreateProductsMixin): self.customer = get_user_model().objects.create_user( username="11111111H", first_name="Darth", - last_name="Maull", + last_name="Maul", email="darth@maul.com", password="dathomir", ) @@ -53,6 +52,9 @@ class TestRedsysTPV(APITestCase, CreateProductsMixin): self.product = self.create_product() self.order = self.create_order() self.order.calculate_total_from_lines() + self.settings = ShopSettings.load() + self.settings.shared_secret = "sq7HjrUOBfKmC576ILgskD5srU870gJ7" # Debug secret + self.settings.save() def create_order(self): order = create_order( @@ -83,12 +85,10 @@ class TestRedsysTPV(APITestCase, CreateProductsMixin): assert merchant_parameters.get("DS_MERCHANT_AMOUNT") == str( int(amount_to_pay * 100) ) - assert ( - merchant_parameters.get("DS_MERCHANT_TERMINAL") == settings.REDSYS_TERMINAL - ) + assert merchant_parameters.get("DS_MERCHANT_TERMINAL") == self.settings.terminal assert ( merchant_parameters.get("DS_MERCHANT_MERCHANTCODE") - == settings.REDSYS_MERCHANT_CODE + == self.settings.merchant_code ) client.get_body_for_order(self.order) @@ -124,7 +124,7 @@ class TestRedsysTPV(APITestCase, CreateProductsMixin): reverse("shop:webhook", kwargs={"uuid": self.order.uuid}), data={ "Ds_MerchantParameters": b64_merchant_params, - "Ds_Signature": settings.REDSYS_SHARED_SECRET, + "Ds_Signature": self.settings.shared_secret, "Ds_SignatureVersion": "HMAC_SHA256_V1", }, ) @@ -164,7 +164,7 @@ class TestRedsysTPV(APITestCase, CreateProductsMixin): reverse("shop:webhook", kwargs={"uuid": self.order.uuid}), data={ "Ds_MerchantParameters": b64_merchant_params, - "Ds_Signature": settings.REDSYS_SHARED_SECRET, + "Ds_Signature": self.settings.shared_secret, "Ds_SignatureVersion": "HMAC_SHA256_V1", }, ) diff --git a/shop/views.py b/shop/views.py index da9aba0..76c2158 100644 --- a/shop/views.py +++ b/shop/views.py @@ -3,7 +3,7 @@ from django.shortcuts import get_object_or_404 from django.views.decorators.csrf import csrf_exempt from shop.models import Order -from shop.utils import validate_payment_for_order, pay_order +from shop.utils import pay_order, validate_payment_for_order @csrf_exempt diff --git a/theme/templates/theme/base.html b/theme/templates/theme/base.html index 207f9b2..6120cb0 100644 --- a/theme/templates/theme/base.html +++ b/theme/templates/theme/base.html @@ -20,7 +20,6 @@ {% endblock %} - - + diff --git a/web/templates/components/icons/star.svg b/web/templates/components/icons/star.svg index 738b998..e1100ea 100644 --- a/web/templates/components/icons/star.svg +++ b/web/templates/components/icons/star.svg @@ -1,5 +1,4 @@ -