Tiempos de Liquidación y Flujos de Procesamiento
Los tiempos de liquidación y procesamiento varían según el método de pago, país de destino, red de payer y hora de la transacción. Esta guía te ayuda a establecer expectativas precisas para tus usuarios y gestionar tus operaciones de tesorería.
Liquidación de PayIn
Cuando un depósito Pay-In llega a COMPLETED, el importe neto (net_amount, en settlement_currency, tal como lo informa la notificación) se acredita en tu cuenta Cashela. Los fondos acreditados se liberan para su uso según el calendario de liquidación de Cashela y tu acuerdo con Cashela.
- Concilia dinero solo en depósitos
COMPLETEDyREVERSED. Los depósitosDECLINED,CANCELLEDyFAILEDno mueven dinero. - Una anulación o un reembolso total de un depósito con tarjeta retira de tu saldo el principal más la comisión de Cashela. Ver Anulaciones y reembolsos.
- Lo que tarda tu cliente en pagar depende del método de pago; los pagos con tarjeta deben completarse dentro del
validity_perioddel checkout (alrededor de una hora).
Liquidación de PayOut
Descripción General
La liquidación de PayOut se refiere a cuándo los fondos son entregados a la cuenta del beneficiario o están disponibles para retiro.
Liquidación por Método de Entrega
| Método de Entrega | Liquidación Típica | Impacto de Corte |
|---|---|---|
| Transferencia Bancaria (ACH) | 1 – 2 días hábiles | Siguiente día si antes del corte |
| Transferencia Bancaria (Instantánea) | Minutos a 4 horas | Disponibilidad 24/7 |
| PIX (Brasil) | Instantáneo | Disponibilidad 24/7 |
| SPEI (México) | Minutos a 2 horas | Horario extendido (6AM-11PM) |
| Retiro en Efectivo | 15 min – 4 horas | Horario de ubicaciones del socio |
| Billetera Móvil | Minutos a 1 hora | Disponibilidad 24/7 |
| SWIFT | 2 – 5 días hábiles | Solo horario bancario |
Horas de Corte de Procesamiento
Muchos payers tienen horas de corte diarias. Las transacciones enviadas después del corte se procesan el siguiente día hábil.
function getExpectedDelivery(payer, submissionTime) { const cutoffTime = payer.cut_off_time; // ej. "16:00" const timezone = payer.cut_off_timezone; // ej. "America/Sao_Paulo"
// Convertir hora de envío a zona horaria del payer const localTime = submissionTime.toLocaleString('en-US', { timeZone: timezone }); const [cutoffHour, cutoffMinute] = cutoffTime.split(':').map(Number);
// Verificar si es después del corte const localHour = new Date(localTime).getHours(); const isAfterCutoff = localHour >= cutoffHour;
// Calcular entrega esperada let deliveryDate = new Date(submissionTime);
if (isAfterCutoff) { // Agregar un día hábil deliveryDate = addBusinessDays(deliveryDate, 1, timezone); }
// Agregar tiempo de procesamiento típico del payer const minHours = payer.estimated_delivery.minimum_hours; const maxHours = payer.estimated_delivery.maximum_hours;
return { earliest: new Date(deliveryDate.getTime() + minHours * 3600000), latest: new Date(deliveryDate.getTime() + maxHours * 3600000), isAfterCutoff };}Procesamiento en Tiempo Real
Flujo de Procesamiento
Todas las transacciones pasan por un pipeline de procesamiento en tiempo real:
┌─────────────┐ ┌──────────────┐ ┌────────────────┐│ Transacción │────►│ Validación & │────►│ Envío a ││ Creada │ │ Cumplimiento │ │ Proveedor/Payer│└─────────────┘ └──────────────┘ └───────┬────────┘ │ ▼┌─────────────┐ ┌──────────────┐ ┌────────────────┐│ Webhook │◄────│ Actualización│◄────│ Procesamiento ││ Entregado │ │ de Estado │ │ del Proveedor │└─────────────┘ └──────────────┘ └────────────────┘Actualizaciones de Estado
Recibe actualizaciones de estado en tiempo real vía webhooks:
| Estado | Descripción | Evento Webhook |
|---|---|---|
CREATED | Transacción inicializada | transaction.created |
PROCESSING | Siendo procesada | transaction.processing |
SUBMITTED | Enviada al proveedor | transaction.submitted |
COMPLETED | Entregada exitosamente | transaction.completed |
FAILED | Procesamiento fallido | transaction.failed |
Consideraciones de Días Hábiles
Feriados y Fines de Semana
Los tiempos de procesamiento se ven afectados por:
- Feriados bancarios locales – Feriados del país de destino
- Fines de semana – La mayoría de transferencias bancarias se pausan
- Mantenimiento de proveedores – Tiempo de inactividad programado
Manejo de Días No Hábiles
function isBusinessDay(date, countryCode) { const holidays = getHolidays(countryCode, date.getFullYear()); const dayOfWeek = date.getDay();
// Verificación de fin de semana (0 = Domingo, 6 = Sábado) if (dayOfWeek === 0 || dayOfWeek === 6) { return false; }
// Verificación de feriado const dateStr = date.toISOString().split('T')[0]; if (holidays.includes(dateStr)) { return false; }
return true;}Mostrar Estimaciones a Usuarios
Buena Práctica: Mostrar Rango
Siempre muestra un rango en lugar de un tiempo específico:
function formatDeliveryEstimate(payer) { const { minimum_hours, maximum_hours } = payer.estimated_delivery;
if (minimum_hours === 0 && maximum_hours === 0) { return 'Entrega instantánea'; }
if (minimum_hours === 0) { return `Hasta ${formatDuration(maximum_hours)}`; }
return `${formatDuration(minimum_hours)} a ${formatDuration(maximum_hours)}`;}
function formatDuration(hours) { if (hours < 1) { return `${Math.round(hours * 60)} minutos`; } if (hours < 24) { return `${hours} hora${hours > 1 ? 's' : ''}`; } const days = Math.round(hours / 24); return `${days} día${days > 1 ? 's' : ''} hábil${days > 1 ? 'es' : ''}`;}
// Ejemplos de salida:// "Entrega instantánea"// "Hasta 4 horas"// "1 a 2 días hábiles"Conciliación
Proceso de Conciliación Diaria
async function dailyReconciliation() { // 1. Obtener todas las transacciones del día anterior const yesterday = new Date(); yesterday.setDate(yesterday.getDate() - 1);
const transactions = await api.getTransactions({ created_after: startOfDay(yesterday), created_before: endOfDay(yesterday) });
// 2. Agrupar por estado const byStatus = groupBy(transactions, 'status');
// 3. Verificar transacciones atascadas const processing = byStatus['PROCESSING'] || []; const stuckTransactions = processing.filter(tx => { const age = Date.now() - new Date(tx.created_at).getTime(); const maxAge = tx.payer.estimated_delivery.maximum_hours * 3600000; return age > maxAge * 1.5; // 50% sobre el tiempo esperado });
if (stuckTransactions.length > 0) { alertOperations('Transacciones atascadas detectadas', stuckTransactions); }
// 4. Generar reporte return { total: transactions.length, completadas: (byStatus['COMPLETED'] || []).length, fallidas: (byStatus['FAILED'] || []).length, pendientes: processing.length, atascadas: stuckTransactions.length };}Buenas Prácticas
- Establece expectativas precisas – Muestra tiempos de entrega realistas basados en datos del payer
- Considera los cortes – Advierte a los usuarios sobre horas de corte próximas
- Monitorea webhooks – No dependas solo de consultas para actualizaciones de estado
- Implementa conciliación – Ejecuta verificaciones diarias para detectar transacciones atascadas
- Maneja zonas horarias – Muestra las horas en la zona horaria local del usuario
- Planifica para feriados – Advierte a los usuarios durante períodos de feriados
Documentación Relacionada
- PayIn → Webhooks – Notificaciones de estado de PayIn
- PayOut → Transacción – Seguimiento de estado de transacción
- Notificaciones – Manejo de eventos webhook
- Obtener Payers – Estimaciones de tiempo de entrega por payer