From 3e41ca178e109d1a8ffb1949e71b12fdceb506d4 Mon Sep 17 00:00:00 2001 From: Martin Quinteros Date: Mon, 4 Dec 2023 13:26:06 +0000 Subject: [PATCH] [IMP] payment_mercado_pago: add two states in mapping constant Although the lack of these statuses does not block the flow of a transaction, they create confusing records for the user. - Authorized: it is returned by Mercadopago when it authorizes payments by bundle. It should behave as a pending payment as it's not yet captured and could still be canceled by timeout. - Cancelled: It is returned by Mercadopago when a payment is not made within the expected timeframe. This prevents odoo from leaving payment transactions in draft that cannot be cancelled by the customer. closes odoo/odoo#152064 X-original-commit: 44790e7f115610548b140c0d53f97bb11f973224 Signed-off-by: Antoine Vandevenne (anv) Signed-off-by: Morgane Demesmaeker --- addons/payment_mercado_pago/const.py | 52 ++++++- .../i18n/payment_mercado_pago.pot | 127 ++++++++++++++++++ .../models/payment_transaction.py | 22 ++- 3 files changed, 199 insertions(+), 2 deletions(-) diff --git a/addons/payment_mercado_pago/const.py b/addons/payment_mercado_pago/const.py index b67e36befcf..0fa7765d4a4 100644 --- a/addons/payment_mercado_pago/const.py +++ b/addons/payment_mercado_pago/const.py @@ -1,5 +1,8 @@ # Part of Odoo. See LICENSE file for full copyright and licensing details. +from odoo import _ + + # Currency codes of the currencies supported by Mercado Pago in ISO 4217 format. # See https://api.mercadopago.com/currencies. Last seen online: 24 November 2022. SUPPORTED_CURRENCIES = [ @@ -59,7 +62,54 @@ PAYMENT_METHODS_MAPPING = { # Mapping of transaction states to Mercado Pago payment statuses. # See https://www.mercadopago.com.mx/developers/en/reference/payments/_payments_id/get. TRANSACTION_STATUS_MAPPING = { - 'pending': ('pending', 'in_process', 'in_mediation'), + 'pending': ('pending', 'in_process', 'in_mediation', 'authorized'), 'done': ('approved', 'refunded'), 'canceled': ('cancelled', 'null'), + 'error': ('rejected'), +} + +# Mapping of error states to Mercado Pago error messages. +# See https://www.mercadopago.com.ar/developers/en/docs/checkout-api/response-handling/collection-results +ERROR_MESSAGE_MAPPING = { + 'accredited': _( + "Your payment has been credited. In your summary you will see the charge as a statement " + "descriptor." + ), + 'pending_contingency': _( + "We are processing your payment. Don't worry, in less than 2 business days, we will notify " + "you by e-mail if your payment has been credited." + ), + 'pending_review_manual': _( + "We are processing your payment. Don't worry, less than 2 business days we will notify you " + "by e-mail if your payment has been credited or if we need more information." + ), + 'cc_rejected_bad_filled_card_number': _("Check the card number."), + 'cc_rejected_bad_filled_date': _("Check expiration date."), + 'cc_rejected_bad_filled_other': _("Check the data."), + 'cc_rejected_bad_filled_security_code': _("Check the card security code."), + 'cc_rejected_blacklist': _("We were unable to process your payment, please use another card."), + 'cc_rejected_call_for_authorize': _("You must authorize the payment with this card."), + 'cc_rejected_card_disabled': _( + "Call your card issuer to activate your card or use another payment method. The phone " + "number is on the back of your card." + ), + 'cc_rejected_card_error': _( + "We were unable to process your payment, please check your card information." + ), + 'cc_rejected_duplicated_payment': _( + "You have already made a payment for that value. If you need to pay again, use another card" + " or another payment method." + ), + 'cc_rejected_high_risk': _( + "We were unable to process your payment, please use another card." + ), + 'cc_rejected_insufficient_amount': _("Your card has not enough funds."), + 'cc_rejected_invalid_installments': _( + "This payment method does not process payments in installments." + ), + 'cc_rejected_max_attempts': _( + "You have reached the limit of allowed attempts. Choose another card or other means of " + "payment." + ), + 'cc_rejected_other_reason': _("Payment was not processed, use another card or contact issuer.") } diff --git a/addons/payment_mercado_pago/i18n/payment_mercado_pago.pot b/addons/payment_mercado_pago/i18n/payment_mercado_pago.pot index db76ca7f9f3..c7df332741a 100644 --- a/addons/payment_mercado_pago/i18n/payment_mercado_pago.pot +++ b/addons/payment_mercado_pago/i18n/payment_mercado_pago.pot @@ -20,6 +20,43 @@ msgstr "" msgid "Access Token" msgstr "" +#. module: payment_mercado_pago +#. odoo-python +#: code:addons/payment_mercado_pago/const.py:0 +#, python-format +msgid "" +"Call your card issuer to activate your card or use another payment method. " +"The phone number is on the back of your card." +msgstr "" + +#. module: payment_mercado_pago +#. odoo-python +#: code:addons/payment_mercado_pago/const.py:0 +#, python-format +msgid "Check expiration date." +msgstr "" + +#. module: payment_mercado_pago +#. odoo-python +#: code:addons/payment_mercado_pago/const.py:0 +#, python-format +msgid "Check the card number." +msgstr "" + +#. module: payment_mercado_pago +#. odoo-python +#: code:addons/payment_mercado_pago/const.py:0 +#, python-format +msgid "Check the card security code." +msgstr "" + +#. module: payment_mercado_pago +#. odoo-python +#: code:addons/payment_mercado_pago/const.py:0 +#, python-format +msgid "Check the data." +msgstr "" + #. module: payment_mercado_pago #: model:ir.model.fields,field_description:payment_mercado_pago.field_payment_provider__code msgid "Code" @@ -59,6 +96,13 @@ msgstr "" msgid "Payment Transaction" msgstr "" +#. module: payment_mercado_pago +#. odoo-python +#: code:addons/payment_mercado_pago/const.py:0 +#, python-format +msgid "Payment was not processed, use another card or contact issuer." +msgstr "" + #. module: payment_mercado_pago #. odoo-python #: code:addons/payment_mercado_pago/models/payment_transaction.py:0 @@ -107,3 +151,86 @@ msgstr "" #: model:ir.model.fields,help:payment_mercado_pago.field_payment_provider__code msgid "The technical code of this payment provider." msgstr "" + +#. module: payment_mercado_pago +#. odoo-python +#: code:addons/payment_mercado_pago/const.py:0 +#, python-format +msgid "This payment method does not process payments in installments." +msgstr "" + +#. module: payment_mercado_pago +#. odoo-python +#: code:addons/payment_mercado_pago/const.py:0 +#, python-format +msgid "" +"We are processing your payment. Don't worry, in less than 2 business days, " +"we will notify you by e-mail if your payment has been credited." +msgstr "" + +#. module: payment_mercado_pago +#. odoo-python +#: code:addons/payment_mercado_pago/const.py:0 +#, python-format +msgid "" +"We are processing your payment. Don't worry, less than 2 business days we " +"will notify you by e-mail if your payment has been credited or if we need " +"more information." +msgstr "" + +#. module: payment_mercado_pago +#. odoo-python +#: code:addons/payment_mercado_pago/const.py:0 +#, python-format +msgid "" +"We were unable to process your payment, please check your card information." +msgstr "" + +#. module: payment_mercado_pago +#. odoo-python +#: code:addons/payment_mercado_pago/const.py:0 +#: code:addons/payment_mercado_pago/const.py:0 +#, python-format +msgid "We were unable to process your payment, please use another card." +msgstr "" + +#. module: payment_mercado_pago +#. odoo-python +#: code:addons/payment_mercado_pago/const.py:0 +#, python-format +msgid "" +"You have already made a payment for that value. If you need to pay again, " +"use another card or another payment method." +msgstr "" + +#. module: payment_mercado_pago +#. odoo-python +#: code:addons/payment_mercado_pago/const.py:0 +#, python-format +msgid "" +"You have reached the limit of allowed attempts. Choose another card or other" +" means of payment." +msgstr "" + +#. module: payment_mercado_pago +#. odoo-python +#: code:addons/payment_mercado_pago/const.py:0 +#, python-format +msgid "You must authorize the payment with this card." +msgstr "" + +#. module: payment_mercado_pago +#. odoo-python +#: code:addons/payment_mercado_pago/const.py:0 +#, python-format +msgid "Your card has not enough funds." +msgstr "" + +#. module: payment_mercado_pago +#. odoo-python +#: code:addons/payment_mercado_pago/const.py:0 +#, python-format +msgid "" +"Your payment has been credited. In your summary you will see the charge as a" +" statement descriptor." +msgstr "" diff --git a/addons/payment_mercado_pago/models/payment_transaction.py b/addons/payment_mercado_pago/models/payment_transaction.py index 5d6fd9e22f7..23416ec0221 100644 --- a/addons/payment_mercado_pago/models/payment_transaction.py +++ b/addons/payment_mercado_pago/models/payment_transaction.py @@ -6,7 +6,7 @@ from urllib.parse import quote as url_quote from werkzeug import urls -from odoo import _, models +from odoo import _, api, models from odoo.exceptions import UserError, ValidationError from odoo.addons.payment_mercado_pago import const @@ -182,6 +182,14 @@ class PaymentTransaction(models.Model): self._set_done() elif payment_status in const.TRANSACTION_STATUS_MAPPING['canceled']: self._set_canceled() + elif payment_status in const.TRANSACTION_STATUS_MAPPING['error']: + status_detail = verified_payment_data.get('status_detail') + _logger.warning( + "Received data for transaction with reference %s with status %s and error code: %s", + self.reference, payment_status, status_detail + ) + error_message = self._mercado_pago_get_error_msg(status_detail) + self._set_error(error_message) else: # Classify unsupported payment status as the `error` tx state. _logger.warning( "Received data for transaction with reference %s with invalid payment status: %s", @@ -190,3 +198,15 @@ class PaymentTransaction(models.Model): self._set_error( "Mercado Pago: " + _("Received data with invalid status: %s", payment_status) ) + + @api.model + def _mercado_pago_get_error_msg(self, status_detail): + """ Return the error message corresponding to the payment status. + + :param str status_detail: The status details sent by the provider. + :return: The error message. + :rtype: str + """ + return "Mercado Pago: " + const.ERROR_MESSAGE_MAPPING.get( + status_detail, const.ERROR_MESSAGE_MAPPING['cc_rejected_other_reason'] + )