# Part of Odoo. See LICENSE file for full copyright and licensing details. import logging import pprint from odoo import http from odoo.exceptions import ValidationError from odoo.http import request _logger = logging.getLogger(__name__) class MercadoPagoController(http.Controller): _return_url = '/payment/mercado_pago/return' _webhook_url = '/payment/mercado_pago/webhook' @http.route(_return_url, type='http', methods=['GET'], auth='public') def mercado_pago_return_from_checkout(self, **data): """ Process the notification data sent by Mercado Pago after redirection from checkout. :param dict data: The notification data. """ # Handle the notification data. _logger.info("Handling redirection from Mercado Pago with data:\n%s", pprint.pformat(data)) if data.get('payment_id') != 'null': request.env['payment.transaction'].sudo()._handle_notification_data( 'mercado_pago', data ) else: # The customer cancelled the payment by clicking on the return button. pass # Don't try to process this case because the payment id was not provided. # Redirect the user to the status page. return request.redirect('/payment/status') @http.route( f'{_webhook_url}/', type='http', auth='public', methods=['POST'], csrf=False ) def mercado_pago_webhook(self, reference, **_kwargs): """ Process the notification data sent by Mercado Pago to the webhook. :param str reference: The transaction reference embedded in the webhook URL. :param dict _kwargs: The extra query parameters. :return: An empty string to acknowledge the notification. :rtype: str """ data = request.get_json_data() _logger.info("Notification received from Mercado Pago with data:\n%s", pprint.pformat(data)) # Mercado Pago sends two types of asynchronous notifications: webhook notifications and # IPNs which are very similar to webhook notifications but are sent later and contain less # information. Therefore, we filter the notifications we receive based on the 'action' # (type of event) key as it is not populated for IPNs, and we don't want to process the # other types of events. if data.get('action') in ('payment.created', 'payment.updated'): # Handle the notification data. try: payment_id = data.get('data', {}).get('id') request.env['payment.transaction'].sudo()._handle_notification_data( 'mercado_pago', {'external_reference': reference, 'payment_id': payment_id} ) # Use 'external_reference' as the reference key like in the redirect data. except ValidationError: # Acknowledge the notification to avoid getting spammed. _logger.exception("Unable to handle the notification data; skipping to acknowledge") return '' # Acknowledge the notification.