💻 Ejemplos de Uso en PHP
Configuración Inicial
Section titled “Configuración Inicial”Antes de empezar, configura las constantes necesarias en tu aplicación:
<?php// URL base de tu instancia de Dataemunahdefine('DATAEMUNAH_HOST', 'https://aw.dataemunah.com');
// Tu API Key proporcionada por el líder técnicodefine('API_PAYROLL_KEY', 'tu_api_key_aqui');
// Endpoint de nóminadefine('NOMINA_ENDPOINT', DATAEMUNAH_HOST . '/api/nomina/calculate');Función Base para Peticiones
Section titled “Función Base para Peticiones”Crea una función reutilizable para hacer peticiones al endpoint:
<?php/** * Realiza una petición al endpoint de simulación de nómina * * @param array $requestData Datos del request * @return array Respuesta decodificada del API * @throws Exception Si hay error en la petición */function calcularNomina($requestData){ // Configurar headers $headers = [ 'Content-Type: application/json', 'X-Api-Key: Bearer ' . API_PAYROLL_KEY ];
// Inicializar cURL $ch = curl_init(NOMINA_ENDPOINT);
// Configurar opciones curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($requestData)); curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_TIMEOUT, 30); // Timeout de 30 segundos
// Ejecutar petición $response = curl_exec($ch); $statusCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); $curlError = curl_error($ch);
curl_close($ch);
// Verificar errores de cURL if ($curlError) { throw new Exception('Error en la conexión: ' . $curlError); }
// Decodificar respuesta $apiResponse = json_decode($response, true);
if (json_last_error() !== JSON_ERROR_NONE) { throw new Exception('Error al decodificar JSON: ' . json_last_error_msg()); }
// Verificar respuesta exitosa if ($statusCode !== 200 || !$apiResponse['success']) { $errorMsg = $apiResponse['error']['message'] ?? 'Error desconocido'; throw new Exception('Error del API (HTTP ' . $statusCode . '): ' . $errorMsg); }
return $apiResponse;}Ejemplo 1: Cálculo Individual Básico
Section titled “Ejemplo 1: Cálculo Individual Básico”Calcula la nómina de un empleado en escenario promedio sin novedades:
<?phprequire_once 'config.php';require_once 'funciones_nomina.php';
try { $requestData = [ 'periodo' => [ 'mes' => 1, 'anio' => 2025 ], 'nivelCalculo' => 'empleado', 'escenario' => 'promedio', 'porcentajeNovedades' => 0, // Sin novedades 'perfiles' => [ [ 'idEmpleado' => 'EMP001', 'tipoContrato' => 'indefinido', 'salarioBasico' => 3000000, 'tipoSalario' => 'no_integral', 'diasContratados' => 30, 'aplicaAuxilioTransporte' => true, 'nivelRiesgoArl' => 1 ] ] ];
$respuesta = calcularNomina($requestData);
// Extraer datos del empleado $empleado = $respuesta['data']['resultados']['detalleEmpleados'][0];
echo "=== RESUMEN EMPLEADO {$empleado['idEmpleado']} ===\n"; echo "Salario Básico: $" . number_format($empleado['devengos']['salarioBasico'], 2) . "\n"; echo "Auxilio Transporte: $" . number_format($empleado['devengos']['auxilioTransporte'], 2) . "\n"; echo "Total Devengos: $" . number_format($empleado['devengos']['totalDevengos'], 2) . "\n"; echo "Total Deducciones: $" . number_format($empleado['deducciones']['totalDeducciones'], 2) . "\n"; echo "Nómina Neta: $" . number_format($empleado['totales']['nominaNeta'], 2) . "\n"; echo "Costo Empleador: $" . number_format($empleado['totales']['costoEmpleador'], 2) . "\n"; echo "Provisiones: $" . number_format($empleado['totales']['totalProvisiones'], 2) . "\n"; echo "COSTO TOTAL RH: $" . number_format($empleado['totales']['costoTotalRecursoHumano'], 2) . "\n";
} catch (Exception $e) { echo "Error: " . $e->getMessage() . "\n";}Salida esperada:
=== RESUMEN EMPLEADO EMP001 ===Salario Básico: $3,000,000.00Auxilio Transporte: $200,000.00Total Devengos: $3,200,000.00Total Deducciones: $240,000.00Nómina Neta: $2,960,000.00Costo Empleador: $735,000.00Provisiones: $266,560.00COSTO TOTAL RH: $3,961,560.00Ejemplo 2: Escenario de Proyecto con Múltiples Empleados
Section titled “Ejemplo 2: Escenario de Proyecto con Múltiples Empleados”Calcula el costo total de un proyecto con varios empleados:
<?phprequire_once 'config.php';require_once 'funciones_nomina.php';
try { $requestData = [ 'periodo' => [ 'mes' => 2, 'anio' => 2025 ], 'nivelCalculo' => 'proyecto', 'escenario' => 'promedio', 'porcentajeNovedades' => 30, // 30% de empleados con novedades 'perfiles' => [ [ 'idEmpleado' => 'EMP001', 'idProyecto' => 'PROYECTO_ALPHA', 'tipoContrato' => 'indefinido', 'salarioBasico' => 4500000, 'tipoSalario' => 'no_integral', 'diasContratados' => 30, 'aplicaAuxilioTransporte' => false, 'nivelRiesgoArl' => 2 ], [ 'idEmpleado' => 'EMP002', 'idProyecto' => 'PROYECTO_ALPHA', 'tipoContrato' => 'termino_fijo', 'salarioBasico' => 3000000, 'tipoSalario' => 'no_integral', 'diasContratados' => 30, 'aplicaAuxilioTransporte' => true, 'nivelRiesgoArl' => 2 ], [ 'idEmpleado' => 'EMP003', 'idProyecto' => 'PROYECTO_ALPHA', 'tipoContrato' => 'indefinido', 'salarioBasico' => 2500000, 'tipoSalario' => 'no_integral', 'diasContratados' => 30, 'aplicaAuxilioTransporte' => true, 'nivelRiesgoArl' => 1 ] ] ];
$respuesta = calcularNomina($requestData);
// Extraer totales por proyecto $proyectos = $respuesta['data']['resultados']['totalesPorProyecto'];
foreach ($proyectos as $proyecto) { echo "\n=== PROYECTO: {$proyecto['idProyecto']} ===\n"; echo "Empleados: {$proyecto['cantidadEmpleados']}\n"; echo "Empleados con novedades: {$proyecto['empleadosConNovedades']}\n"; echo "Total Salarios: $" . number_format($proyecto['totales']['totalSalariosBasicos'], 2) . "\n"; echo "Total Nómina Neta: $" . number_format($proyecto['totales']['totalNominaNeta'], 2) . "\n"; echo "Total Costo RH: $" . number_format($proyecto['totales']['totalCostoRecursoHumano'], 2) . "\n"; }
// Estadísticas de novedades $stats = $respuesta['data']['resultados']['estadisticasNovedades']; echo "\n=== ESTADÍSTICAS DE NOVEDADES ===\n"; echo "Porcentaje configurado: {$stats['porcentajeConfigurado']}%\n"; echo "Porcentaje real aplicado: {$stats['porcentajeReal']}%\n"; echo "Empleados con novedades: {$stats['empleadosConNovedades']} de {$stats['totalEmpleados']}\n";
} catch (Exception $e) { echo "Error: " . $e->getMessage() . "\n";}Ejemplo 3: Comparación de Escenarios
Section titled “Ejemplo 3: Comparación de Escenarios”Compara los 3 escenarios para el mismo grupo de empleados:
<?phprequire_once 'config.php';require_once 'funciones_nomina.php';
// Datos base de empleados$perfiles = [ [ 'idEmpleado' => 'EMP001', 'tipoContrato' => 'indefinido', 'salarioBasico' => 3500000, 'tipoSalario' => 'no_integral', 'diasContratados' => 30, 'aplicaAuxilioTransporte' => true, 'nivelRiesgoArl' => 1 ], [ 'idEmpleado' => 'EMP002', 'tipoContrato' => 'indefinido', 'salarioBasico' => 2800000, 'tipoSalario' => 'no_integral', 'diasContratados' => 30, 'aplicaAuxilioTransporte' => true, 'nivelRiesgoArl' => 1 ]];
$escenarios = ['mejor', 'promedio', 'peor'];$resultados = [];
try { foreach ($escenarios as $escenario) { $requestData = [ 'periodo' => ['mes' => 1, 'anio' => 2025], 'nivelCalculo' => 'empleado', 'escenario' => $escenario, 'porcentajeNovedades' => 50, // Solo aplica en promedio 'perfiles' => $perfiles ];
$respuesta = calcularNomina($requestData); $totales = $respuesta['data']['resultados']['totalesGenerales'];
$resultados[$escenario] = [ 'nominaNeta' => $totales['totalNominaNeta'], 'costoTotal' => $totales['totalCostoRecursoHumano'] ]; }
// Mostrar comparación echo "=== COMPARACIÓN DE ESCENARIOS ===\n\n"; echo str_pad("ESCENARIO", 15) . str_pad("NÓMINA NETA", 20) . "COSTO TOTAL RH\n"; echo str_repeat("-", 60) . "\n";
foreach ($resultados as $escenario => $datos) { echo str_pad(strtoupper($escenario), 15); echo str_pad("$" . number_format($datos['nominaNeta'], 2), 20); echo "$" . number_format($datos['costoTotal'], 2) . "\n"; }
// Calcular diferencias $difMejorPeor = $resultados['peor']['costoTotal'] - $resultados['mejor']['costoTotal']; $porcDif = ($difMejorPeor / $resultados['mejor']['costoTotal']) * 100;
echo "\n=== ANÁLISIS ===\n"; echo "Diferencia Mejor vs Peor: $" . number_format($difMejorPeor, 2) . "\n"; echo "Porcentaje de variación: " . number_format($porcDif, 2) . "%\n";
} catch (Exception $e) { echo "Error: " . $e->getMessage() . "\n";}Ejemplo 4: Empleado con Novedades Específicas
Section titled “Ejemplo 4: Empleado con Novedades Específicas”Calcula nómina con horas extras, bonificaciones y otros conceptos:
<?phprequire_once 'config.php';require_once 'funciones_nomina.php';
try { $requestData = [ 'periodo' => [ 'mes' => 3, 'anio' => 2025 ], 'nivelCalculo' => 'empleado', 'escenario' => 'promedio', 'perfiles' => [ [ 'idEmpleado' => 'EMP001', 'tipoContrato' => 'indefinido', 'salarioBasico' => 3000000, 'tipoSalario' => 'no_integral', 'diasContratados' => 30, 'aplicaAuxilioTransporte' => true, 'nivelRiesgoArl' => 2, 'novedades' => [ 'horasExtras' => [ 'diurnas' => 15, // 15 horas extras diurnas 'nocturnas' => 8 // 8 horas extras nocturnas ], 'recargos' => [ 'nocturno' => 20 // 20 horas trabajo nocturno ], 'bonificaciones' => [ [ 'concepto' => 'Bonificación por cumplimiento de objetivos', 'tipo' => 'salarial', 'monto' => 600000 ], [ 'concepto' => 'Auxilio de alimentación', 'tipo' => 'no_salarial', 'monto' => 300000 ] ] ] ] ] ];
$respuesta = calcularNomina($requestData); $empleado = $respuesta['data']['resultados']['detalleEmpleados'][0];
echo "=== DETALLE DE NÓMINA CON NOVEDADES ===\n\n";
// Devengos echo "DEVENGOS:\n"; echo " Salario Básico: $" . number_format($empleado['devengos']['salarioBasico'], 2) . "\n"; echo " Auxilio Transporte: $" . number_format($empleado['devengos']['auxilioTransporte'], 2) . "\n"; echo " Horas Extras: $" . number_format($empleado['devengos']['horasExtras'], 2) . "\n"; echo " Recargos: $" . number_format($empleado['devengos']['recargos'], 2) . "\n"; echo " Bonificaciones: $" . number_format($empleado['devengos']['bonificaciones'], 2) . "\n"; echo " TOTAL DEVENGOS: $" . number_format($empleado['devengos']['totalDevengos'], 2) . "\n\n";
// Deducciones echo "DEDUCCIONES:\n"; echo " Salud: $" . number_format($empleado['deducciones']['salud'], 2) . "\n"; echo " Pensión: $" . number_format($empleado['deducciones']['pension'], 2) . "\n"; echo " Retención: $" . number_format($empleado['deducciones']['retencionFuente'], 2) . "\n"; echo " TOTAL DEDUCCIONES: $" . number_format($empleado['deducciones']['totalDeducciones'], 2) . "\n\n";
// Detalle de novedades aplicadas if (!empty($empleado['novedades']['horasExtras'])) { echo "DETALLE HORAS EXTRAS:\n"; foreach ($empleado['novedades']['horasExtras']['detalle'] as $he) { echo " {$he['tipo']}: {$he['cantidad']}h x $" . number_format($he['valorHora'], 2) . " = $" . number_format($he['total'], 2) . "\n"; } echo "\n"; }
// Totales finales echo "=== TOTALES ===\n"; echo "Nómina a Pagar: $" . number_format($empleado['totales']['nominaNeta'], 2) . "\n"; echo "Costo Empleador: $" . number_format($empleado['totales']['costoEmpleador'], 2) . "\n"; echo "Provisiones: $" . number_format($empleado['totales']['totalProvisiones'], 2) . "\n"; echo "COSTO TOTAL: $" . number_format($empleado['totales']['costoTotalRecursoHumano'], 2) . "\n";
} catch (Exception $e) { echo "Error: " . $e->getMessage() . "\n";}Ejemplo 5: Porcentajes Personalizados (Exoneración Parafiscales)
Section titled “Ejemplo 5: Porcentajes Personalizados (Exoneración Parafiscales)”Calcula nómina con empresa exonerada de SENA e ICBF:
<?phprequire_once 'config.php';require_once 'funciones_nomina.php';
try { $requestData = [ 'periodo' => [ 'mes' => 1, 'anio' => 2025 ], 'nivelCalculo' => 'empleado', 'escenario' => 'promedio', 'porcentajeNovedades' => 0, 'porcentajesPersonalizados' => [ 'saludEmpleado' => 0.04, 'saludEmpleador' => 0.085, 'pensionEmpleado' => 0.04, 'pensionEmpleador' => 0.12, 'sena' => 0, // ✅ Exonerado 'icbf' => 0, // ✅ Exonerado 'cajaCompensacion' => 0.04, 'cesantias' => 0.0833, 'interesesCesantias' => 0.01, 'primaServicios' => 0.0833, 'vacaciones' => 0.0417 ], 'perfiles' => [ [ 'idEmpleado' => 'EMP001', 'tipoContrato' => 'indefinido', 'salarioBasico' => 5000000, 'tipoSalario' => 'no_integral', 'diasContratados' => 30, 'aplicaAuxilioTransporte' => false, 'nivelRiesgoArl' => 1 ] ] ];
$respuesta = calcularNomina($requestData); $empleado = $respuesta['data']['resultados']['detalleEmpleados'][0];
echo "=== APORTES EMPLEADOR (CON EXONERACIÓN) ===\n"; echo "Salud: $" . number_format($empleado['aportesEmpleador']['salud'], 2) . "\n"; echo "Pensión: $" . number_format($empleado['aportesEmpleador']['pension'], 2) . "\n"; echo "ARL: $" . number_format($empleado['aportesEmpleador']['arl'], 2) . "\n"; echo "SENA: $" . number_format($empleado['aportesEmpleador']['sena'], 2) . " ✅ EXONERADO\n"; echo "ICBF: $" . number_format($empleado['aportesEmpleador']['icbf'], 2) . " ✅ EXONERADO\n"; echo "Caja Compensación: $" . number_format($empleado['aportesEmpleador']['cajaCompensacion'], 2) . "\n"; echo "TOTAL: $" . number_format($empleado['aportesEmpleador']['totalAportesEmpleador'], 2) . "\n";
} catch (Exception $e) { echo "Error: " . $e->getMessage() . "\n";}Ejemplo 6: Salario Integral
Section titled “Ejemplo 6: Salario Integral”Calcula nómina de un empleado con salario integral:
<?phprequire_once 'config.php';require_once 'funciones_nomina.php';
try { $requestData = [ 'periodo' => [ 'mes' => 1, 'anio' => 2025 ], 'nivelCalculo' => 'empleado', 'escenario' => 'promedio', 'perfiles' => [ [ 'idEmpleado' => 'GERENTE001', 'tipoContrato' => 'indefinido', 'salarioBasico' => 20000000, // > 13 SMMLV 'tipoSalario' => 'integral', // ✅ Salario integral 'diasContratados' => 30, 'aplicaAuxilioTransporte' => false, // No aplica en integral 'nivelRiesgoArl' => 1 ] ] ];
$respuesta = calcularNomina($requestData); $empleado = $respuesta['data']['resultados']['detalleEmpleados'][0];
echo "=== SALARIO INTEGRAL ===\n\n"; echo "Salario Total: $" . number_format($empleado['devengos']['salarioBasico'], 2) . "\n"; echo "Factor Prestacional (30%): $" . number_format($empleado['devengos']['salarioBasico'] * 0.3, 2) . "\n"; echo "Salario Base (70%): $" . number_format($empleado['devengos']['baseIbc'], 2) . "\n\n";
echo "DEDUCCIONES:\n"; echo "Salud: $" . number_format($empleado['deducciones']['salud'], 2) . " ❌ NO APLICA\n"; echo "Pensión: $" . number_format($empleado['deducciones']['pension'], 2) . " ❌ NO APLICA\n\n";
echo "APORTES EMPLEADOR:\n"; echo "Todos los aportes: $" . number_format($empleado['aportesEmpleador']['totalAportesEmpleador'], 2) . " ❌ NO APLICAN\n\n";
echo "PROVISIONES:\n"; echo "Todas las provisiones: $" . number_format($empleado['provisiones']['totalProvisiones'], 2) . " ❌ NO APLICAN\n"; echo "(Ya están incluidas en el factor prestacional del 30%)\n\n";
echo "COSTO TOTAL: $" . number_format($empleado['totales']['costoTotalRecursoHumano'], 2) . "\n";
} catch (Exception $e) { echo "Error: " . $e->getMessage() . "\n";}Manejo de Errores
Section titled “Manejo de Errores”Ejemplo de manejo robusto de errores:
<?phprequire_once 'config.php';require_once 'funciones_nomina.php';
function calcularNominaSeguro($requestData){ try { $respuesta = calcularNomina($requestData);
// Log exitoso error_log("Cálculo exitoso - Tiempo: " . $respuesta['metadata']['tiempoProcesamientoMs'] . "ms");
return [ 'exito' => true, 'datos' => $respuesta['data'] ];
} catch (Exception $e) { // Log del error error_log("Error en cálculo de nómina: " . $e->getMessage());
// Determinar tipo de error $mensaje = $e->getMessage();
if (strpos($mensaje, 'HTTP 400') !== false) { $tipoError = 'validacion'; $mensajeUsuario = 'Hay errores en los datos enviados. Verifica los parámetros.'; } elseif (strpos($mensaje, 'HTTP 403') !== false) { $tipoError = 'autenticacion'; $mensajeUsuario = 'API Key inválido. Contacta al líder técnico.'; } elseif (strpos($mensaje, 'HTTP 500') !== false) { $tipoError = 'servidor'; $mensajeUsuario = 'Error interno del servidor. Intenta más tarde.'; } elseif (strpos($mensaje, 'timeout') !== false) { $tipoError = 'timeout'; $mensajeUsuario = 'La petición tardó demasiado. Intenta con menos perfiles.'; } else { $tipoError = 'conexion'; $mensajeUsuario = 'Error de conexión. Verifica tu conexión a internet.'; }
return [ 'exito' => false, 'tipoError' => $tipoError, 'mensaje' => $mensajeUsuario, 'detallesTecnicos' => $mensaje ]; }}
// Uso$resultado = calcularNominaSeguro($requestData);
if ($resultado['exito']) { // Procesar datos exitosos $datos = $resultado['datos']; // ... tu lógica} else { // Manejar error echo "Error: " . $resultado['mensaje'] . "\n";
if (DEBUG_MODE) { echo "Detalles: " . $resultado['detallesTecnicos'] . "\n"; }}Tips de Optimización
Section titled “Tips de Optimización”1. Cachear Resultados
Section titled “1. Cachear Resultados”Para escenarios que se consultan frecuentemente:
<?phpfunction obtenerCostoProyecto($idProyecto, $mes, $anio, $escenario){ $cacheKey = "nomina_{$idProyecto}_{$mes}_{$anio}_{$escenario}";
// Intentar obtener del caché (ej: Redis, Memcached, archivo) $cached = obtenerDeCache($cacheKey); if ($cached !== null) { return $cached; }
// Si no está en caché, calcular $resultado = calcularNomina(/* ... */);
// Guardar en caché por 1 hora guardarEnCache($cacheKey, $resultado, 3600);
return $resultado;}2. Procesar en Lotes
Section titled “2. Procesar en Lotes”Para muchos proyectos, procesa de forma asíncrona:
<?phpfunction calcularMultiplesProyectos($proyectos){ $resultados = [];
foreach ($proyectos as $proyecto) { try { $resultado = calcularNomina($proyecto['requestData']); $resultados[$proyecto['id']] = $resultado;
// Pequeña pausa entre peticiones usleep(100000); // 0.1 segundos
} catch (Exception $e) { $resultados[$proyecto['id']] = ['error' => $e->getMessage()]; } }
return $resultados;}3. Validar Antes de Enviar
Section titled “3. Validar Antes de Enviar”Valida datos localmente antes de hacer la petición:
<?phpfunction validarSalarioMinimo($salario, $porcentajeJornada = 100){ $SMMLV_2025 = 1423500; $salarioMinimo = ($SMMLV_2025 * $porcentajeJornada) / 100;
if ($salario < $salarioMinimo) { throw new Exception( "El salario ($salario) es menor al SMMLV proporcional ($salarioMinimo)" ); }
return true;}
// Usotry { validarSalarioMinimo(1200000, 100); // Lanza excepción} catch (Exception $e) { echo "Error de validación: " . $e->getMessage(); // No hacer la petición al API}Siguiente: Respuestas y Errores
Section titled “Siguiente: Respuestas y Errores”En la siguiente sección encontrarás el detalle completo de las respuestas del endpoint y cómo manejar cada tipo de error.