add payment_redsys_preauth

This commit is contained in:
Luis 2026-06-24 11:49:41 +02:00
parent 0f2c8c0565
commit 08e34c1426
18 changed files with 1043 additions and 0 deletions

View file

@ -0,0 +1,133 @@
===========================================
Pasarela de pago Redsys con preautorización
===========================================
..
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! source digest: sha256:1eb9535d052a619aa545a383869076ca1dc1fade22746cb3fe13afa726c3e3a3
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png
:target: https://odoo-community.org/page/development-status
:alt: Beta
.. |badge2| image:: https://img.shields.io/badge/licence-AGPL--3-blue.png
:target: http://www.gnu.org/licenses/agpl-3.0-standalone.html
:alt: License: AGPL-3
.. |badge3| image:: https://img.shields.io/badge/github-Criptomart%2Ffoodcoopbcn-lightgray.png?logo=github
:target: https://github.com/Criptomart/foodcoopbcn/tree/12.0/payment_redsys_preauth
:alt: Criptomart/foodcoopbcn
|badge1| |badge2| |badge3|
Este módulo añade la opción de pago a través de la pasarela de Redsys con preautorización con tarjeta bancaria.
**Table of contents**
.. contents::
:local:
Configuration
=============
Parámetros
~~~~~~~~~~
* **Nombre del comercio**: Indicaremos el nombre del comercio.
* **Número de comercio (FUC)**: Indicaremos el número de comercio que
nuestra entidad nos ha comunicado.
* **Clave secreta de encriptación**: Indicaremos la clave de encriptación
que tiene el comercio.
* **Número de terminal**: Indicaremos el terminal del TPV.
* **Tipo de firma**: Seleccionaremos el tipo de firma del comercio.
* **Tipo de moneda**: Seleccionaremos la moneda de nuestro terminal TPV
(Normalmente EUR - Euros).
* **Tipo de transacción**: Indicaremos el tipo de transacción, 1.
* **Idioma TPV**: Indicaremos el idioma en el TPV.
* **Método de pago**: Indicaremos que tipo de pago se debe aceptar, pago con
tarjeta, Bizum u otro de los disponibles.
* **URL_OK/URL_KO**: Durante el proceso del pago, y una vez que
se muestra al cliente la pantalla con el resultado del mismo, es
posible redirigir su navegador a una URL para las transacciones
autorizadas y a otra si la transacción ha sido denegada. A éstas
se las denomina URL_OK y URL_KO, respectivamente. Se trata
de dos URLs que pueden ser proporcionadas por el comercio.
* **Porcentaje de pago**: Indicar el porcentaje de pago que se permite, si
se deja a 0.0 se entiende 100%.
Nota
~~~~
Se tiene que verificar la configuración del comercio en el
módulo de administración de Redsys, donde la opción “Parámetros en las
URLs” debe tener el valor “SI”.
En caso de que exista más de una base de datos en la instalación, cuando la
pasarela de pago envía el formulario a "/payment/redsys/return" odoo no sabe
con que base de datos procesar esta información, por lo que hay que establecer
los parametros **dbfilter** y **dbname** en el archivo de configuración.
Para mostrar simultáneamente en el comercio electrónico varios de los métodos
de pago que proporciona Redsys, como pago con tarjeta y Bizum por ejemplo,
debemos duplicar el medio de pago y escoger en el campo método de pago el que
corresponda en cada caso.
En los pagos con preautorización, el titular del TPV deberá solicitar al banco su activación.
Known issues / Roadmap
======================
De acuerdo a los requisitos de Redsys, el tamaño máximo del número de pedido
resultante (``Ds_Order``) es de 12 caracteres. Este addon trunca dicho
dato en el comienzo de la transacción, con el resultado de que, aunque Redsys
la aceptará, no se finalizará el pedido pedido en Odoo al retornar y entregará
un Error 500 a Redsys.
Para evitar esto, es recomendable seleccionar secuencias de pedido que se
ajusten a esta limitación, en particular de 10 o menos caracteres, al ser la
referencia un número extendido a partir del pedido, que incluye un guion y un
número secuencial para posibles repeticiones de pago.
Bug Tracker
===========
Bugs are tracked on `GitHub Issues <https://github.com/Criptomart/foodcoopbcn/issues>`_.
In case of trouble, please check there if your issue has already been reported.
If you spotted it first, help us to smash it by providing a detailed and welcomed
`feedback <https://github.com/Criptomart/foodcoopbcn/issues/new?body=module:%20payment_redsys_preauth%0Aversion:%2012.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_.
Do not contact contributors directly about support or help with technical issues.
Credits
=======
Authors
~~~~~~~
* Criptomart
Contributors
~~~~~~~~~~~~
* `Criptomart <https://www.criptomart.net>`_:
* Santi Noreña
Maintainers
~~~~~~~~~~~
This module is part of the `Criptomart/foodcoopbcn <https://github.com/Criptomart/foodcoopbcn/tree/12.0/payment_redsys_preauth>`_ project on GitHub.
You are welcome to contribute.

View file

@ -0,0 +1,4 @@
# License AGPL-3 - See https://www.gnu.org/licenses/agpl-3.0.html
from . import models
from . import controllers

View file

@ -0,0 +1,15 @@
# Copyright 2024 - 2025 Criptomart
{
"name": "Pasarela de pago Redsys con preautorización",
"category": "Payment Acquirer",
"summary": "Payment Acquirer: Redsys Implementation with Preauthorization",
"version": "16.0.0.0.1",
"author": "Criptomart",
"website": "https://git.criptomart.net/foodcoopbcn",
"depends": ["payment_redsys","sale_order_invoice_amount"],
"data": [
"data/payment_redsys.xml"
],
"license": "AGPL-3",
"installable": True,
}

View file

@ -0,0 +1,2 @@
from . import main

View file

@ -0,0 +1,29 @@
# © 2024 - 2025 criptomart.net
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
import logging
import pprint
from odoo import http
from odoo.http import request
from odoo.addons.payment_redsys.controllers.main import RedsysController
_logger = logging.getLogger(__name__)
class RedsysController(RedsysController):
_return_url = '/payment/redsys/return'
_cancel_url = '/payment/redsys/cancel'
_exception_url = '/payment/redsys/error'
_reject_url = '/payment/redsys/reject'
@http.route(['/payment/redsys/result/<page>'], type='http', auth='public',methods=['GET'], website=True)
def redsys_result(self, page, **post):
_logger.info('________ Redsys return sync: %s -- %s',
pprint.pformat(post), page)
# double check
if post:
request.env['payment.transaction'].sudo()._handle_notification_data('redsys', post)
return request.redirect('/payment/status')

View file

@ -0,0 +1,26 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright 2024-2025 Criptomart
License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl-3). -->
<odoo noupdate="1">
<record id="payment_provider_redsys_preauth" model="payment.provider">
<field name="name">Redsys Preautorización </field>
<field name="image_128" type="base64" file="payment_redsys_preauth/static/description/icon.png"/>
<field name="code">redsys</field>
<field name="company_id" ref="base.main_company"/>
<field name="redsys_merchant_name">Bussines name</field>
<field name="redsys_merchant_code">8888888</field>
<field name="redsys_merchant_description">Bussines description</field>
<field name="redsys_secret_key">xxxxxxxxxxxx -- SHA256</field>
<field name="redsys_terminal">001</field>
<field name="redsys_transaction_type">1</field>
<field name="module_id" ref="base.module_payment_redsys_preauth"/>
<field name="pre_msg"><![CDATA[<p>You will be redirected to the Redsys payment gateway after clicking on the payment button.</p>]]></field>
</record>
<record id="payment_icon_cc_bizum" model="payment.icon">
<field name="name">Bizum</field>
<field name="image" type="base64" file="payment_redsys_preauth/static/img/bizum.png"/>
</record>
</odoo>

View file

@ -0,0 +1,2 @@
from . import payment_provider
from . import payment_transaction

View file

@ -0,0 +1,135 @@
# © 2024 - 2025 criptomart
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
import logging
import json
import pprint
import requests
import urllib
from odoo import models, api, exceptions, fields
from odoo.addons.payment.models.payment_provider import ValidationError
from odoo.tools.float_utils import float_compare
from odoo.tools.translate import _
import odoo.exceptions
_logger = logging.getLogger(__name__)
class PaymentProvider(models.Model):
_inherit = 'payment.provider'
@api.depends('code')
def _compute_feature_support_fields(self):
super()._compute_feature_support_fields()
self.update({
'support_manual_capture': 'partial',
})
def get_redsys_rest_urls(self, environment):
""" Redsys Rest URLs
"""
if environment == 'prod':
return {
'redsys_rest_url':
'https://sis.redsys.es/sis/rest/trataPeticionREST',
}
else:
# redsys no acepta preautorizaciones en test, pero puede que cambie...
return {
'redsys_rest_url':
'https://sis-t.redsys.es:25443/sis/rest/trataPeticionREST',
}
def _prepare_merchant_parameters(self, tx_values):
base_url = self._get_website_url()
callback_url = "http://botiga.foodcoopbcn.cat"
values = {
"Ds_Sermepa_Url": self._redsys_get_api_url(),
"Ds_Merchant_Amount": str(int(round(tx_values["amount"] * 100))),
"Ds_Merchant_Currency": self.redsys_currency or "978",
"Ds_Merchant_Order": (
tx_values["reference"] and tx_values["reference"][-12:] or False
),
"Ds_Merchant_MerchantCode": (
self.redsys_merchant_code and self.redsys_merchant_code[:9]
),
"Ds_Merchant_Terminal": self.redsys_terminal or "1",
"Ds_Merchant_TransactionType": (self.redsys_transaction_type or "1"),
"Ds_Merchant_Titular": tx_values.get(
"billing_partner", self.env.user.partner_id
).display_name[:60],
"Ds_Merchant_MerchantName": (
self.redsys_merchant_name and self.redsys_merchant_name[:25]
),
"Ds_Merchant_MerchantUrl": (
"%s/payment/redsys/return" % (callback_url or base_url)
)[:250],
"Ds_Merchant_MerchantData": self.redsys_merchant_data or "",
"Ds_Merchant_ProductDescription": (
self.redsys_merchant_description
and self.redsys_merchant_description[:125]
),
"Ds_Merchant_ConsumerLanguage": (self.redsys_merchant_lang or "001"),
"Ds_Merchant_UrlOk": "%s/payment/redsys/result/redsys_result_ok" % base_url,
"Ds_Merchant_UrlKo": "%s/payment/redsys/result/redsys_result_ko" % base_url,
"Ds_Merchant_Paymethods": self.redsys_pay_method or "T",
}
return self._url_encode64(json.dumps(values)).decode("utf-8")
def _prepare_s2s_merchant_parameters(self, tx_values):
values = {
'Ds_Merchant_Amount': str(int(round(tx_values['amount'] * 100))),
'Ds_Merchant_Currency': self.redsys_currency or '978',
'Ds_Merchant_Order': (
tx_values['reference'] and tx_values['reference'][-12:] or
False),
'Ds_Merchant_MerchantCode': (
self.redsys_merchant_code and
self.redsys_merchant_code[:9]),
'Ds_Merchant_Terminal': self.redsys_terminal or '1',
}
if 'transaction_type' in tx_values:
values.update({'Ds_Merchant_TransactionType': tx_values['transaction_type']})
else:
values.update({'Ds_Merchant_TransactionType':
(self.redsys_transaction_type or '2')}),
return self._url_encode64(json.dumps(values))
def redsys_s2s_create_transaction(self, values):
self.ensure_one()
redsys_values = dict()
merchant_parameters = self._prepare_s2s_merchant_parameters(values)
redsys_values.update({
'Ds_SignatureVersion': str(self.redsys_signature_version),
'Ds_MerchantParameters': merchant_parameters,
'Ds_Signature': self.sign_parameters(
self.redsys_secret_key, merchant_parameters),
})
return redsys_values
def redsys_send_s2s_msg(self, values):
toSend = self.redsys_s2s_create_transaction(values)
url = self.get_redsys_rest_urls('prod')['redsys_rest_url']
_logger.info('Redsys: sending rest values:\n%s', pprint.pformat(toSend))
try:
if toSend and url:
response = requests.post(url, data=toSend)
else:
raise exceptions.ValidationError('Error en los parámetros de la petición rest')
except requests.exceptions.RequestException as e:
_logger.error('Redsys: Error sending rest transaction %s:\n%s', values['reference'], str(e))
return False
if response and response.status_code != 200:
_logger.error('Redsys: Error sending rest transaction %s: %s', values['reference'], response.status_code)
return False
_logger.info('Redsys: rest response:\n%s', pprint.pformat(response.text))
try:
errorCheck = response.json()
if errorCheck.get('errorCode', ''):
_logger.error('Redsys: Error recibido tx %s: %s', values['reference'], errorCheck.get('errorCode'))
except json.JSONDecodeError:
_logger.error('Error al decodificar la respuesta JSON para la transacción %s', values['reference'])
return False
return errorCheck

View file

@ -0,0 +1,150 @@
# © 2024 - 2025 criptomart
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).
import logging
import json
import pprint
import requests
from odoo import models, api, exceptions, fields
from odoo.addons.payment.models.payment_provider import ValidationError
from odoo.tools.float_utils import float_compare
from odoo.tools.translate import _
_logger = logging.getLogger(__name__)
class TxRedsysPreAuth(models.Model):
_inherit = 'payment.transaction'
def _get_specific_rendering_values(self, processing_values):
if self.provider_code != "redsys":
return super()._get_specific_rendering_values(processing_values)
redsys_values = dict(processing_values)
merchant_parameters = self.provider_id._prepare_merchant_parameters(
processing_values
)
redsys_values.update(
{
"api_url": self.provider_id._redsys_get_api_url(),
"Ds_SignatureVersion": str(self.provider_id.redsys_signature_version),
"Ds_MerchantParameters": merchant_parameters,
"Ds_Signature": self.provider_id.sign_parameters(
self.provider_id.redsys_secret_key, merchant_parameters
),
}
)
return redsys_values
# chequea que el usuario cancele el pago 9915. cambia el stado de done a authorized
@api.model
def _get_redsys_state(self, status_code):
if 0 <= status_code <= 100:
return "authorized"
elif status_code <= 203:
return "pending"
elif status_code == 400:
return "cancel"
elif status_code == 900:
return "done"
elif 912 <= status_code <= 9915:
return "cancel"
else:
return "error"
def _process_notification_data(self, data):
if self.provider_code != "redsys":
return super()._process_notification_data(data)
params = self.merchant_params_json2dict(data)
status_code = int(params.get('Ds_Response', '29999'))
state = self._get_redsys_state(status_code)
vals = {
'state': state,
'redsys_txnid': params.get('Ds_AuthorisationCode'),
}
state_message = ""
feedback_error = False
if state == 'done':
vals['state_message'] = _('Ok: %s') % params.get('Ds_Response')
self._set_done()
self._finalize_post_processing()
if state == 'authorized':
vals['state_message'] = _('Auth Ok: %s') % params.get('Ds_Response')
self._set_authorized()
self._finalize_post_processing()
elif state == 'pending': # 'Payment error: code: %s.'
state_message = _("Redsys: feedback error: %s" %(status_code))
self._set_pending()
elif state == 'cancel': # 'Payment error: bank unavailable.'
state_message = _("Redsys: feedback error: %s" %(status_code))
self._set_canceled()
else:
state_message = _("Redsys: feedback error: %s" %(status_code))
self._set_error(state_message)
feedback_error = True
if state_message:
vals['state_message'] = state_message % {
"status_code": params.get("Ds_Response"),
"error_code": params.get("Ds_ErrorCode"),
}
if state == 'error':
_logger.warning(vals['state_message'])
self.write(vals)
def _send_capture_request(self, amount_to_capture=None):
self.ensure_one()
self._ensure_provider_is_not_disabled()
_logger.info('Redsys: Capturing transaction %s -- %s', self.reference, amount_to_capture)
try:
if amount_to_capture:
values = {'amount': amount_to_capture}
else:
values = {'amount': sum(order.invoiced_amount for order in self.sale_order_ids)}
values.update({'reference': self.reference})
values.update({'transaction_type': '2'})
response = self.provider_id.redsys_send_s2s_msg(values)
if not response:
raise exceptions.ValidationError('Error mandando mensaje rest');
if response.get('errorCode', ''):
raise exceptions.ValidationError('Ref %s: Error Code %s' %(self.reference, response.get('errorCode')))
params = self.merchant_params_json2dict(response)
_logger.info('Redsys: parameters received:\n%s', pprint.pformat(params))
if params['Ds_Response'] == '0900' and params['Ds_Order'] == self.reference:
self.provider_reference = params['Ds_AuthorisationCode']
self._set_done()
_logger.info('Confirmacion de preautorizacion realizada con exito para la transaccion %s', self.reference)
message = ('Preautorizacion confirmada')
self.sale_order_ids.message_post(body=message)
else:
raise exceptions.ValidationError('Error en confirmacion de preautorizacion tx: %s - %s', self.reference, params['Ds_Response'])
except Exception as e:
_logger.exception('Redsys: Error capturando preautorización transacción %s:\n%s', self.reference, str(e))
raise exceptions.UserError(_('Error capturing preauthorization for transaction %s:\n%s') % (self.reference, str(e)))
def _send_void_request(self, amount_to_void=None):
self.ensure_one()
self._ensure_provider_is_not_disabled()
_logger.info('Redsys: Preauthorization cancel for transaction %s', self.reference)
try:
if amount_to_void:
values = {'amount': amount_to_void}
else:
values = {'amount': self.amount}
values.update({'reference': self.reference})
values.update({'transaction_type': '9'})
response = self.provider_id.redsys_send_s2s_msg(values)
if not response:
raise exceptions.ValidationError(_('error redsys_s2s_msg'))
if response.get('errorCode', ''):
raise exceptions.ValidationError('Ref %s: Error Code %s' % (self.reference, response.get('errorCode')))
params = self.merchant_params_json2dict(response)
_logger.info('Redsys: parameters received):\n%s', pprint.pformat(params))
if params['Ds_Response'] == '0400' and params['Ds_Order'] == self.reference:
self._set_canceled()
_logger.info('Preautorización cancelada con éxito para la transacción %s', self.reference)
else:
raise exceptions.ValidationError('No se pudo cancelar la preautorización para la transacción %s - %s', self.reference, params['Ds_Response'])
except Exception as e:
_logger.exception('Redsys Error cancelando preautorización tx %s:\n%s', self.reference, str(e))
raise exceptions.UserError(_('Error cancelling preauthorization for transaction %s:\n%s') % (self.reference, str(e)))

View file

@ -0,0 +1,54 @@
Parámetros
~~~~~~~~~~
* **Nombre del comercio**: Indicaremos el nombre del comercio.
* **Número de comercio (FUC)**: Indicaremos el número de comercio que
nuestra entidad nos ha comunicado.
* **Clave secreta de encriptación**: Indicaremos la clave de encriptación
que tiene el comercio.
* **Número de terminal**: Indicaremos el terminal del TPV.
* **Tipo de firma**: Seleccionaremos el tipo de firma del comercio.
* **Tipo de moneda**: Seleccionaremos la moneda de nuestro terminal TPV
(Normalmente EUR - Euros).
* **Tipo de transacción**: Indicaremos el tipo de transacción, 1.
* **Idioma TPV**: Indicaremos el idioma en el TPV.
* **Método de pago**: Indicaremos que tipo de pago se debe aceptar, pago con
tarjeta, Bizum u otro de los disponibles.
* **URL_OK/URL_KO**: Durante el proceso del pago, y una vez que
se muestra al cliente la pantalla con el resultado del mismo, es
posible redirigir su navegador a una URL para las transacciones
autorizadas y a otra si la transacción ha sido denegada. A éstas
se las denomina URL_OK y URL_KO, respectivamente. Se trata
de dos URLs que pueden ser proporcionadas por el comercio.
* **Porcentaje de pago**: Indicar el porcentaje de pago que se permite, si
se deja a 0.0 se entiende 100%.
Nota
~~~~
Se tiene que verificar la configuración del comercio en el
módulo de administración de Redsys, donde la opción “Parámetros en las
URLs” debe tener el valor “SI”.
En caso de que exista más de una base de datos en la instalación, cuando la
pasarela de pago envía el formulario a "/payment/redsys/return" odoo no sabe
con que base de datos procesar esta información, por lo que hay que establecer
los parametros **dbfilter** y **dbname** en el archivo de configuración.
Para mostrar simultáneamente en el comercio electrónico varios de los métodos
de pago que proporciona Redsys, como pago con tarjeta y Bizum por ejemplo,
debemos duplicar el medio de pago y escoger en el campo método de pago el que
corresponda en cada caso.
En los pagos con preautorización, el titular del TPV deberá solicitar al banco su activación.

View file

@ -0,0 +1,3 @@
* `Criptomart <https://www.criptomart.net>`_:
* Santi Noreña

View file

@ -0,0 +1 @@
Este módulo añade la opción de pago a través de la pasarela de Redsys con preautorización con tarjeta bancaria.

View file

@ -0,0 +1,9 @@
De acuerdo a los requisitos de Redsys, el tamaño máximo del número de pedido
resultante (``Ds_Order``) es de 12 caracteres. Este addon trunca dicho
dato en el comienzo de la transacción, con el resultado de que, aunque Redsys
la aceptará, no se finalizará el pedido pedido en Odoo al retornar y entregará
un Error 500 a Redsys.
Para evitar esto, es recomendable seleccionar secuencias de pedido que se
ajusten a esta limitación, en particular de 10 o menos caracteres, al ser la
referencia un número extendido a partir del pedido, que incluye un guion y un
número secuencial para posibles repeticiones de pago.

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

View file

@ -0,0 +1,480 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="generator" content="Docutils: http://docutils.sourceforge.net/" />
<title>Pasarela de pago Redsys con preautorización</title>
<style type="text/css">
/*
:Author: David Goodger (goodger@python.org)
:Id: $Id: html4css1.css 7952 2016-07-26 18:15:59Z milde $
:Copyright: This stylesheet has been placed in the public domain.
Default cascading style sheet for the HTML output of Docutils.
See http://docutils.sf.net/docs/howto/html-stylesheets.html for how to
customize this style sheet.
*/
/* used to remove borders from tables and images */
.borderless, table.borderless td, table.borderless th {
border: 0 }
table.borderless td, table.borderless th {
/* Override padding for "table.docutils td" with "! important".
The right padding separates the table cells. */
padding: 0 0.5em 0 0 ! important }
.first {
/* Override more specific margin styles with "! important". */
margin-top: 0 ! important }
.last, .with-subtitle {
margin-bottom: 0 ! important }
.hidden {
display: none }
.subscript {
vertical-align: sub;
font-size: smaller }
.superscript {
vertical-align: super;
font-size: smaller }
a.toc-backref {
text-decoration: none ;
color: black }
blockquote.epigraph {
margin: 2em 5em ; }
dl.docutils dd {
margin-bottom: 0.5em }
object[type="image/svg+xml"], object[type="application/x-shockwave-flash"] {
overflow: hidden;
}
/* Uncomment (and remove this text!) to get bold-faced definition list terms
dl.docutils dt {
font-weight: bold }
*/
div.abstract {
margin: 2em 5em }
div.abstract p.topic-title {
font-weight: bold ;
text-align: center }
div.admonition, div.attention, div.caution, div.danger, div.error,
div.hint, div.important, div.note, div.tip, div.warning {
margin: 2em ;
border: medium outset ;
padding: 1em }
div.admonition p.admonition-title, div.hint p.admonition-title,
div.important p.admonition-title, div.note p.admonition-title,
div.tip p.admonition-title {
font-weight: bold ;
font-family: sans-serif }
div.attention p.admonition-title, div.caution p.admonition-title,
div.danger p.admonition-title, div.error p.admonition-title,
div.warning p.admonition-title, .code .error {
color: red ;
font-weight: bold ;
font-family: sans-serif }
/* Uncomment (and remove this text!) to get reduced vertical space in
compound paragraphs.
div.compound .compound-first, div.compound .compound-middle {
margin-bottom: 0.5em }
div.compound .compound-last, div.compound .compound-middle {
margin-top: 0.5em }
*/
div.dedication {
margin: 2em 5em ;
text-align: center ;
font-style: italic }
div.dedication p.topic-title {
font-weight: bold ;
font-style: normal }
div.figure {
margin-left: 2em ;
margin-right: 2em }
div.footer, div.header {
clear: both;
font-size: smaller }
div.line-block {
display: block ;
margin-top: 1em ;
margin-bottom: 1em }
div.line-block div.line-block {
margin-top: 0 ;
margin-bottom: 0 ;
margin-left: 1.5em }
div.sidebar {
margin: 0 0 0.5em 1em ;
border: medium outset ;
padding: 1em ;
background-color: #ffffee ;
width: 40% ;
float: right ;
clear: right }
div.sidebar p.rubric {
font-family: sans-serif ;
font-size: medium }
div.system-messages {
margin: 5em }
div.system-messages h1 {
color: red }
div.system-message {
border: medium outset ;
padding: 1em }
div.system-message p.system-message-title {
color: red ;
font-weight: bold }
div.topic {
margin: 2em }
h1.section-subtitle, h2.section-subtitle, h3.section-subtitle,
h4.section-subtitle, h5.section-subtitle, h6.section-subtitle {
margin-top: 0.4em }
h1.title {
text-align: center }
h2.subtitle {
text-align: center }
hr.docutils {
width: 75% }
img.align-left, .figure.align-left, object.align-left, table.align-left {
clear: left ;
float: left ;
margin-right: 1em }
img.align-right, .figure.align-right, object.align-right, table.align-right {
clear: right ;
float: right ;
margin-left: 1em }
img.align-center, .figure.align-center, object.align-center {
display: block;
margin-left: auto;
margin-right: auto;
}
table.align-center {
margin-left: auto;
margin-right: auto;
}
.align-left {
text-align: left }
.align-center {
clear: both ;
text-align: center }
.align-right {
text-align: right }
/* reset inner alignment in figures */
div.align-right {
text-align: inherit }
/* div.align-center * { */
/* text-align: left } */
.align-top {
vertical-align: top }
.align-middle {
vertical-align: middle }
.align-bottom {
vertical-align: bottom }
ol.simple, ul.simple {
margin-bottom: 1em }
ol.arabic {
list-style: decimal }
ol.loweralpha {
list-style: lower-alpha }
ol.upperalpha {
list-style: upper-alpha }
ol.lowerroman {
list-style: lower-roman }
ol.upperroman {
list-style: upper-roman }
p.attribution {
text-align: right ;
margin-left: 50% }
p.caption {
font-style: italic }
p.credits {
font-style: italic ;
font-size: smaller }
p.label {
white-space: nowrap }
p.rubric {
font-weight: bold ;
font-size: larger ;
color: maroon ;
text-align: center }
p.sidebar-title {
font-family: sans-serif ;
font-weight: bold ;
font-size: larger }
p.sidebar-subtitle {
font-family: sans-serif ;
font-weight: bold }
p.topic-title {
font-weight: bold }
pre.address {
margin-bottom: 0 ;
margin-top: 0 ;
font: inherit }
pre.literal-block, pre.doctest-block, pre.math, pre.code {
margin-left: 2em ;
margin-right: 2em }
pre.code .ln { color: grey; } /* line numbers */
pre.code, code { background-color: #eeeeee }
pre.code .comment, code .comment { color: #5C6576 }
pre.code .keyword, code .keyword { color: #3B0D06; font-weight: bold }
pre.code .literal.string, code .literal.string { color: #0C5404 }
pre.code .name.builtin, code .name.builtin { color: #352B84 }
pre.code .deleted, code .deleted { background-color: #DEB0A1}
pre.code .inserted, code .inserted { background-color: #A3D289}
span.classifier {
font-family: sans-serif ;
font-style: oblique }
span.classifier-delimiter {
font-family: sans-serif ;
font-weight: bold }
span.interpreted {
font-family: sans-serif }
span.option {
white-space: nowrap }
span.pre {
white-space: pre }
span.problematic {
color: red }
span.section-subtitle {
/* font-size relative to parent (h1..h6 element) */
font-size: 80% }
table.citation {
border-left: solid 1px gray;
margin-left: 1px }
table.docinfo {
margin: 2em 4em }
table.docutils {
margin-top: 0.5em ;
margin-bottom: 0.5em }
table.footnote {
border-left: solid 1px black;
margin-left: 1px }
table.docutils td, table.docutils th,
table.docinfo td, table.docinfo th {
padding-left: 0.5em ;
padding-right: 0.5em ;
vertical-align: top }
table.docutils th.field-name, table.docinfo th.docinfo-name {
font-weight: bold ;
text-align: left ;
white-space: nowrap ;
padding-left: 0 }
/* "booktabs" style (no vertical lines) */
table.docutils.booktabs {
border: 0px;
border-top: 2px solid;
border-bottom: 2px solid;
border-collapse: collapse;
}
table.docutils.booktabs * {
border: 0px;
}
table.docutils.booktabs th {
border-bottom: thin solid;
text-align: left;
}
h1 tt.docutils, h2 tt.docutils, h3 tt.docutils,
h4 tt.docutils, h5 tt.docutils, h6 tt.docutils {
font-size: 100% }
ul.auto-toc {
list-style-type: none }
</style>
</head>
<body>
<div class="document" id="pasarela-de-pago-redsys-con-preautorizacion">
<h1 class="title">Pasarela de pago Redsys con preautorización</h1>
<!-- !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! source digest: sha256:1eb9535d052a619aa545a383869076ca1dc1fade22746cb3fe13afa726c3e3a3
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -->
<p><a class="reference external" href="https://odoo-community.org/page/development-status"><img alt="Beta" src="https://img.shields.io/badge/maturity-Beta-yellow.png" /></a> <a class="reference external" href="http://www.gnu.org/licenses/agpl-3.0-standalone.html"><img alt="License: AGPL-3" src="https://img.shields.io/badge/licence-AGPL--3-blue.png" /></a> <a class="reference external" href="https://github.com/Criptomart/foodcoopbcn/tree/12.0/payment_redsys_preauth"><img alt="Criptomart/foodcoopbcn" src="https://img.shields.io/badge/github-Criptomart%2Ffoodcoopbcn-lightgray.png?logo=github" /></a></p>
<p>Este módulo añade la opción de pago a través de la pasarela de Redsys con preautorización con tarjeta bancaria.</p>
<p><strong>Table of contents</strong></p>
<div class="contents local topic" id="contents">
<ul class="simple">
<li><a class="reference internal" href="#configuration" id="id1">Configuration</a><ul>
<li><a class="reference internal" href="#parametros" id="id2">Parámetros</a></li>
<li><a class="reference internal" href="#nota" id="id3">Nota</a></li>
</ul>
</li>
<li><a class="reference internal" href="#known-issues-roadmap" id="id4">Known issues / Roadmap</a></li>
<li><a class="reference internal" href="#bug-tracker" id="id5">Bug Tracker</a></li>
<li><a class="reference internal" href="#credits" id="id6">Credits</a><ul>
<li><a class="reference internal" href="#authors" id="id7">Authors</a></li>
<li><a class="reference internal" href="#contributors" id="id8">Contributors</a></li>
<li><a class="reference internal" href="#maintainers" id="id9">Maintainers</a></li>
</ul>
</li>
</ul>
</div>
<div class="section" id="configuration">
<h1><a class="toc-backref" href="#id1">Configuration</a></h1>
<div class="section" id="parametros">
<h2><a class="toc-backref" href="#id2">Parámetros</a></h2>
<ul class="simple">
<li><strong>Nombre del comercio</strong>: Indicaremos el nombre del comercio.</li>
<li><strong>Número de comercio (FUC)</strong>: Indicaremos el número de comercio que
nuestra entidad nos ha comunicado.</li>
<li><strong>Clave secreta de encriptación</strong>: Indicaremos la clave de encriptación
que tiene el comercio.</li>
<li><strong>Número de terminal</strong>: Indicaremos el terminal del TPV.</li>
<li><strong>Tipo de firma</strong>: Seleccionaremos el tipo de firma del comercio.</li>
<li><strong>Tipo de moneda</strong>: Seleccionaremos la moneda de nuestro terminal TPV
(Normalmente EUR - Euros).</li>
<li><strong>Tipo de transacción</strong>: Indicaremos el tipo de transacción, 1.</li>
<li><strong>Idioma TPV</strong>: Indicaremos el idioma en el TPV.</li>
<li><strong>Método de pago</strong>: Indicaremos que tipo de pago se debe aceptar, pago con
tarjeta, Bizum u otro de los disponibles.</li>
<li><strong>URL_OK/URL_KO</strong>: Durante el proceso del pago, y una vez que
se muestra al cliente la pantalla con el resultado del mismo, es
posible redirigir su navegador a una URL para las transacciones
autorizadas y a otra si la transacción ha sido denegada. A éstas
se las denomina URL_OK y URL_KO, respectivamente. Se trata
de dos URLs que pueden ser proporcionadas por el comercio.</li>
<li><strong>Porcentaje de pago</strong>: Indicar el porcentaje de pago que se permite, si
se deja a 0.0 se entiende 100%.</li>
</ul>
</div>
<div class="section" id="nota">
<h2><a class="toc-backref" href="#id3">Nota</a></h2>
<p>Se tiene que verificar la configuración del comercio en el
módulo de administración de Redsys, donde la opción “Parámetros en las
URLs” debe tener el valor “SI”.</p>
<p>En caso de que exista más de una base de datos en la instalación, cuando la
pasarela de pago envía el formulario a “/payment/redsys/return” odoo no sabe
con que base de datos procesar esta información, por lo que hay que establecer
los parametros <strong>dbfilter</strong> y <strong>dbname</strong> en el archivo de configuración.</p>
<p>Para mostrar simultáneamente en el comercio electrónico varios de los métodos
de pago que proporciona Redsys, como pago con tarjeta y Bizum por ejemplo,
debemos duplicar el medio de pago y escoger en el campo método de pago el que
corresponda en cada caso.</p>
<p>En los pagos con preautorización, el titular del TPV deberá solicitar al banco su activación.</p>
</div>
</div>
<div class="section" id="known-issues-roadmap">
<h1><a class="toc-backref" href="#id4">Known issues / Roadmap</a></h1>
<p>De acuerdo a los requisitos de Redsys, el tamaño máximo del número de pedido
resultante (<tt class="docutils literal">Ds_Order</tt>) es de 12 caracteres. Este addon trunca dicho
dato en el comienzo de la transacción, con el resultado de que, aunque Redsys
la aceptará, no se finalizará el pedido pedido en Odoo al retornar y entregará
un Error 500 a Redsys.
Para evitar esto, es recomendable seleccionar secuencias de pedido que se
ajusten a esta limitación, en particular de 10 o menos caracteres, al ser la
referencia un número extendido a partir del pedido, que incluye un guion y un
número secuencial para posibles repeticiones de pago.</p>
</div>
<div class="section" id="bug-tracker">
<h1><a class="toc-backref" href="#id5">Bug Tracker</a></h1>
<p>Bugs are tracked on <a class="reference external" href="https://github.com/Criptomart/foodcoopbcn/issues">GitHub Issues</a>.
In case of trouble, please check there if your issue has already been reported.
If you spotted it first, help us to smash it by providing a detailed and welcomed
<a class="reference external" href="https://github.com/Criptomart/foodcoopbcn/issues/new?body=module:%20payment_redsys_preauth%0Aversion:%2012.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**">feedback</a>.</p>
<p>Do not contact contributors directly about support or help with technical issues.</p>
</div>
<div class="section" id="credits">
<h1><a class="toc-backref" href="#id6">Credits</a></h1>
<div class="section" id="authors">
<h2><a class="toc-backref" href="#id7">Authors</a></h2>
<ul class="simple">
<li>Criptomart</li>
</ul>
</div>
<div class="section" id="contributors">
<h2><a class="toc-backref" href="#id8">Contributors</a></h2>
<ul class="simple">
<li><a class="reference external" href="https://www.criptomart.net">Criptomart</a>:<ul>
<li>Santi Noreña</li>
</ul>
</li>
</ul>
</div>
<div class="section" id="maintainers">
<h2><a class="toc-backref" href="#id9">Maintainers</a></h2>
<p>This module is part of the <a class="reference external" href="https://github.com/Criptomart/foodcoopbcn/tree/12.0/payment_redsys_preauth">Criptomart/foodcoopbcn</a> project on GitHub.</p>
<p>You are welcome to contribute.</p>
</div>
</div>
</div>
</body>
</html>

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB