135 lines
5.7 KiB
Python
135 lines
5.7 KiB
Python
# © 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
|
|
|