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