Saltar al contenido principal

Checkout y Pagos

Guía completa para el procesamiento de pagos con Stripe, PayPal, MercadoPago y pagos en sitio.


Vista General

LosCenotes soporta múltiples pasarelas de pago:

PasarelaDescripciónRegión
StripeTarjetas de crédito/débitoGlobal
PayPalCuentas PayPalGlobal
MercadoPagoPopular en LatinoaméricaLATAM
On-SitePago en ubicaciónLocal

Flujo de Pago

1. Calcular Precio → /pricing/calculate-complete
2. Validar Reservación → /public/reservations/validate (opcional)
3. Crear Intención de Pago → /checkout/{provider}/create
4. Procesar Pago → Redirigir o Confirmar
5. Recibir Confirmación → Webhook o Callback

Métodos de Pago

GET /payment-methods

Listar todos los métodos de pago disponibles.

curl -X GET "https://service-gateway.loscenotes.com/payment-methods" \
-H "Content-Type: application/json"

Respuesta:

{
"success": true,
"message": "payment_methods.list_retrieved_successfully",
"data": [
{
"id": "pm-stripe",
"provider": "stripe",
"name": {
"es": "Tarjeta de crédito/débito",
"en": "Credit/Debit Card"
},
"description": {
"es": "Paga con Visa, Mastercard, Amex",
"en": "Pay with Visa, Mastercard, Amex"
},
"isActive": true,
"supportedCards": ["visa", "mastercard", "amex"],
"iconUrl": "/icons/stripe.svg",
"processingFee": 0,
"minAmount": 1000,
"maxAmount": 10000000,
"requiresNativeProcessing": true
},
{
"id": "pm-paypal",
"provider": "paypal",
"name": {
"es": "PayPal",
"en": "PayPal"
},
"description": {
"es": "Paga con tu cuenta PayPal",
"en": "Pay with your PayPal account"
},
"isActive": true,
"iconUrl": "/icons/paypal.svg",
"processingFee": 0,
"minAmount": 1000,
"maxAmount": 10000000,
"requiresNativeProcessing": false
},
{
"id": "pm-mercadopago",
"provider": "mercadopago",
"name": {
"es": "MercadoPago",
"en": "MercadoPago"
},
"description": {
"es": "Paga con MercadoPago, OXXO, SPEI",
"en": "Pay with MercadoPago, OXXO, SPEI"
},
"isActive": true,
"iconUrl": "/icons/mercadopago.svg",
"processingFee": 0,
"minAmount": 1000,
"maxAmount": 10000000,
"requiresNativeProcessing": false
},
{
"id": "pm-onsite",
"provider": "on_site",
"name": {
"es": "Pago en sitio",
"en": "Pay on-site"
},
"description": {
"es": "Paga al llegar al cenote (efectivo o tarjeta)",
"en": "Pay when you arrive at the cenote (cash or card)"
},
"isActive": true,
"iconUrl": "/icons/cash.svg",
"processingFee": 0,
"minAmount": 1000,
"maxAmount": 5000000,
"requiresNativeProcessing": false
}
],
"pagination": {
"total": 4,
"perPage": 10,
"currentPage": 1,
"lastPage": 1
}
}

GET /payment-methods/active

Obtener solo métodos de pago activos (recomendado para frontend).

curl -X GET "https://service-gateway.loscenotes.com/payment-methods/active" \
-H "Content-Type: application/json"

Pagos con Stripe

POST /checkout/stripe/create-payment-intent

Crear un PaymentIntent de Stripe para pagos con tarjeta.

curl -X POST "https://service-gateway.loscenotes.com/checkout/stripe/create-payment-intent" \
-H "Content-Type: application/json" \
-H "X-API-Key: pk_live_your_api_key" \
-d '{
"reservationId": "reservation-uuid",
"amount": 157500,
"currency": "MXN",
"customerEmail": "cliente@email.com",
"metadata": {
"cenoteId": "cenote-uuid",
"visitDate": "2025-03-15"
}
}'

Respuesta:

{
"success": true,
"message": "checkout.payment_intent_created_successfully",
"data": {
"clientSecret": "pi_3MQ...secret_abc123",
"paymentIntentId": "pi_3MQExample",
"amount": 157500,
"currency": "mxn",
"status": "requires_payment_method"
}
}

POST /checkout/stripe/confirm

Confirmar un pago de Stripe después de que el cliente ingresó los datos de tarjeta.

curl -X POST "https://service-gateway.loscenotes.com/checkout/stripe/confirm" \
-H "Content-Type: application/json" \
-H "X-API-Key: pk_live_your_api_key" \
-d '{
"paymentIntentId": "pi_3MQExample",
"paymentMethodId": "pm_card_visa"
}'

Respuesta:

{
"success": true,
"message": "checkout.payment_confirmed_successfully",
"data": {
"paymentIntentId": "pi_3MQExample",
"status": "succeeded",
"reservationId": "reservation-uuid",
"confirmationCode": "RES-ABC123",
"paidAt": "2025-03-10T15:30:00.000Z"
}
}

Pagos con PayPal

POST /checkout/paypal/create-order

Crear una orden de PayPal para pago.

curl -X POST "https://service-gateway.loscenotes.com/checkout/paypal/create-order" \
-H "Content-Type: application/json" \
-H "X-API-Key: pk_live_your_api_key" \
-d '{
"reservationId": "reservation-uuid",
"amount": 157500,
"currency": "MXN",
"returnUrl": "https://yourapp.com/payment/success",
"cancelUrl": "https://yourapp.com/payment/cancel"
}'

Respuesta:

{
"success": true,
"message": "checkout.paypal_order_created_successfully",
"data": {
"orderId": "5O190127TN364715T",
"approvalUrl": "https://www.paypal.com/checkoutnow?token=5O190127TN364715T",
"status": "CREATED"
}
}

POST /checkout/paypal/capture

Capturar un pago de PayPal después de que el usuario lo aprobó.

curl -X POST "https://service-gateway.loscenotes.com/checkout/paypal/capture" \
-H "Content-Type: application/json" \
-H "X-API-Key: pk_live_your_api_key" \
-d '{
"orderId": "5O190127TN364715T"
}'

Respuesta:

{
"success": true,
"message": "checkout.paypal_payment_captured_successfully",
"data": {
"orderId": "5O190127TN364715T",
"status": "COMPLETED",
"reservationId": "reservation-uuid",
"confirmationCode": "RES-ABC123",
"paidAt": "2025-03-10T15:30:00.000Z"
}
}

Pagos con MercadoPago

POST /checkout/mercadopago-native/create-preference

Crear una preferencia de MercadoPago para Checkout Pro.

curl -X POST "https://service-gateway.loscenotes.com/checkout/mercadopago-native/create-preference" \
-H "Content-Type: application/json" \
-H "X-API-Key: pk_live_your_api_key" \
-d '{
"reservationId": "reservation-uuid",
"items": [
{
"title": "Cenote Dos Ojos - 2 Adultos",
"quantity": 1,
"unitPrice": 1575,
"currency": "MXN"
}
],
"payer": {
"email": "cliente@email.com",
"name": "Juan Pérez"
},
"backUrls": {
"success": "https://yourapp.com/payment/success",
"failure": "https://yourapp.com/payment/failure",
"pending": "https://yourapp.com/payment/pending"
}
}'

Respuesta:

{
"success": true,
"message": "checkout.mercadopago_preference_created_successfully",
"data": {
"preferenceId": "1234567890-abc123-def456",
"checkoutUrl": "https://www.mercadopago.com.mx/checkout/v1/redirect?pref_id=1234567890-abc123-def456",
"initPoint": "https://www.mercadopago.com.mx/checkout/v1/redirect?pref_id=1234567890-abc123-def456"
}
}

Nota: Redirige al usuario a checkoutUrl para completar el pago en la página alojada de MercadoPago.


Pagos en Sitio

POST /checkout/on-site

Registrar un pago en sitio (pagar en ubicación).

curl -X POST "https://service-gateway.loscenotes.com/checkout/on-site" \
-H "Content-Type: application/json" \
-H "X-API-Key: pk_live_your_api_key" \
-d '{
"reservationId": "reservation-uuid",
"paymentMethod": "cash",
"notes": "Customer will pay in cash at arrival"
}'

Respuesta:

{
"success": true,
"message": "checkout.on_site_payment_registered",
"data": {
"reservationId": "reservation-uuid",
"status": "pending_payment",
"confirmationCode": "RES-ABC123",
"paymentDue": "on_arrival"
}
}

Validación de Reservación

POST /public/reservations/validate

Pre-validar una reservación antes de crearla.

curl -X POST "https://service-gateway.loscenotes.com/public/reservations/validate" \
-H "Content-Type: application/json" \
-H "X-API-Key: pk_live_your_api_key" \
-d '{
"cenoteId": "cenote-uuid",
"date": "2025-03-15",
"startTime": "09:00",
"endTime": "12:00",
"ageBreakdown": {
"adult": 2,
"child": 1
},
"guestEmail": "cliente@email.com",
"guestName": "Juan Pérez"
}'

Respuesta:

{
"success": true,
"message": "reservation.validation_completed",
"data": {
"isValid": true,
"availability": {
"available": true,
"remainingCapacity": 45
},
"pricing": {
"basePrice": 35000,
"totalVisitors": 3,
"subtotal": 91000,
"discounts": 0,
"total": 91000,
"currency": "MXN"
},
"warnings": [],
"errors": []
}
}

Webhooks

Las confirmaciones de pago también se envían via webhooks. Configura tu URL de webhook en el portal de partners.

Eventos de Webhook

EventoDescripción
payment.completedPago exitoso
payment.failedPago falló
payment.refundedPago fue reembolsado
reservation.confirmedReservación confirmada
reservation.cancelledReservación cancelada

Payload del Webhook

{
"event": "payment.completed",
"timestamp": "2025-03-10T15:30:00.000Z",
"data": {
"reservationId": "reservation-uuid",
"confirmationCode": "RES-ABC123",
"paymentId": "payment-uuid",
"amount": 157500,
"currency": "MXN",
"paymentMethod": "stripe",
"paidAt": "2025-03-10T15:30:00.000Z"
}
}

Manejo de Errores

Errores de Pago

ErrorDescripción
card_declinedTarjeta rechazada
insufficient_fundsFondos insuficientes
expired_cardTarjeta expirada
invalid_cvcCódigo de seguridad inválido
processing_errorError de procesamiento

Mejores Prácticas

try {
const result = await createPaymentIntent(data);
// Handle success
} catch (error) {
if (error.code === 'card_declined') {
showError('Tu tarjeta fue rechazada. Intenta con otra.');
} else if (error.code === 'insufficient_funds') {
showError('Fondos insuficientes en tu tarjeta.');
} else {
showError('Error al procesar el pago. Intenta de nuevo.');
}
}

Moneda

Todos los precios en la API se devuelven en CENTAVOS.

MontoCentavosMostrar
$350.00 MXN35000(35000 / 100).toFixed(2)
$1,575.00 MXN157500(157500 / 100).toFixed(2)
$15.00 USD1500(1500 / 100).toFixed(2)
// Convertir centavos a formato de visualización
const formatPrice = (cents, currency = 'MXN') => {
const amount = cents / 100;
return new Intl.NumberFormat('es-MX', {
style: 'currency',
currency: currency
}).format(amount);
};

console.log(formatPrice(157500)); // "$1,575.00"