# Mercado Pago solution for Odoo 18 – Return URL Fix

Odoo 18 with Mercado Pago as the payment gateway

During a recent Odoo 18 implementation using Mercado Pago as the payment gateway, I encountered a problem that was not officially documented and had no working solution in forums or repositories: the Mercado Pago modal did not open at checkout. Instead, an error said the “Return URL” settings were missing.

This prevented users from completing payment. The most frustrating part was discovering there was no way to configure these URLs through the Odoo interface. Although the module `payment_mercado_pago` lets you enter credentials and enable the provider, it offers no field for setting the `back_urls` that Mercado Pago needs to redirect users correctly after payment.

## Why can't back_urls be configured through the interface?

The official Mercado Pago module for Odoo, known as `payment_mercado_pago`, is community-maintained and does not follow the regular update cycle of official Odoo modules. Updates have no fixed schedule and depend on voluntary contributions.

The module therefore has no provider setting for return URLs. Because the backend builds the Mercado Pago payload automatically, the interface offers no way to modify it.

## Why did I edit the code directly?

The ideal approach would be a custom module inheriting the required classes and overriding the methods to change. This keeps changes separate from the original code and protects them from future module updates.

However, this module is not updated frequently, and I had a staging environment for testing, so I edited the source file directly. This is not recommended for production without version control or prior testing.

For an example of extending functionality through a custom module without changing core files, see my article on customizing the Odoo frontend with CSS, JS and XML using module inheritance: 🔗 [How to customize the Odoo frontend](https://tuwebmaster.com.ar/en/como-personalizar-el-frontend-de-odoo/)

## Editing payment_transaction.py

The solution was to edit the method `_mercado_pago_prepare_preference_request_payload`, which builds the payload sent to Mercado Pago to create the payment preference.

The method is located at:

addons/payment_mercado_pago/models/payment_transaction.py

Inside that method, I manually added the `back_urls` block to the returned dictionary. This dictionary represents the request body sent to Mercado Pago and must contain the return URLs.

## Modified snippet:

```
return {
    'auto_return': 'approved',
    'back_urls': {
        'success': "https://tusitio.com/payment/mp/return",
        'pending': "https://tusitio.com/payment/mp/return",
        'failure': "https://tusitio.com/payment/mp/return",
    },
    'external_reference': self.reference,
    ...
}
```

This block belongs to the method that also defines parameters such as `external_reference`, the `items`, the `notification_url` and the details of the `payer`. The `back_urls` must be at this level, because Mercado Pago expects them in the preference payload.

## Implementing the return controller

Once Mercado Pago has the return URLs, those routes must exist in Odoo. Otherwise, users will be redirected to a 404 page.

The January 2026 update includes the complete controller I use to preserve the cart session and send customers to the order confirmation page.

I added save_session=True to the route. The controller reads status or, if it is absent, collection_status, and logs the reference and status through the standard Odoo logger.

The approved, success, pending and in_process statuses lead to /shop/confirmation. All other statuses return to /shop.

Showing the confirmation page for a pending or processing payment does not mean the funds have been received. A browser redirect does not validate payment: the transaction must be updated through a verified Mercado Pago notification.

**File:** `return_controller.py` **Location:** `payment_mercado_pago/controllers/`

```
# path: payment_mercado_pago/controllers/return_controller.py

import logging

from odoo import http

from odoo.http import request

_logger = logging.getLogger(__name__)

class MercadoPagoReturnController(http.Controller):

    # Agregamos save_session=True para asegurar que no se pierda el carrito/usuario

    @http.route('/payment/mp/return', type='http', auth='public', csrf=False, save_session=True)

    def mercadopago_return(self, **kwargs):

        """Captura el retorno del cliente desde Mercado Pago y redirige."""

        

        # 1. Obtenemos estado y referencia

        # MP a veces usa 'collection_status' en lugar de 'status'

        status = kwargs.get('status') or kwargs.get('collection_status')

        reference = kwargs.get('external_reference')

        # 2. Log estándar de Odoo (más rápido que escribir en ir.logging manualmente)

        _logger.info("MercadoPago Return: Ref=%s - Status=%s - Params=%s", reference, status, kwargs)

        # 3. Estados que muestran la confirmación del pedido

        

        confirmation_states = ['approved', 'success', 'pending', 'in_process']

        if status in confirmation_states:

            # Si es aprobado O pendiente (rapipago/tarjeta en revision), va a la Thank You Page

            return request.redirect('/shop/confirmation')

            

        # 4. Solo si falla realmente, volvemos al shop

        _logger.warning("MercadoPago Return no aprobado. Redirigiendo a shop. Status: %s", status)

        return request.redirect('/shop')
```

And imported it in the corresponding `__init__.py` file:

```
from . import main
from . import return_controller
```

After restarting the Odoo service (`sudo systemctl restart odoo`), the flow worked.

## Result

- The Mercado Pago modal opens correctly.

- Users can complete payment without errors.

- Approved, pending or processing payments are shown on `/shop/confirmation`; all other statuses return to `/shop`.

- This avoids the 404 error caused by a missing return-URL controller.

If it helps you, great. If you adapt it, even better. Questions, suggestions and experiences are welcome in the comments. I hope this helps other technicians working with Odoo and payment gateways.

Author label integrated into the border

Author's note

Content

    I'm **Sasha Herscovich**, and I design, develop and provide technical support for online stores built with WordPress and Odoo. I solve real problems every day and occasionally share what I encounter in case it helps someone else.
  

    This blog contains ideas, solutions and code snippets I use in real projects. Some are for people who manage their own websites; others are for developers and designers looking to improve their work, save time or understand how to solve a particular issue.
  

    I don't sell magic formulas or universal solutions. I share what works for me, what I test and what I learn along the way. If it helps you, welcome. And if you'd like to comment, improve or adapt something, I'd love you to.

Canonical page: https://tuwebmaster.com.ar/en/solucion-mercado-pago-odoo-18-return-url-fix/
