Inicio
DocumentaciĂłn
Recursos
Partners
Comunidad

Recursos

Revisa las actualizaciones de nuestras soluciones y operatividad del sistema o pide soporte técnico.

Partners

Conoce nuestro programa para agencias o desarrolladores que ofrecen servicios de integraciĂłn y vendedores que quieren contratarlos.

Comunidad

Recibe las Ășltimas novedades, pide ayuda a otros integradores y comparte tus conocimientos.

Configurar notificaciones de pago - Etapas de integraciĂłn - Mercado Pago Developers

Configurar notificaciones de pago

Las notificaciones Webhooks, también conocidas como devoluciones de llamada web, son un método efectivo que permiten a los servidores de Mercado Pago enviar información en tiempo real cuando ocurre un evento específico relacionado con tu integración.

En lugar de que tu sistema realice consultas constantes para verificar actualizaciones, los Webhooks permiten la transmisión de datos de manera pasiva y automåtica entre Mercado Pago y tu integración a través de una solicitud HTTP POST, optimizando la comunicación y reduciendo la carga en los servidores.

Consulta el flujo general de una notificaciĂłn en el diagrama a continuaciĂłn.

Diagram

A continuaciĂłn, presentamos un paso a paso para configurar las notificaciones de creaciĂłn y actualizaciĂłn de pagos. Una vez configuradas, las notificaciones Webhook se enviarĂĄn cada vez que se cree un pago o se modifique su estado (Pendiente, Rechazado o Aprobado). En el proceso de integraciĂłn con Mercado Pago, puedes configurar las notificaciones de dos maneras:

Tipo de ConfiguraciĂłnDescripciĂłnVentajasCuĂĄndo Usar
Configuración a través de Tus IntegracionesEste método permite configurar notificaciones directamente en tu Panel de Desarrollador. Puedes configurar notificaciones para cada una de tus aplicaciones, identificar cuentas distintas si es necesario, y validar el origen de la notificación mediante una firma secreta.- Identificación sencilla de cuentas distintas, asegurando una adecuada gestión en entornos diversos.
- Alta seguridad al validar el origen de las notificaciones mediante una firma secreta, que garantiza la integridad de la informaciĂłn recibida.
- MĂĄs versĂĄtil y eficaz para mantener un control centralizado y gestionar la comunicaciĂłn con las aplicaciones de manera eficiente.
Recomendado para la mayorĂ­a de las integraciones.
ConfiguraciĂłn durante la creaciĂłn de pagos o preferenciasLas notificaciones se configuran para cada transacciĂłn individualmente durante la creaciĂłn del pago o preferencia.- Ajustes especĂ­ficos para cada transacciĂłn.
- Flexibilidad en casos de necesidad de parĂĄmetros dinĂĄmicos obligatorios.
- Ideal para integraciones como plataformas de pago para mĂșltiples vendedores.
Conveniente en los casos en que sea necesario enviar un query parameter dinĂĄmico de forma obligatoria, ademĂĄs de ser adecuado para integraciones que funcionan como una plataforma de pago para mĂșltiples vendedores.
Importante
Las URLs configuradas durante la creación de un pago tendrån prioridad por sobre aquellas configuradas a través de Tus integraciones.

Configuración a través de Tus integraciones

Puedes configurar notificaciones para cada una de tus aplicaciones directamente desde Tus integraciones de manera eficiente y segura. En este apartado, explicaremos cĂłmo:

  1. Indicar las URLs de notificaciĂłn y configurar eventos
  2. Validar el origen de una notificaciĂłn
  3. Simular el recibimiento de una notificaciĂłn

1. Indicar URLs de notificaciĂłn y configurar el evento

Para configurar notificaciones Webhooks, es necesario indicar las URLs a las que las mismas serĂĄn enviadas. Para hacerlo, sigue el paso a paso a continuaciĂłn:

  1. Ingresa a Tus integraciones y selecciona la aplicaciĂłn integrada con Checkout Pro para la que deseas activar las notificaciones.

Application

  1. En el menĂș de la izquierda, selecciona Webhooks > Configurar notificaciones.

Webhooks

  1. Selecciona la pestaña Modo productivo y proporciona una URL HTTPS para recibir notificaciones con tu integración productiva.

URL

  1. Selecciona lo evento Pagos para recibir notificaciones, que serån enviadas en formato JSON a través de un HTTPS POST a la URL especificada anteriormente.

Payment

  1. Por Ășltimo, haz clic en Guardar configuraciĂłn. Esto generarĂĄ una clave secreta exclusiva para la aplicaciĂłn, que permitirĂĄ validar la autenticidad de las notificaciones recibidas, garantizando que hayan sido enviadas por Mercado Pago. Ten en cuenta que esta clave generada no tiene plazo de caducidad y su renovaciĂłn periĂłdica no es obligatoria, aunque sĂ­ recomendada. Para hacerlo, basta con cliquear en el botĂłn Restablecer.

2. Simular la recepciĂłn de la notificaciĂłn

Para garantizar que las notificaciones sean configuradas correctamente, es necesario simular su recepciĂłn. Para hacerlo, sigue el paso a paso a continuaciĂłn.

  1. Después de configurar las URLs y los Eventos, haz clic en Guardar configuración.
  2. Luego, haz clic en Simular para probar si la URL indicada estĂĄ recibiendo las notificaciones correctamente.
  3. En la pantalla de simulaciĂłn, selecciona la URL que se va a probar, que puede ser la URL de prueba o la de producciĂłn.
  4. A continuaciĂłn, elige el tipo de evento e ingresa la identificaciĂłn que se enviarĂĄ en el cuerpo de la notificaciĂłn (Data ID).
  5. Por Ășltimo, haz clic en Enviar prueba para verificar la solicitud, la respuesta proporcionada por el servidor y la descripciĂłn del evento. RecibirĂĄs una respuesta similar al ejemplo a continuaciĂłn, que representa el body de la notificaciĂłn recibida en tu servidor.

plain

{
  "action": "payment.updated",
  "api_version": "v1",
  "data": {
    "id": "123456"
  },
  "date_created": "2021-11-01T02:02:02Z",
  "id": "123456",
  "live_mode": false,
  "type": "payment",
  "user_id": 724484980
}

3. Validar origen de la notificaciĂłn

La validaciĂłn del origen de una notificaciĂłn es fundamental para asegurar la seguridad y la autenticidad de la informaciĂłn recibida. Este proceso ayuda a prevenir fraudes y garantiza que solo las notificaciones legĂ­timas sean procesadas.

Mercado Pago enviarĂĄ a su servidor una notificaciĂłn similar al ejemplo a continuaciĂłn para una alerta del tĂłpico payment. En este ejemplo, se incluye la notificaciĂłn completa, que contiene los query params, el body y el header de la notificaciĂłn.

  • Query params: Son parĂĄmetros de consulta que acompañan la URL. En el ejemplo, tenemos data.id=123456 y type=payment.
  • Body: El cuerpo de la notificaciĂłn contiene informaciĂłn detallada sobre el evento, como action, api_version, data, date_created, id, live_mode, type y user_id.
  • Header: El encabezado contiene metadatos importantes, incluyendo la firma secreta de la notificaciĂłn x-signature.

plain

POST /test?data.id=123456&type=payment HTTP/1.1
Host: prueba.requestcatcher.com
Accept: */*
Accept-Encoding: *
Connection: keep-alive
Content-Length: 177
Content-Type: application/json
Newrelic: eyJ2IjpbMCwxXSwiZCI6eyJ0eSI6IkFwcCIsImFjIjoiOTg5NTg2IiwiYXAiOiI5NjA2MzYwOTQiLCJ0eCI6IjU3ZjI4YzNjOWE2ODNlZDYiLCJ0ciI6IjY0NjA0OTM3OWI1ZjA3MzMyZDdhZmQxMjEyM2I5YWE4IiwicHIiOjAuNzk3ODc0LCJzYSI6ZmFsc2UsInRpIjoxNzQyNTA1NjM4Njg0LCJ0ayI6IjE3MDk3MDcifX0=
Traceparent: 00-646049379b5f07332d7afd12123b9aa8-e7f77a41f687aecd-00
Tracestate: 1709707@nr=0-0-989586-960636094-e7f77a41f687aecd-57f28c3c9a683ed6-0-0.797874-1742505638684
User-Agent: restclient-node/4.15.3
X-Request-Id: bb56a2f1-6aae-46ac-982e-9dcd3581d08e
X-Rest-Pool-Name: /services/webhooks.js
X-Retry: 0
X-Signature: ts=1742505638683,v1=ced36ab6d33566bb1e16c125819b8d840d6b8ef136b0b9127c76064466f5229b
X-Socket-Timeout: 22000
{"action":"payment.updated","api_version":"v1","data":{"id":"123456"},"date_created":"2021-11-01T02:02:02Z","id":"123456","live_mode":false,"type":"payment","user_id":724484980}

A partir de la notificaciĂłn Webhook recibida, podrĂĄs validar la autenticidad de su origen. Mercado Pago siempre incluirĂĄ la clave secreta en las notificaciones Webhooks que serĂĄn recibidas, lo que permitirĂĄ validar su autenticidad. Esta clave serĂĄ enviada en el header x-signature, que serĂĄ similar al ejemplo debajo.

plain

`ts=1742505638683,v1=ced36ab6d33566bb1e16c125819b8d840d6b8ef136b0b9127c76064466f5229b`

Para confirmar la validaciĂłn, es necesario extraer la clave contenida en el header y compararla con la clave otorgada para tu aplicaciĂłn en Tus integraciones. Para eso, sigue el paso a paso a continuaciĂłn. Al final, disponibilizamos nuestros SDKs con ejemplos de cĂłdigos completos para facilitar el proceso.

  1. Para extraer el timestamp (ts) y la clave (v1) del header x-signature, divide el contenido del header por el carácter “,", lo que resultará en una lista de elementos. El valor para el prefijo ts es el timestamp (en milisegundos) de la notificación y v1 es la clave encriptada. Siguiendo el ejemplo presentado anteriormente, ts=1742505638683 y v1=ced36ab6d33566bb1e16c125819b8d840d6b8ef136b0b9127c76064466f5229b.
  2. Utilizando el template a continuaciĂłn, sustituye los parĂĄmetros con los datos recibidos en tu notificaciĂłn.

plain

id:[data.id_url];request-id:[x-request-id_header];ts:[ts_header];
  • Los parĂĄmetros con el sufijo _url provienen de query params. Ejemplo: [data.id_url] se sustituirĂĄ por el valor correspondiente al ID del evento (data.id). Este query param puede ser hallado en la notificaciĂłn recibida. En el ejemplo de notificaciĂłn mencionado anteriormente, el data.id_url es 123456.
  • [x-request-id_header] deberĂĄ ser sustituido por el valor recibido en el header x-request-id. En el ejemplo de notificaciĂłn mencionado anteriormente, el x-request-id es bb56a2f1-6aae-46ac-982e-9dcd3581d08e.
  • [ts_header] serĂĄ el valor ts extraĂ­do del header x-signature. En el ejemplo de notificaciĂłn mencionado anteriormente, el ts es 1742505638683.
  • Al aplicar los datos al template, quedarĂ­a de la siguiente manera: id:123456;request-id:bb56a2f1-6aae-46ac-982e-9dcd3581d08e;ts:1742505638683;
Importante
Si alguno de los valores presentados en el modelo anterior no estĂĄ presente en la notificaciĂłn recibida, debes removerlo.
  1. En Tus integraciones, selecciona la aplicaciĂłn integrada, haz clic en Webhooks > Configurar notificaciĂłn y revela la clave secreta generada.

Signature

  1. Genera la contraclave para la validaciĂłn. Para hacer esto, calcula un HMAC con la funciĂłn de hash SHA256 en base hexadecimal, utilizando la clave secreta como clave y el template con los valores como mensaje.
          
$cyphedSignature = hash_hmac('sha256', $data, $key);

        
          
const crypto = require('crypto');
const cyphedSignature = crypto
    .createHmac('sha256', secret)
    .update(signatureTemplateParsed)
    .digest('hex'); 

        
          
String cyphedSignature = new HmacUtils("HmacSHA256", secret).hmacHex(signedTemplate);

        
          
import hashlib, hmac, binascii

cyphedSignature = binascii.hexlify(hmac_sha256(secret.encode(), signedTemplate.encode()))

        
  1. Finalmente, compara la clave generada con la clave extraĂ­da del header, asegurĂĄndote de que tengan una correspondencia exacta. AdemĂĄs, puedes usar el timestamp extraĂ­do del header para compararlo con un timestamp generado en el momento de la recepciĂłn de la notificaciĂłn, con el fin de establecer una tolerancia de demora en la recepciĂłn del mensaje.

A continuaciĂłn, puedes ver ejemplos de cĂłdigo completo:

          
<?php
// Obtain the x-signature value from the header
$xSignature = $_SERVER['HTTP_X_SIGNATURE'];
$xRequestId = $_SERVER['HTTP_X_REQUEST_ID'];

// Obtain Query params related to the request URL
$queryParams = $_GET;

// Extract the "data.id" from the query params
$dataID = isset($queryParams['data.id']) ? $queryParams['data.id'] : '';

// Separating the x-signature into parts
$parts = explode(',', $xSignature);

// Initializing variables to store ts and hash
$ts = null;
$hash = null;

// Iterate over the values to obtain ts and v1
foreach ($parts as $part) {
    // Split each part into key and value
    $keyValue = explode('=', $part, 2);
    if (count($keyValue) == 2) {
        $key = trim($keyValue[0]);
        $value = trim($keyValue[1]);
        if ($key === "ts") {
            $ts = $value;
        } elseif ($key === "v1") {
            $hash = $value;
        }
    }
}

// Obtain the secret key for the user/application from Mercadopago developers site
$secret = "your_secret_key_here";

// Generate the manifest string
$manifest = "id:$dataID;request-id:$xRequestId;ts:$ts;";

// Create an HMAC signature defining the hash type and the key as a byte array
$sha = hash_hmac('sha256', $manifest, $secret);
if ($sha === $hash) {
    // HMAC verification passed
    echo "HMAC verification passed";
} else {
    // HMAC verification failed
    echo "HMAC verification failed";
}
?>

        
          
// Obtain the x-signature value from the header
const xSignature = headers['x-signature']; // Assuming headers is an object containing request headers
const xRequestId = headers['x-request-id']; // Assuming headers is an object containing request headers

// Obtain Query params related to the request URL
const urlParams = new URLSearchParams(window.location.search);
const dataID = urlParams.get('data.id');

// Separating the x-signature into parts
const parts = xSignature.split(',');

// Initializing variables to store ts and hash
let ts;
let hash;

// Iterate over the values to obtain ts and v1
parts.forEach(part => {
    // Split each part into key and value
    const [key, value] = part.split('=');
    if (key && value) {
        const trimmedKey = key.trim();
        const trimmedValue = value.trim();
        if (trimmedKey === 'ts') {
            ts = trimmedValue;
        } else if (trimmedKey === 'v1') {
            hash = trimmedValue;
        }
    }
});

// Obtain the secret key for the user/application from Mercadopago developers site
const secret = 'your_secret_key_here';

// Generate the manifest string
const manifest = `id:${dataID};request-id:${xRequestId};ts:${ts};`;

// Create an HMAC signature
const hmac = crypto.createHmac('sha256', secret);
hmac.update(manifest);

// Obtain the hash result as a hexadecimal string
const sha = hmac.digest('hex');

if (sha === hash) {
    // HMAC verification passed
    console.log("HMAC verification passed");
} else {
    // HMAC verification failed
    console.log("HMAC verification failed");
}

        
          
import hashlib
import hmac
import urllib.parse

# Obtain the x-signature value from the header
xSignature = request.headers.get("x-signature")
xRequestId = request.headers.get("x-request-id")

# Obtain Query params related to the request URL
queryParams = urllib.parse.parse_qs(request.url.query)

# Extract the "data.id" from the query params
dataID = queryParams.get("data.id", [""])[0]

# Separating the x-signature into parts
parts = xSignature.split(",")

# Initializing variables to store ts and hash
ts = None
hash = None

# Iterate over the values to obtain ts and v1
for part in parts:
    # Split each part into key and value
    keyValue = part.split("=", 1)
    if len(keyValue) == 2:
        key = keyValue[0].strip()
        value = keyValue[1].strip()
        if key == "ts":
            ts = value
        elif key == "v1":
            hash = value

# Obtain the secret key for the user/application from Mercadopago developers site
secret = "your_secret_key_here"

# Generate the manifest string
manifest = f"id:{dataID};request-id:{xRequestId};ts:{ts};"

# Create an HMAC signature defining the hash type and the key as a byte array
hmac_obj = hmac.new(secret.encode(), msg=manifest.encode(), digestmod=hashlib.sha256)

# Obtain the hash result as a hexadecimal string
sha = hmac_obj.hexdigest()
if sha == hash:
    # HMAC verification passed
    print("HMAC verification passed")
else:
    # HMAC verification failed
    print("HMAC verification failed")

        
          
import (
	"crypto/hmac"
	"crypto/sha256"
	"encoding/hex"
	"fmt"
	"net/http"
	"strings"
)

func main() {
	http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		// Obtain the x-signature value from the header
		xSignature := r.Header.Get("x-signature")
		xRequestId := r.Header.Get("x-request-id")

		// Obtain Query params related to the request URL
		queryParams := r.URL.Query()

		// Extract the "data.id" from the query params
		dataID := queryParams.Get("data.id")

		// Separating the x-signature into parts
		parts := strings.Split(xSignature, ",")

		// Initializing variables to store ts and hash
		var ts, hash string

		// Iterate over the values to obtain ts and v1
		for _, part := range parts {
			// Split each part into key and value
			keyValue := strings.SplitN(part, "=", 2)
			if len(keyValue) == 2 {
				key := strings.TrimSpace(keyValue[0])
				value := strings.TrimSpace(keyValue[1])
				if key == "ts" {
					ts = value
				} else if key == "v1" {
					hash = value
				}
			}
		}

		// Get secret key/token for specific user/application from Mercadopago developers site
		secret := "your_secret_key_here"

		// Generate the manifest string
		manifest := fmt.Sprintf("id:%v;request-id:%v;ts:%v;", dataID, xRequestId, ts)

		// Create an HMAC signature defining the hash type and the key as a byte array
		hmac := hmac.New(sha256.New, []byte(secret))
		hmac.Write([]byte(manifest))

		// Obtain the hash result as a hexadecimal string
		sha := hex.EncodeToString(hmac.Sum(nil))

if sha == hash {
    // HMAC verification passed
    fmt.Println("HMAC verification passed")
} else {
    // HMAC verification failed
    fmt.Println("HMAC verification failed")
}

	})
}

        

Una vez que las notificaciones sean configuradas, consulta las acciones necesarias después de recibir una notificación para informar que las mismas fueron debidamente recibidas:

Acciones necesarias después de recibir la notificación

Cuando recibes una notificaciĂłn en tu plataforma, Mercado Pago espera una respuesta para validar que esa recepciĂłn fue correcta. Para eso, debes devolver un HTTP STATUS 200 (OK) o 201 (CREATED).

El tiempo de espera para esa confirmación serå de 22 segundos. Si no se envía esta respuesta, el sistema entenderå que la notificación no fue recibida y realizarå un nuevo intento de envío cada 15 minutos, hasta que reciba la respuesta. Después del tercer intento, el plazo serå prorrogado, pero los envíos continuarån sucediendo.

Luego de responder la notificaciĂłn, confirmando su recibimiento, puedes obtener toda la informaciĂłn sobre el evento del tĂłpico payments notificado haciendo un GET al endpoint v1/payments/{id}.

Con esta informaciĂłn podrĂĄs realizar las actualizaciones necesarias a tu plataforma, como por ejemplo, actualizar un pago aprobado.

Ademås, para consultar el estado del evento posterior a la notificación, puedes utilizar los diferentes métodos de nuestros SDKs para realizar la consulta con el ID que fue enviado en la notificación.

          
MercadoPago.SDK.setAccessToken("ENV_ACCESS_TOKEN");
switch (type) {
    case "payment":
        Payment payment = Payment.findById(data.id);
        break;
    case "plan":
        Plan plan = Plan.findById(data.id);
        break;
    case "subscription":
        Subscription subscription = Subscription.findById(data.id);
        break;
    case "invoice":
        Invoice invoice = Invoice.findById(data.id);
        break;
    case "point_integration_wh":
        // POST contiene la informaciĂČn relacionada a la notificaciĂČn.
        break;
}

        
          
mercadopago.configurations.setAccessToken('ENV_ACCESS_TOKEN');
switch (type) {
  case 'payment':
    const payment = await mercadopago.payment.findById(data.id);
    break;
  case 'plan':
    const plan = await mercadopago.plans.get(data.id);
    break;
  case 'subscription':
    const subscription = await mercadopago.subscriptions.get(data.id);
    break;
  case 'invoice':
    const invoice = await mercadopago.invoices.get(data.id);
    break;
  case 'point_integration_wh':
    // Contiene la informaciĂČn relacionada a la notificaciĂČn.
    break;
}

        
          
MercadoPago::SDK.configure(access_token: 'ENV_ACCESS_TOKEN')
case payload['type']
when 'payment'
  payment = MercadoPago::Payment.search(id: payload['data']['id'])
when 'plan'
  plan = MercadoPago::Plan.search(id: payload['data']['id'])
when 'subscription'
  subscription = MercadoPago::Subscription.search(id: payload['data']['id'])
when 'invoice'
  invoice = MercadoPago::Invoice.search(id: payload['data']['id'])
when 'point_integration_wh'
  # Contiene la informaciĂČn relacionada a la notificaciĂČn.
end

        
          
MercadoPagoConfig.AccessToken = "ENV_ACCESS_TOKEN";
switch (type)
{
    case "payment":
        Payment payment = await Payment.FindByIdAsync(payload["data"]["id"].ToString());
        break;
    case "plan":
        Plan plan = await Plan.FindByIdAsync(payload["data"]["id"].ToString());
        break;
    case "subscription":
        Subscription subscription = await Subscription.FindByIdAsync(payload["data"]["id"].ToString());
        break;
    case "invoice":
        Invoice invoice = await Invoice.FindByIdAsync(payload["data"]["id"].ToString());
        break;
    case "point_integration_wh":
        // Contiene la informaciĂČn relacionada a la notificaciĂČn.
        break;
}

        
          
sdk = mercadopago.SDK("ENV_ACCESS_TOKEN")
notification_type = data["type"]
if notification_type == "payment":
    payment = sdk.payment().get(payload["data"]["id"])
elif notification_type == "plan":
    plan = sdk.preapproval().get(payload["data"]["id"]) 
elif notification_type == "subscription":
    subscription = sdk.preapproval().get(payload["data"]["id"])
elif notification_type == "invoice":
    invoice = sdk.invoice().get(payload["data"]["id"])
elif notification_type == "point_integration_wh":
    # Contiene la informaciĂČn relacionada a la notificaciĂČn.
else:
    return

        
          
accessToken := "{{ACCESS_TOKEN}}"
cfg, err := config.New(accessToken)
if err != nil {
	fmt.Println(err)
	return
}
client := customer.NewClient(cfg)
switch req.Type {
case "payment":
	client := payment.NewClient(cfg)
	resource, err = client.Get(context.Background(), resource.ID)
	if err != nil {
		fmt.Println(err)
		return
	}
case "plan":
    client := preapprovalplan.NewClient(cfg)
    resource, err := client.Get(context.Background(), preApprovalPlanID)
	if err != nil {
		fmt.Println(err)
		return
	}
case "invoice":
	client := invoice.NewClient(cfg)
	resource, err := client.Get(context.Background(), req.Data.ID)
	if err != nil {
		fmt.Println(err)
		return
	}
case "point_integration_wh":
	// Contiene la informaciĂČn relacionada a la notificaciĂČn.
}