Visión general
Qué es
Aceptar pagos con Apple Pay a través de MONDO
Lo que necesitas
ID de cuenta MONDO + Clave secreta
Lo que envías
Token de Apple Pay + cantidad + moneda
Lo que obtienes
ESTADO COMPLETADO o RECHAZADO
Cómo funciona
Opción A: Autoalojado
Muestra el botón de Apple Pay en tu sitio y envíanos el token
Opción B: Alojado por MONDO
Nosotros nos encargamos de todo - solo redirige a tu cliente hacia nosotros
Inicio rápido (Autoalojado)
POST https://server-to-server.getmondo.co/payment/
{
"company_account_id": "your_id",
"gateway_secret_key": "your_key",
"apple_pay_token": { /* from Apple Pay JS */ },
"transaction_amount": "99.99",
"transaction_currency_iso3": "EUR",
"live_or_sandbox": "sandbox"
}
Acerca de Apple Pay
Apple Pay ofrece una manera rápida, segura y privada para que los clientes paguen. Con MONDO como tu Proveedor de Servicios de Pago (PSP), puedes aceptar Apple Pay sin necesidad de tener tu propia cuenta de desarrollador de Apple.
MONDO como tu PSP
- ✓ MONDO posee el ID de comerciante de Apple
- ✓ MONDO gestiona certificados de Apple Pay
- ✓ MONDO gestiona la validación de comerciantes
- ✓ MONDO descifra y procesa tokens de pago
Gestión de Tokens — ¿Quién hace qué?
Apple Pay utiliza cifrado de extremo a extremo para proteger los datos del titular de la tarjeta. Así se dividen las responsabilidades:
| Apple (Dispositivo del cliente) | Genera un token de pago cifrado que contiene datos de la tarjeta, criptograma y detalles de autenticación |
| Tú (Comerciante) | Pase el token cifrado directamente a MONDO mediante el parámetro apple_pay_token — NO intente descifrarlo |
| MONDO (PSP) | Descifra el token usando nuestro certificado de procesamiento de pagos de Apple Pay y procesa el pago con CardCorp |
Elige tu método de integración
📋 Requisitos
- ✓ ID de cuenta de socio - Tu identificador único de cuenta MONDO
- ✓ Clave secreta del socio - Tu clave de autenticación API
- ✓ HTTPS - Tu sitio web debe usar HTTPS
⚠️ Se requiere verificación de dominio
Tu dominio debe estar registrado con Apple a través de MONDO. Esta es una configuración única.
- Ir a GETMONDO.CO
- Login → Developer → Apple Pay → Add Apple Pay Domain
🔄 Flujo de Pago
En tu sitio web
Interfaz nativa de Apple Pay
Tu llamada JS accede al punto de validación de MONDO
Face ID / Touch ID
POST to /payment/ with apple_pay_token
Usuario redirigido a URL de éxito/fallo
🔗 Punto final de API
Punto de validación del comerciante
Parámetros de Validación del Comerciante
| Parámetro | Tipo | Requerido | Descripción |
|---|---|---|---|
| validationURL | string | ✓ Sí | La URL proporcionada por Apple en la onvalidatemerchant evento |
| company_account_id | string | ✓ Sí | Tu ID de cuenta de socio MONDO |
| gateway_secret_key | string | ✓ Sí | Tu clave secreta de socio MONDO |
| domain_name | string | ○ Condicional | Tu dominio de Apple Pay (p. ej. paynow.yoursite.com). Necesario para llamadas de servidor a servidor donde el encabezado Origin del navegador no está disponible. No es necesario si se llama directamente desde el navegador. |
Si su backend hace de proxy para la llamada de validación del comerciante (es decir, su servidor llama a MONDO en lugar de que el navegador llame directamente), debe incluir
domain_name establecido en el dominio donde se muestra tu botón de Apple Pay. Esto asegura que la sesión de Apple Pay coincida con el dominio de tu página de pago. 📝 Parámetros Requeridos (Procesamiento de pago)
| Parámetro | Tipo | Descripción |
|---|---|---|
| company_account_id | string | Tu ID de cuenta de socio MONDO |
| gateway_secret_key | string | Tu clave secreta de socio MONDO |
| apple_pay_token | object | Cifrado token de event.payment.token — pasar directamente a MONDO tal cual (no descifrar) |
| transaction_amount | decimal | Importe del pago (p. ej., 99.99) |
| transaction_currency_iso3 | string | Código de moneda (EUR, USD, GBP) |
| cardholder_email_address | string | Correo electrónico del cliente |
Parámetros opcionales
| Parámetro | Descripción |
|---|---|
| partner_return_url_completed | URL para redirección de pago exitoso |
| partner_return_url_rejected | URL para redirección de pago rechazado |
| partner_webhook_url | URL para notificaciones webhook |
| live_or_sandbox | live o sandbox |
📤 Respuesta API
Los pagos con Apple Pay se procesan inmediatamente. La respuesta contiene el estado final de la transacción:
{
"status": "success",
"transaction_status": "COMPLETED",
"gateway_session_id": "73d68b79579eeaa4a1f35f667509ba19",
"transaction_id": "37819a4707f3736b6fb42148d98f05ab",
"gateway_message": "Transaction succeeded",
"redirect_url": "https://yoursite.com/success?gateway_session_id=...&payment_status=COMPLETED"
}
Campos de respuesta
| Campo | Descripción |
|---|---|
| status | success o error |
| transaction_status | COMPLETED o REJECTED |
| gateway_session_id | Identificador único de sesión para esta transacción |
| transaction_id | Identificador único de transacción - úsalo para correlacionar con callbacks |
| gateway_message | Mensaje de estado legible |
| redirect_url | URL para redirigir al usuario después del pago (opcional - solo para UX) |
A diferencia de los pagos con tarjeta que requieren redirección 3D Secure, las transacciones con Apple Pay se procesan al instante. El pago ya está completo cuando recibes la respuesta.
🍎 Integración de Apple Pay JS
Paso 1: Añadir botón de Apple Pay
<apple-pay-button buttonstyle="black" type="plain" locale="en" onclick="startApplePayPayment()"></apple-pay-button>
Paso 2: Comprobar disponibilidad
if (window.ApplePaySession && ApplePaySession.canMakePayments()) {
document.getElementById('apple-pay-button').style.display = 'block';
}
Paso 3: Implementación Completa
async function startApplePayPayment() {
const paymentRequest = {
countryCode: 'US',
currencyCode: 'EUR',
merchantCapabilities: ['supports3DS'],
supportedNetworks: ['visa', 'masterCard'],
total: { label: 'Your Company', amount: '99.99', type: 'final' }
};
const session = new ApplePaySession(3, paymentRequest);
// Merchant Validation
session.onvalidatemerchant = async (event) => {
const resp = await fetch('https://server-to-server.getmondo.co/payment/apple_pay_validate_merchant.php', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
validationURL: event.validationURL,
company_account_id: 'YOUR_ACCOUNT_ID',
gateway_secret_key: 'YOUR_SECRET_KEY',
domain_name: 'your-domain.com' // Required for server-to-server; optional if browser calls directly
})
});
session.completeMerchantValidation(await resp.json());
};
// Payment Authorization - Apple provides ENCRYPTED token in event.payment.token
// IMPORTANT: Pass the token directly to MONDO - do NOT attempt to decrypt it
session.onpaymentauthorized = async (event) => {
const resp = await fetch('https://server-to-server.getmondo.co/payment/', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
company_account_id: 'YOUR_ACCOUNT_ID',
gateway_secret_key: 'YOUR_SECRET_KEY',
apple_pay_token: event.payment.token, // Encrypted token - MONDO decrypts
transaction_amount: '99.99',
transaction_currency_iso3: 'EUR',
cardholder_email_address: 'customer@example.com',
partner_return_url_completed: 'https://yoursite.com/success',
partner_return_url_rejected: 'https://yoursite.com/failed',
live_or_sandbox: 'live'
})
});
const result = await resp.json();
if (result.transaction_status === 'COMPLETED') {
session.completePayment(ApplePaySession.STATUS_SUCCESS);
// Payment already processed - redirect is optional for user experience
if (result.redirect_url) {
window.location.href = result.redirect_url;
}
} else {
session.completePayment(ApplePaySession.STATUS_FAILURE);
if (result.redirect_url) {
window.location.href = result.redirect_url;
}
}
};
session.begin();
}
Modos de prueba
MONDO soporta dos modos de prueba. Entender la diferencia es crucial para una integración exitosa.
Qué sucede
- ✅ La estructura del token está validada
- ✅ Todos los campos requeridos están verificados
- ⏭️ La descodificación se omite (se devuelve datos simulados)
- ⏭️ La llamada a la API de CardCorp se ha omitido
- ✅ Se ha ejecutado el flujo completo de pago
Qué sucede
- ✅ La estructura del token está validada
- ✅ Todos los campos requeridos están verificados
- ✅ Descifrado criptográfico real
- ✅ Procesamiento de API Real CardCorp
- ✅ Se cobra dinero real
🎯 ¿Por qué SANDBOX requiere la misma estructura de token?
Este diseño garantiza que al cambiar de SANDBOX a LIVE, tu integración funcione inmediatamente sin cambios en el código.
⚙️ Configurando el modo
Incluir live_or_sandbox parámetro en tu solicitud de API:
{
"company_account_id": "your_account_id",
"gateway_secret_key": "your_secret_key",
"apple_pay_token": { ... },
"transaction_amount": "99.99",
"transaction_currency_iso3": "EUR",
"live_or_sandbox": "sandbox" // or "live" for production
}
🎭 Sandbox: Forzar Resultado de Transacción
En modo SANDBOX, puedes forzar un resultado específico de la transacción para pruebas:
| Parámetro | Valor | Resultado |
|---|---|---|
| sandbox_force_transaction_status | COMPLETED |
✅ Pago aprobado |
| sandbox_force_transaction_status | REJECTED |
❌ Pago rechazado |
Estructura del token de Apple Pay
El token de Apple Pay debe tener la siguiente estructura. Esto es igual tanto para los modos SANDBOX como LIVE.
"***") resultará en un error, incluso en modo SANDBOX. Estructura de Token Requerida
{
"paymentData": {
"version": "EC_v1",
"data": "BASE64_ENCRYPTED_PAYMENT_DATA",
"signature": "BASE64_SIGNATURE",
"header": {
"ephemeralPublicKey": "BASE64_EPHEMERAL_KEY",
"publicKeyHash": "BASE64_PUBLIC_KEY_HASH",
"transactionId": "UNIQUE_TRANSACTION_ID"
}
},
"paymentMethod": {
"displayName": "Visa 1234",
"network": "Visa",
"type": "debit"
},
"transactionIdentifier": "APPLE_TRANSACTION_ID"
}
Descripciones de campo
| Campo | Requerido | Descripción |
|---|---|---|
| paymentData.version | ✓ | Siempre EC_v1 |
| paymentData.data | ✓ | Datos de pago cifrados en Base64 de Apple |
| paymentData.signature | ✓ | Firma Base64 para verificación |
| paymentData.header.ephemeralPublicKey | ✓ | Clave pública efímera Base64 |
| paymentData.header.publicKeyHash | ✓ | Hash Base64 de la clave pública del comerciante |
| paymentData.header.transactionId | ✓ | Identificador único de transacción |
| paymentMethod.network | ○ | Red de tarjetas (Visa, Mastercard, Amex) |
| paymentMethod.displayName | ○ | Mostrar nombre desde Apple Wallet |
✓ = Requerido | ○ = Recomendado
Token de Prueba Sandbox
Copia este token para pruebas en SANDBOX. Los valores cifrados no necesitan ser reales, solo se valida la estructura.
{
"paymentData": {
"version": "EC_v1",
"data": "c2FuZGJveF9lbmNyeXB0ZWRfZGF0YV8xNzAyMjU2MDAwMDAw",
"signature": "c2FuZGJveF9zaWduYXR1cmVfMTcwMjI1NjAwMDAwMA==",
"header": {
"ephemeralPublicKey": "c2FuZGJveF9lcGhlbWVyYWxfa2V5XzE3MDIyNTYwMDAwMDA=",
"publicKeyHash": "c2FuZGJveF9wdWJsaWNfa2V5X2hhc2g=",
"transactionId": "SANDBOX_TXN_1702256000000_a1b2c3d4e5f6"
}
},
"paymentMethod": {
"displayName": "Visa 4242",
"network": "Visa",
"type": "debit"
},
"transactionIdentifier": "SANDBOX_TXN_1702256000000_a1b2c3d4e5f6"
}
Errores comunes de token
| Error | Causa | Solución |
|---|---|---|
| Invalid token format | El token no es un objeto JSON | Enviar token como objeto, no como cadena |
| Missing paymentData | El token no tiene la propiedad paymentData | Incluir token completo de Apple Pay JS |
| Missing header fields | falta ephemeralPublicKey, publicKeyHash o transactionId | Asegúrate de que todos los campos del encabezado estén presentes |
¿De dónde viene el token?
En modo EN VIVO, el token proviene de Apple Pay JS cuando el usuario autoriza el pago:
session.onpaymentauthorized = (event) => {
// This is the token you send to MONDO
const token = event.payment.token;
// Send to MONDO API
fetch('/payment/', {
body: JSON.stringify({
apple_pay_token: token, // Pass the entire token object
...
})
});
};
Estado de la transacción
Entender los estados de las transacciones y cómo consultarlos es esencial para una integración completa.
Estados Finales de la Transacción
Estos son los posibles estados finales que recibirás vía webhook o al consultar el endpoint /details:
Estado Intermedio
La transacción se ha creado pero aún se está procesando. Esto puede ocurrir cuando:
- El usuario está completando la autenticación 3D Secure
- El pago está siendo procesado por la red de tarjetas
- El usuario abandonó el proceso de pago
¿Cuándo deberías consultar el estado de la transacción?
- No recibiste un webhook dentro del tiempo esperado (por ejemplo, 5 minutos)
- Necesitas verificar el estado de una transacción manualmente
- Tu punto final de webhook estuvo temporalmente no disponible
Estado de la Transacción
Para verificar el estado de una transacción, realiza una solicitud POST al punto final de detalles:
Parámetros de solicitud
| Parámetro | Requerido | Descripción |
|---|---|---|
| company_account_id | ✓ | Tu ID de cuenta de socio MONDO |
| gateway_secret_key | ✓ | Tu clave secreta de socio MONDO |
| gateway_session_id | ✓ | El ID de sesión devuelto de la solicitud de pago inicial |
Solicitud de Ejemplo
curl -X POST https://server-to-server.getmondo.co/details/ \
-H "Content-Type: application/json" \
-d '{
"company_account_id": "your_account_id",
"gateway_secret_key": "your_secret_key",
"gateway_session_id": "sess_abc123xyz"
}'
Respuesta Ejemplo
{
"success": true,
"transaction_status": "COMPLETED",
"gateway_session_id": "sess_abc123xyz",
"transaction_amount": "99.99",
"transaction_currency_iso3": "EUR",
"card_last_4_digits": "4242",
"card_brand": "VISA",
"gateway_result_code": "000.000.000",
"gateway_result_description": "Transaction succeeded",
"created_at": "2024-12-10T22:30:00Z",
"completed_at": "2024-12-10T22:31:15Z"
}
Recibiendo actualizaciones de estado
Hay dos maneras de recibir el estado final de la transacción:
| Método | Cómo funciona | Cuándo usar |
|---|---|---|
| Webhook Recomendado | MONDO envía una solicitud POST a tu partner_webhook_url |
Método principal - automático, en tiempo real |
| Redirect URL | El usuario es redirigido a su partner_return_url_completed o partner_return_url_rejected |
Para confirmación del usuario |
| Query /details | Haces una solicitud POST para verificar el estado | Recurso si no se recibe webhook |
Si la transacción permanece INICIADA
Si una transacción permanece en estado INICIADO durante más de 15 minutos, probablemente significa:
- El usuario abandonó el desafío 3D Secure
- El usuario cerró su navegador durante el pago
- Hubo un problema de red durante el procesamiento
Acción: Consulta el punto final /details para obtener el estado actual. Estas transacciones eventualmente expirarán y pasarán al estado FAILED o CANCELED.