Integración vía Mercado Pago para sitios web
Este modelo permite ofrecer Apple Pay en tu sitio web sin gestionar certificados de pago ni desencriptar tokens en tu servidor. Puedes integrar vía SDK, usando el SDK de JavaScript de Mercado Pago en el frontend para mostrar el botón Apple Pay, o vía API, implementando el flujo en tu backend. En ambos casos, Mercado Pago se encarga de la validación con Apple y devuelve un token listo para crear el pago.
sequenceDiagram
participant C as Comprador
participant V as Sitio web (frontend)
participant MP as Mercado Pago
participant A as Apple
V->>MP: Inicializar Apple Pay
MP->>A: Validar comercio y dominio
A-->>V: Botón Apple Pay disponible
C->>V: Clic en Apple Pay
V->>A: Solicitud de pago (Touch ID/Face ID)
A-->>MP: Token de Apple Pay
MP-->>V: Token de Mercado Pago (callback)
V->>V: Enviar token al backend
V->>MP: Crear pago (token + datos)
MP-->>V: Respuesta del pago
En esta integración utilizas el SDK de JavaScript de Mercado Pago en el frontend para mostrar el botón Apple Pay. Mercado Pago valida la sesión con Apple y devuelve un token listo para crear el pago en tu backend. Sigue los pasos a continuación para integrar.
Habiendo obtenido y configurado los certificados obligatorios de Apple Developer, incluye el SDK MercadoPago.js en tu página:
<script src="https://sdk.mercadopago.com/js/v2"></script>
Luego, inicializa la biblioteca con tu Public Key de pruebasClave pública de la aplicación creada en Mercado Pago, usada en el frontend. Puedes acceder a ella a través de Tus integraciones > Detalles de aplicación > Pruebas > Credenciales de prueba.:
javascript
const mp = new MercadoPago('YOUR_PUBLIC_KEY'); const quickCheckoutBuilder = mp.quickCheckout();
- Configura los datos del pago y de la sesión Apple Pay en tu frontend. A continuación, puedes ver un ejemplo de configuración y la descripción de los parámetros necesarios para hacerlo.
const renderApplePayBrick = async (quickCheckoutBuilder) => {
const settings = {
checkoutTypes: ['applePay'],
applePay: {
paymentRequest: {
countryCode: 'BR',
currencyCode: 'BRL',
merchantCapabilities: ['supports3DS'],
supportedNetworks: ['visa', 'masterCard'],
total: {
label: 'Mi producto',
amount: '10.00'
}
},
sessionRequest: {
id: 'PUBLIC_HASH_DE_MERCADO_PAGO',
merchantIdentifier: 'merchant.tu-identificador',
domainName: 'tu-dominio.com',
displayName: 'Mi tienda',
initiative: 'web',
initiativeContext: 'tu-dominio.com'
},
customization: {
locale: 'es-ES'
},
callbacks: {
onReady: async () => {
console.log('Apple Pay listo');
},
onTokenGenerated: async (token, bin, paymentMethodId) => {
// Envía token, bin y paymentMethodId a tu backend para crear el pago
const response = await fetch('/tu-endpoint/pagar', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ token, bin, paymentMethodId })
});
const result = await response.json();
// Redirigir o mostrar resultado según result
},
onCancel: async () => {
console.log('Pago cancelado');
},
onError: async (error) => {
console.error('Error Apple Pay:', error);
}
}
}
};
window.applePayBrickController = await quickCheckoutBuilder.create(
'payment-container',
settings
);
};
renderApplePayBrick(quickCheckoutBuilder);
| Parámetro | Descripción |
paymentRequest.merchantCapabilities | Capacidades del comercio para el pago. Debe incluir obligatoriamente supports3DS para habilitar la autenticación 3D Secure en las transacciones con Apple Pay. |
paymentRequest.supportedNetworks | Redes de pago admitidas en el checkout. Solo se soportan las banderas visa y/o masterCard. |
sessionRequest.id | Hash público que Mercado Pago te entrega después de configurar y enviar los certificados en el Apple Developer Portal. Identifica tu sesión de Apple Pay ante Mercado Pago. |
sessionRequest.merchantIdentifier | Identificador único de tu negocio en Apple Pay. Corresponde al Merchant ID que creaste y configuraste en el Apple Developer Portal. |
sessionRequest.domainName | Dominio de tu sitio donde se muestra el botón Apple Pay. Debe coincidir con el dominio que verificaste en el Apple Developer Portal y donde está publicado el archivo de verificación en .well-known. |
sessionRequest.displayName | Nombre comercial que se muestra al usuario durante el flujo de pago de Apple Pay, por ejemplo, en la pantalla de autorización de Touch ID o Face ID. |
sessionRequest.initiativeContext | Contexto de la iniciativa de pago en la web. Debe tener el mismo valor que domainName para que la sesión de Apple Pay se valide correctamente. |
- Una vez creadas las configuraciones, define en tu HTML el contenedor donde se renderizará el botón de Apple Pay e inserta el código a continuación.
html
<div id="payment-container" class="payment-container"></div>
El resultado de renderizar el componente debe ser similar al de la imagen a continuación.

Personalización visual del botón
Puedes personalizar el estilo del botón, el tipo de texto y el idioma dentro del objeto customization de tu configuración:
javascript
customization: { buttonStyle: 'black', // 'black' | 'white' | 'white-outline' buttonType: 'pay', // 'pay' | 'buy' | 'check-out' | 'plain' | etc. locale: 'es-ES' // El valor por defecto es el idioma y la región configurados actualmente en el navegador }
| Opción | Descripción |
buttonStyle | Estilo del botón. Los valores pueden ser: black, white u white-outline. |
buttonType | Tipo de botón mostrado. Los valores pueden ser: pay, buy, check-out, plain, entre otros. |
locale | Código de idioma. Los valores pueden ser: es-ES, pt-BR, en-US, entre otros. |
Cuando el comprador autoriza el pago con Apple Pay, el callback onTokenGenerated entrega en tu frontend el token, el bin y el paymentMethodId.
Envía estos valores en el pago a Mercado Pago a través de nuestros SDKs. Deberás utilizar tu Access Token de pruebasClave privada de la aplicación creada en Mercado Pago, utilizado en el backend. Puedes acceder a él a través de Tus integraciones > Detalles de aplicación > Pruebas > Credenciales de prueba..
<?php
use MercadoPago\Client\Payment\PaymentClient;
use MercadoPago\Client\Common\RequestOptions;
use MercadoPago\MercadoPagoConfig;
MercadoPagoConfig::setAccessToken("YOUR_ACCESS_TOKEN");
$client = new PaymentClient();
$request_options = new RequestOptions();
$request_options->setCustomHeaders(["X-Idempotency-Key: <SOME_UNIQUE_VALUE>"]);
$payment = $client->create([
"transaction_amount" => (float) $_POST['<TRANSACTION_AMOUNT>'],
"token" => $_POST['<TOKEN>'],
"description" => $_POST['<DESCRIPTION>'],
"installments" => $_POST['<INSTALLMENTS>'],
"payment_method_id" => $_POST['<PAYMENT_METHOD_ID>'],
"issuer_id" => $_POST['<ISSUER>'],
"payer" => [
"email" => $_POST['<EMAIL>'],
"identification" => [
"type" => $_POST['<IDENTIFICATION_TYPE>'],
"number" => $_POST['<NUMBER>']
]
]
], $request_options);
echo implode($payment);
?>
import { MercadoPagoConfig, Payment } from '@src/index';
const client = new MercadoPagoConfig({ accessToken: '<ACCESS_TOKEN>', options: { timeout: 5000 } });
const payment = new Payment(client);
payment
.create({
body: {
transaction_amount: 100,
token: '<TOKEN>',
description: '<DESCRIPTION>',
installments: 1,
payment_method_id: '<PAYMENT_METHOD_ID>',
issuer_id: 310,
payer: {
email: '<EMAIL>',
identification: {
number: '12345678909',
type: 'CPF',
},
},
},
}).then(console.log).catch(console.log);
Map<String, String> customHeaders = new HashMap<>();
customHeaders.put("x-idempotency-key", <SOME_UNIQUE_VALUE>);
MPRequestOptions requestOptions = MPRequestOptions.builder()
.customHeaders(customHeaders)
.build();
MercadoPagoConfig.setAccessToken("YOUR_ACCESS_TOKEN");
PaymentClient client = new PaymentClient();
PaymentCreateRequest paymentCreateRequest =
PaymentCreateRequest.builder()
.transactionAmount(request.getTransactionAmount())
.token(request.getToken())
.description(request.getDescription())
.installments(request.getInstallments())
.paymentMethodId(request.getPaymentMethodId())
.payer(
PaymentPayerRequest.builder()
.email(request.getPayer().getEmail())
.firstName(request.getPayer().getFirstName())
.identification(
IdentificationRequest.builder()
.type(request.getPayer().getIdentification().getType())
.number(request.getPayer().getIdentification().getNumber())
.build())
.build())
.build();
client.create(paymentCreateRequest, requestOptions);
require 'mercadopago'
sdk = Mercadopago::SDK.new('YOUR_ACCESS_TOKEN')
custom_headers = {
'x-idempotency-key': '<SOME_UNIQUE_VALUE>'
}
custom_request_options = Mercadopago::RequestOptions.new(custom_headers: custom_headers)
payment_data = {
transaction_amount: params[:transactionAmount].to_f,
token: params[:token],
description: params[:description],
installments: params[:installments].to_i,
payment_method_id: params[:paymentMethodId],
payer: {
email: params[:cardholderEmail],
identification: {
type: params[:identificationType],
number: params[:identificationNumber]
},
first_name: params[:cardholderName]
}
}
payment_response = sdk.payment.create(payment_data, custom_request_options)
payment = payment_response[:response]
puts payment
using System;
using MercadoPago.Client.Common;
using MercadoPago.Client.Payment;
using MercadoPago.Config;
using MercadoPago.Resource.Payment;
MercadoPagoConfig.AccessToken = "YOUR_ACCESS_TOKEN";
var requestOptions = new RequestOptions();
requestOptions.CustomHeaders.Add("x-idempotency-key", "<SOME_UNIQUE_VALUE>");
var paymentRequest = new PaymentCreateRequest
{
TransactionAmount = decimal.Parse(Request["transactionAmount"]),
Token = Request["token"],
Description = Request["description"],
Installments = int.Parse(Request["installments"]),
PaymentMethodId = Request["paymentMethodId"],
Payer = new PaymentPayerRequest
{
Email = Request["cardholderEmail"],
Identification = new IdentificationRequest
{
Type = Request["identificationType"],
Number = Request["identificationNumber"],
},
FirstName = Request["cardholderName"]
},
};
var client = new PaymentClient();
Payment payment = await client.CreateAsync(paymentRequest, requestOptions);
Console.WriteLine(payment.Status);
import mercadopago
sdk = mercadopago.SDK("ACCESS_TOKEN")
request_options = mercadopago.config.RequestOptions()
request_options.custom_headers = {
'x-idempotency-key': '<SOME_UNIQUE_VALUE>'
}
payment_data = {
"transaction_amount": float(request.POST.get("transaction_amount")),
"token": request.POST.get("token"),
"description": request.POST.get("description"),
"installments": int(request.POST.get("installments")),
"payment_method_id": request.POST.get("payment_method_id"),
"payer": {
"email": request.POST.get("cardholderEmail"),
"identification": {
"type": request.POST.get("identificationType"),
"number": request.POST.get("identificationNumber")
},
"first_name": request.POST.get("cardholderName")
}
}
payment_response = sdk.payment().create(payment_data, request_options)
payment = payment_response["response"]
print(payment)
| Elemento | Descripción | Obligatoriedad |
Authorization | Header con tu Access Token de pruebasClave privada de la aplicación creada en Mercado Pago, utilizado en el backend. Puedes acceder a él a través de Tus integraciones > Detalles de aplicación > Pruebas > Credenciales de prueba.. | Obligatorio |
X-Idempotency-Key | Header con valor único por solicitud (por ejemplo, UUID v4) para evitar pagos duplicados. | Obligatorio |
token | Card token recibido en el callback onTokenGenerated. | Obligatorio |
payment_method_id | Identificador del medio de pago: visa o master. | Obligatorio |
transaction_amount | Monto de la transacción. | Obligatorio |
installments | Cantidad de cuotas. | Obligatorio |
payer | Datos del comprador. | Obligatorio |
description | Descripción del pago. | Obligatorio |
issuer_id | ID del emisor de la tarjeta. | Opcional |
La API devuelve una respuesta con una estructura similar a la del siguiente ejemplo:
json
{ "status": "approved", "status_detail": "accredited", "id": 3055677, "date_approved": "2019-02-23T00:01:10.000-04:00", "payer": { ... }, "payment_method_id": "visa", "payment_type_id": "credit_card", "refunds": [], ... }
Puedes simular distintos escenarios de pago en entorno de pruebas usando la propiedad testStatus en la configuración de Apple Pay. Solo tiene efecto cuando usas una Public Key de pruebasClave pública de la aplicación creada en Mercado Pago, usada en el frontend. Puedes acceder a ella a través de Tus integraciones > Detalles de aplicación > Pruebas > Credenciales de prueba..
testStatus es opcional y debe usarse únicamente para pruebas. En producción, no incluyas esta configuración.- Añade la propiedad
testStatusdentro deapplePayen tu configuración. Utiliza los diferentes valores posibles detallados en la tabla para simular escenarios de pago.
javascript
const settings = { checkoutTypes: ['applePay'], applePay: { paymentRequest: { /* ... */ }, sessionRequest: { /* ... */ }, callbacks: { /* ... */ }, testStatus: 'APRO' // Opcional: solo para pruebas } };
Valor testStatus | Escenario de pago |
APRO | Pago aprobado |
OTHE | Rechazado por error general |
CONT | Pendiente de pago |
CALL | Rechazado con validación para autorizar |
FUND | Rechazado por importe insuficiente |
SECU | Rechazado por código de seguridad inválido |
EXPI | Rechazado por fecha de vencimiento |
FORM | Rechazado por error de formulario |
CARD | Rechazado por falta de card_number |
INST | Rechazado por cuotas inválidas |
DUPL | Rechazado por pago duplicado |
LOCK | Rechazado por tarjeta deshabilitada |
CTNA | Rechazado por tipo de tarjeta no permitida |
ATTE | Rechazado por intentos excedidos del PIN |
BLAC | Rechazado por estar en lista negra |
UNSU | No soportado |
TEST | Usado para aplicar regla de montos |
