A django app to emit and listen Redsys/Sermepa POS payments
Project description
Django sermepa es una aplicación muy al estilo de django-paypal para usar el TPV Virtual de Redsys/Sermepa, el TPV más usado en España.
Permite generar cobros puntuales, recurrentes por fichero o por referencia, y devoluciones.
La app tiene una vista que escucha las notificaciones del TPV (se debe pedir su activación a tu banco) y lanza signals para que sean procesadas por tu aplicación de cobros, para cambiar de estado el pedido, enviar emails de notificación…
Este fork implementa la versión 2.1 de Sermepa (SHA-256).
Versiones compatibles
Python: 3.8, 3.9, 3.10, 3.11, 3.12, 3.13
Django: 3.2, 4.0, 4.1, 4.2, 5.0, 5.1
Historial de versiones
2.0.0: Soporte para Django 3.2 a 5.1 y Python 3.8 a 3.13. CI con GitHub Actions. Ver CHANGELOG.md para el detalle completo de cambios.
1.1.5: Corrección de errores en form y mixin. Django 2.2 y Python 3.8.
1.1.4: Corrección de errores de empaquetado, migraciones y readme. Django 1.11 y Python 3.6.
1.1.3: Soporte django 1.4+ (probado en 1.4, 1.5, 1.6, 1.7).
1.1.2: Compatible con python 2.7 y python 3.x.
Instalación
Instala el proyecto usando pip:
pip install django-sermepa-etxea
O directamente desde GitHub:
pip install git+https://github.com/Etxea/django-sermepa
Añádelo a INSTALLED_APPS del settings.py:
INSTALLED_APPS += ('sermepa',)
Aplica migraciones:
python manage.py migrate
Configuración
Añade los siguientes settings:
SERMEPA_URL_PRO = 'https://sis.redsys.es/sis/realizarPago' SERMEPA_URL_TEST = 'https://sis-t.redsys.es:25443/sis/realizarPago' SERMEPA_MERCHANT_CODE = '327234688' # comercio de test SERMEPA_TERMINAL = '002' SERMEPA_SECRET_KEY = 'tu_clave_secreta_en_base64' SERMEPA_CURRENCY = '978' # Euros SERMEPA_SIGNATURE_VERSION = 'HMAC_SHA256_V1'Deberás modificar SERMEPA_MERCHANT_CODE, SERMEPA_SECRET_KEY, SERMEPA_TERMINAL con los datos proporcionados por tu banco.
Añade la ruta de la respuesta de Sermepa a tus urls:
from django.urls import include, path urlpatterns = [ path('sermepa/', include('sermepa.urls')), # ... ]
Uso
Programa los listeners de las signals de OK, KO y si quieres de error:
6.1 El listener recibe un objeto de tipo SermepaResponse con toda la información de la operación del TPV. Puedes usar un listener que procese todos los casos, o uno por cada caso (OK y KO):
def payment_ok(sender, **kwargs): '''sender es un objeto de clase SermepaResponse. Utiliza el campo Ds_MerchantData para asociarlo a tu Pedido o Carrito''' pedido = Pedido.objects.get(id=sender.Ds_MerchantData) pedido.estado = 'cobrado' pedido.Ds_AuthorisationCode = sender.Ds_AuthorisationCode pedido.save() send_email_success(pedido) def payment_ko(sender, **kwargs): '''sender es un objeto de clase SermepaResponse''' pass def sermepa_ipn_error(sender, **kwargs): '''Esta señal salta cuando el POST data recibido está mal firmado.''' pass6.2 Asocia el listener a las señales, en algún punto que se cargue al iniciar el proyecto, por ejemplo en el models.py:
from sermepa.signals import payment_was_successful from sermepa.signals import payment_was_error from sermepa.signals import signature_error payment_was_successful.connect(payment_ok) payment_was_error.connect(payment_ko) signature_error.connect(sermepa_ipn_error)
Utiliza el form de SermepaPaymentForm para inicializar el botón de pago.
El botón de pago será un formulario POST a la url del TPV, firmado con tu clave secreta, que deberá pasar toda la información de la operación: modalidad de pago, importe (en céntimos), URLs de notificación, OK y KO, descripción, datos del comercio, identificador de tu pedido, identificador de la operación…
Existen diferentes modalidades de pago:
Las compras puntuales, el Ds_Merchant_TransactionType=’0’ y el Ds_Merchant_Order debe ser un string siempre único y de 10 caracteres.
Las suscripciones o pagos recurrentes. Existen 2 tipos, por fichero o por referencia.
2.1 Por fichero, tienen un límite de 12 meses o 12 cobros.
2.1.1 El primer cobro el Ds_Merchant_TransactionType=’L’ y el Ds_Merchant_Order debe ser siempre único.
El tpv responde con el mismo valor pasado en la variable Ds_Order más 2 dígitos adicionales indicando el número de transacción (la primera es 00)
2.1.2 Los cobros sucesivos se debe pasar el Ds_Merchant_TransactionType=’M’ y el primer Ds_Merchant_Order
2.2 Por referencia, no tiene límite de tiempo ni de cobros. Este sistema soporta cobros de 0€ para activaciones y cambios de tarjetas.
2.2.1 El primer cobro el Ds_Merchant_TransactionType=’0’ y el Ds_Merchant_Order=’REQUIRED’
El tpv responde con un nuevo parámetro Ds_Merchant_Identifier, que hay que almacenar (idreferencia)
2.2.2 Los cobros sucesivos son Ds_Merchant_TransactionType=’0’ y el Ds_Merchant_Order=idreferencia (el valor que nos han pasado en el primero cobro)
Mira el código del ejemplo (sermepa_test/views.py) para más info:
from django.shortcuts import render from django.urls import reverse from sermepa.forms import SermepaPaymentForm from sermepa.models import SermepaIdTPV def form(request, trans_type='0'): site = Site.objects.get_current() amount = int(5.50 * 100) # El precio es en céntimos de euro sermepa_dict = { "Ds_Merchant_Titular": 'John Doe', "Ds_Merchant_MerchantData": 12345, "Ds_Merchant_MerchantName": 'ACME', "Ds_Merchant_ProductDescription": 'petardos', "Ds_Merchant_Amount": amount, "Ds_Merchant_Terminal": settings.SERMEPA_TERMINAL, "Ds_Merchant_MerchantCode": settings.SERMEPA_MERCHANT_CODE, "Ds_Merchant_Currency": settings.SERMEPA_CURRENCY, "Ds_Merchant_MerchantURL": "http://%s%s" % (site.domain, reverse('sermepa_ipn')), "Ds_Merchant_UrlOK": "http://%s%s" % (site.domain, reverse('end')), "Ds_Merchant_UrlKO": "http://%s%s" % (site.domain, reverse('end')), "Ds_Merchant_Order": SermepaIdTPV.objects.new_idtpv(), "Ds_Merchant_TransactionType": '0', } form = SermepaPaymentForm(merchant_parameters=sermepa_dict) return render(request, 'form.html', {'form': form, 'debug': settings.DEBUG})y el form.html:
<html> <body> {% if debug %} {{ form.sandbox }} {% else %} {{ form.render_form }} {% endif %} </body> </html>
El TPV enviará una respuesta (SermepaResponse) con la información que se le ha enviado más nuevos datos relacionados con el pago. A destacar:
Ds_MerchantData es el mismo valor enviado en el formulario en el campo Ds_Merchant_MerchantData. Debería contener el identificador de tu Pedido o Carrito
Ds_Merchant_Identifier: la referencia para cobros recurrentes sucesivos si se utiliza el pago por referencia.
Ds_ExpiryDate: Fecha de expiración de la tarjeta
Ds_Card_Number: Número asteriscado de la tarjeta
Ds_AuthorisationCode: Código de la operación autorizada, para poder hacer una devolución posterior.
Prueba el formulario de compra puntual en http://localhost:8000/ o http://localhost:8000/L/ …
Desarrollo
Ejecutar tests:
pip install pytest pytest-django DJANGO_SETTINGS_MODULE=settings pytest sermepa/tests.py -v
Ejecutar tests en múltiples versiones con tox:
pip install tox tox
Licencia
MIT License
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file django_sermepa_etxea-2.1.1.tar.gz.
File metadata
- Download URL: django_sermepa_etxea-2.1.1.tar.gz
- Upload date:
- Size: 12.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
87ee73c8fcdec4635415bf953390f7c690a6239adde067f0aaa5967116d6344b
|
|
| MD5 |
e7c6ee4d10eded88948fc226a81e26bb
|
|
| BLAKE2b-256 |
9be48d19f0457fb5f4d1a7c923b20120d08a12e43d90d544cf63658e322301c6
|
Provenance
The following attestation bundles were made for django_sermepa_etxea-2.1.1.tar.gz:
Publisher:
publish.yml on etxea/django-sermepa
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
django_sermepa_etxea-2.1.1.tar.gz -
Subject digest:
87ee73c8fcdec4635415bf953390f7c690a6239adde067f0aaa5967116d6344b - Sigstore transparency entry: 1283742396
- Sigstore integration time:
-
Permalink:
etxea/django-sermepa@ca9b9b9d9cf21b451a4c850305cfd528650b54e9 -
Branch / Tag:
refs/tags/v2.1.1 - Owner: https://github.com/etxea
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@ca9b9b9d9cf21b451a4c850305cfd528650b54e9 -
Trigger Event:
push
-
Statement type:
File details
Details for the file django_sermepa_etxea-2.1.1-py3-none-any.whl.
File metadata
- Download URL: django_sermepa_etxea-2.1.1-py3-none-any.whl
- Upload date:
- Size: 14.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
097266782db3eaf3e2663ec2c3a350f6cd9a081b6d817e7c8b60e5eaa15b2078
|
|
| MD5 |
ed956845bdd9c27ac7b8355f093a09ec
|
|
| BLAKE2b-256 |
38e924ff34ae51717bb5666580661b5daf2e4153331c479664acbb4eed341572
|
Provenance
The following attestation bundles were made for django_sermepa_etxea-2.1.1-py3-none-any.whl:
Publisher:
publish.yml on etxea/django-sermepa
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
django_sermepa_etxea-2.1.1-py3-none-any.whl -
Subject digest:
097266782db3eaf3e2663ec2c3a350f6cd9a081b6d817e7c8b60e5eaa15b2078 - Sigstore transparency entry: 1283742732
- Sigstore integration time:
-
Permalink:
etxea/django-sermepa@ca9b9b9d9cf21b451a4c850305cfd528650b54e9 -
Branch / Tag:
refs/tags/v2.1.1 - Owner: https://github.com/etxea
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@ca9b9b9d9cf21b451a4c850305cfd528650b54e9 -
Trigger Event:
push
-
Statement type: