# © 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