Configuración SRI
Configuración SRI
Section titled “Configuración SRI”Dominio: https://test-api-factura.edw-dev.com
Dominio: https://api-financiero.e-dinky.com
Esta sección documenta los endpoints relacionados con la configuración del SRI (Servicio de Rentas Internas), incluyendo gestión de credenciales, validación de contraseñas y configuración de parámetros de facturación electrónica.
Actualizar Contraseña SRI Personal
Section titled “Actualizar Contraseña SRI Personal”Información General
Section titled “Información General”- Endpoint:
PUT /api/v1/companies/update-my-sri-password
- Método: PUT
- Autenticación: Bearer Token requerido
- Descripción: Actualiza la contraseña del SRI para el usuario autenticado
Headers Requeridos
Section titled “Headers Requeridos”Authorization: Bearer {token}Content-Type: application/jsonAccept: application/json
Parámetros del Request Body
Section titled “Parámetros del Request Body”Campo | Tipo | Requerido | Descripción |
---|---|---|---|
sri_password | string | Sí | Nueva contraseña del SRI |
confirm_password | string | Sí | Confirmación de la nueva contraseña |
current_password | string | No | Contraseña actual del usuario (para validación adicional) |
Ejemplo de Request
Section titled “Ejemplo de Request”{ "sri_password": "NuevaPassword123!", "confirm_password": "NuevaPassword123!", "current_password": "MiPasswordActual"}
Respuesta Exitosa (200 OK)
Section titled “Respuesta Exitosa (200 OK)”{ "message": "Contraseña SRI actualizada exitosamente", "status": "SUCCESS", "payload": { "user_id": 123, "sri_configured": true, "last_updated": "2024-01-15T14:30:00Z", "password_strength": "strong", "next_validation_required": "2024-04-15T14:30:00Z" }}
Respuesta de Error (422 Unprocessable Content)
Section titled “Respuesta de Error (422 Unprocessable Content)”{ "message": "Error de validación", "status": "ERROR", "payload": null, "error": { "sri_password": [ "La contraseña debe tener al menos 8 caracteres", "La contraseña debe contener al menos una mayúscula" ], "confirm_password": [ "Las contraseñas no coinciden" ] }}
Ejemplos de Código
Section titled “Ejemplos de Código”curl -X PUT \ {{apiFacEcDev}}/api/v1/companies/update-my-sri-password \ -H 'Accept: application/json' \ -H 'Authorization: Bearer {{bearerToken}}' \ -H 'Content-Type: application/json' \ -d '{ "sri_password": "NuevaPassword123!", "confirm_password": "NuevaPassword123!", "current_password": "MiPasswordActual"}'
use Illuminate\Support\Facades\Http;
$response = Http::withHeaders([ 'Authorization' => 'Bearer ' . $bearerToken, 'Accept' => 'application/json',])->put($apiUrl . '/api/v1/companies/update-my-sri-password', [ 'sri_password' => 'NuevaPassword123!', 'confirm_password' => 'NuevaPassword123!', 'current_password' => 'MiPasswordActual']);
$updateResult = $response->json();
const axios = require('axios');
const updateMySriPassword = async (passwordData) => { try { const response = await axios.put( `${apiUrl}/api/v1/companies/update-my-sri-password`, passwordData, { headers: { 'Authorization': `Bearer ${bearerToken}`, 'Content-Type': 'application/json', 'Accept': 'application/json' } } );
console.log('Contraseña SRI actualizada:', response.data); return response.data; } catch (error) { console.error('Error:', error.response.data); throw error; }};
Verificar Contraseña SRI Personal
Section titled “Verificar Contraseña SRI Personal”Información General
Section titled “Información General”- Endpoint:
POST /api/v1/companies/check-my-sri-password
- Método: POST
- Autenticación: Bearer Token requerido
- Descripción: Verifica la validez de la contraseña del SRI del usuario autenticado
Headers Requeridos
Section titled “Headers Requeridos”Authorization: Bearer {token}Content-Type: application/jsonAccept: application/json
Parámetros del Request Body
Section titled “Parámetros del Request Body”Campo | Tipo | Requerido | Descripción |
---|---|---|---|
sri_password | string | Sí | Contraseña del SRI a verificar |
validate_with_sri | boolean | No | Si debe validar directamente con el SRI (default: false) |
environment | string | No | Ambiente a validar: “production” o “test” (default: “production”) |
Ejemplo de Request
Section titled “Ejemplo de Request”{ "sri_password": "MiPasswordSRI123!", "validate_with_sri": true, "environment": "production"}
Respuesta Exitosa (200 OK)
Section titled “Respuesta Exitosa (200 OK)”{ "message": "Contraseña SRI verificada exitosamente", "status": "SUCCESS", "payload": { "is_valid": true, "sri_connection_status": "active", "last_validation": "2024-01-15T14:45:00Z", "environment": "production", "ruc": "1234567890001", "company_name": "Mi Empresa S.A.", "validation_details": { "password_format": "valid", "sri_response_time": "1.2s", "certificate_status": "active", "permissions": [ "facturacion_electronica", "comprobantes_retencion", "guias_remision" ] } }}
Respuesta de Error (401 Unauthorized)
Section titled “Respuesta de Error (401 Unauthorized)”{ "message": "Credenciales SRI inválidas", "status": "ERROR", "payload": null, "error": { "sri_password": [ "La contraseña del SRI es incorrecta" ], "sri_details": { "error_code": "INVALID_CREDENTIALS", "sri_message": "Usuario o contraseña incorrectos", "attempts_remaining": 2, "lockout_time": null } }}
Ejemplos de Código
Section titled “Ejemplos de Código”curl -X POST \ {{apiFacEcDev}}/api/v1/companies/check-my-sri-password \ -H 'Accept: application/json' \ -H 'Authorization: Bearer {{bearerToken}}' \ -H 'Content-Type: application/json' \ -d '{ "sri_password": "MiPasswordSRI123!", "validate_with_sri": true, "environment": "production"}'
use Illuminate\Support\Facades\Http;
$response = Http::withHeaders([ 'Authorization' => 'Bearer ' . $bearerToken, 'Accept' => 'application/json',])->post($apiUrl . '/api/v1/companies/check-my-sri-password', [ 'sri_password' => 'MiPasswordSRI123!', 'validate_with_sri' => true, 'environment' => 'production']);
$validationResult = $response->json();
const axios = require('axios');
const checkMySriPassword = async (passwordData) => { try { const response = await axios.post( `${apiUrl}/api/v1/companies/check-my-sri-password`, passwordData, { headers: { 'Authorization': `Bearer ${bearerToken}`, 'Content-Type': 'application/json', 'Accept': 'application/json' } } );
console.log('Verificación SRI:', response.data); return response.data; } catch (error) { console.error('Error:', error.response.data); throw error; }};
Actualizar Contraseña SRI de Empresa
Section titled “Actualizar Contraseña SRI de Empresa”Información General
Section titled “Información General”- Endpoint:
PUT /api/v1/companies/update-sri-password/:accountId
- Método: PUT
- Autenticación: Bearer Token requerido
- Descripción: Actualiza la contraseña del SRI para una empresa específica (requiere permisos de administrador)
Headers Requeridos
Section titled “Headers Requeridos”Authorization: Bearer {token}Content-Type: application/jsonAccept: application/json
Parámetros de URL
Section titled “Parámetros de URL”Parámetro | Tipo | Requerido | Descripción |
---|---|---|---|
accountId | string | Sí | ID de la cuenta empresarial |
Parámetros del Request Body
Section titled “Parámetros del Request Body”Campo | Tipo | Requerido | Descripción |
---|---|---|---|
sri_password | string | Sí | Nueva contraseña del SRI |
confirm_password | string | Sí | Confirmación de la nueva contraseña |
environment | string | No | Ambiente: “production” o “test” (default: “production”) |
validate_immediately | boolean | No | Validar inmediatamente con el SRI (default: true) |
reason | string | No | Motivo del cambio (para auditoría) |
Ejemplo de Request
Section titled “Ejemplo de Request”{ "sri_password": "NuevaPasswordEmpresa123!", "confirm_password": "NuevaPasswordEmpresa123!", "environment": "production", "validate_immediately": true, "reason": "Actualización de seguridad programada"}
Respuesta Exitosa (200 OK)
Section titled “Respuesta Exitosa (200 OK)”{ "message": "Contraseña SRI de empresa actualizada exitosamente", "status": "SUCCESS", "payload": { "account_id": "61247344", "company_name": "Mi Empresa S.A.", "ruc": "1234567890001", "sri_configured": true, "environment": "production", "last_updated": "2024-01-15T15:00:00Z", "updated_by": { "user_id": 456, "role": "administrator" }, "validation_result": { "is_valid": true, "sri_connection_status": "active", "certificate_status": "active", "permissions_verified": true } }}
Respuesta de Error (403 Forbidden)
Section titled “Respuesta de Error (403 Forbidden)”{ "message": "No tiene permisos para actualizar la configuración SRI de esta empresa", "status": "ERROR", "payload": null, "error": { "authorization": [ "Se requieren permisos de administrador para esta operación" ], "required_permissions": [ "companies.update_sri_config", "companies.manage_credentials" ] }}
Ejemplos de Código
Section titled “Ejemplos de Código”curl -X PUT \ {{apiFacEcDev}}/api/v1/companies/update-sri-password/61247344 \ -H 'Accept: application/json' \ -H 'Authorization: Bearer {{bearerToken}}' \ -H 'Content-Type: application/json' \ -d '{ "sri_password": "NuevaPasswordEmpresa123!", "confirm_password": "NuevaPasswordEmpresa123!", "environment": "production", "validate_immediately": true, "reason": "Actualización de seguridad programada"}'
use Illuminate\Support\Facades\Http;
$response = Http::withHeaders([ 'Authorization' => 'Bearer ' . $bearerToken, 'Accept' => 'application/json',])->put($apiUrl . '/api/v1/companies/update-sri-password/' . $accountId, [ 'sri_password' => 'NuevaPasswordEmpresa123!', 'confirm_password' => 'NuevaPasswordEmpresa123!', 'environment' => 'production', 'validate_immediately' => true, 'reason' => 'Actualización de seguridad programada']);
$updateResult = $response->json();
const axios = require('axios');
const updateCompanySriPassword = async (accountId, passwordData) => { try { const response = await axios.put( `${apiUrl}/api/v1/companies/update-sri-password/${accountId}`, passwordData, { headers: { 'Authorization': `Bearer ${bearerToken}`, 'Content-Type': 'application/json', 'Accept': 'application/json' } } );
console.log('Contraseña SRI de empresa actualizada:', response.data); return response.data; } catch (error) { console.error('Error:', error.response.data); throw error; }};
Validación y Seguridad
Section titled “Validación y Seguridad”Validación de Contraseñas SRI
Section titled “Validación de Contraseñas SRI”const validateSriPassword = (password) => { const validations = { minLength: password.length >= 8, hasUppercase: /[A-Z]/.test(password), hasLowercase: /[a-z]/.test(password), hasNumbers: /\d/.test(password), hasSpecialChars: /[!@#$%^&*(),.?":{}|<>]/.test(password), noCommonPatterns: !/(123456|password|qwerty|admin)/i.test(password) };
const errors = [];
if (!validations.minLength) { errors.push('La contraseña debe tener al menos 8 caracteres'); }
if (!validations.hasUppercase) { errors.push('La contraseña debe contener al menos una mayúscula'); }
if (!validations.hasLowercase) { errors.push('La contraseña debe contener al menos una minúscula'); }
if (!validations.hasNumbers) { errors.push('La contraseña debe contener al menos un número'); }
if (!validations.hasSpecialChars) { errors.push('La contraseña debe contener al menos un carácter especial'); }
if (!validations.noCommonPatterns) { errors.push('La contraseña no puede contener patrones comunes'); }
return { isValid: errors.length === 0, errors: errors, strength: calculatePasswordStrength(validations) };};
const calculatePasswordStrength = (validations) => { const score = Object.values(validations).filter(Boolean).length;
if (score <= 2) return 'weak'; if (score <= 4) return 'medium'; return 'strong';};
Gestión de Intentos Fallidos
Section titled “Gestión de Intentos Fallidos”class SriPasswordAttempts{ private const MAX_ATTEMPTS = 3; private const LOCKOUT_DURATION = 900; // 15 minutos
public function recordFailedAttempt($userId, $accountId = null) { $key = $this->getAttemptKey($userId, $accountId); $attempts = Cache::get($key, 0) + 1;
Cache::put($key, $attempts, self::LOCKOUT_DURATION);
if ($attempts >= self::MAX_ATTEMPTS) { $this->lockAccount($userId, $accountId);
// Notificar al administrador $this->notifySecurityTeam($userId, $accountId, $attempts); }
return [ 'attempts' => $attempts, 'remaining' => max(0, self::MAX_ATTEMPTS - $attempts), 'locked' => $attempts >= self::MAX_ATTEMPTS, 'lockout_expires' => $attempts >= self::MAX_ATTEMPTS ? now()->addSeconds(self::LOCKOUT_DURATION) : null ]; }
public function clearAttempts($userId, $accountId = null) { $key = $this->getAttemptKey($userId, $accountId); Cache::forget($key); $this->unlockAccount($userId, $accountId); }
private function getAttemptKey($userId, $accountId) { return "sri_password_attempts:{$userId}" . ($accountId ? ":{$accountId}" : ''); }}
Encriptación de Credenciales
Section titled “Encriptación de Credenciales”class SriCredentialManager{ public function encryptSriPassword($password, $accountId) { // Usar clave específica por cuenta para mayor seguridad $key = $this->generateAccountKey($accountId);
return encrypt($password, $key); }
public function decryptSriPassword($encryptedPassword, $accountId) { $key = $this->generateAccountKey($accountId);
try { return decrypt($encryptedPassword, $key); } catch (DecryptException $e) { Log::error("Error desencriptando contraseña SRI para cuenta {$accountId}: {$e->getMessage()}"); throw new SriCredentialException('Error al acceder a las credenciales SRI'); } }
private function generateAccountKey($accountId) { return hash('sha256', config('app.key') . $accountId . 'sri_salt'); }
public function rotateSriCredentials($accountId) { // Implementar rotación automática de credenciales $currentPassword = $this->getCurrentSriPassword($accountId);
// Generar nueva contraseña segura $newPassword = $this->generateSecurePassword();
// Actualizar en el SRI (si la API lo permite) $this->updateSriPassword($accountId, $currentPassword, $newPassword);
// Actualizar en nuestra base de datos $this->storeSriPassword($accountId, $newPassword);
return $newPassword; }}
Códigos de Respuesta
Section titled “Códigos de Respuesta”- 200 OK: Operación exitosa
- 400 Bad Request: Parámetros inválidos
- 401 Unauthorized: Token de autorización inválido o credenciales SRI incorrectas
- 403 Forbidden: Sin permisos para la operación
- 422 Unprocessable Entity: Error de validación
- 429 Too Many Requests: Demasiados intentos fallidos
- 500 Internal Server Error: Error interno del servidor
- 503 Service Unavailable: Servicio SRI no disponible
Mejores Prácticas
Section titled “Mejores Prácticas”🔐 Seguridad de Credenciales
Section titled “🔐 Seguridad de Credenciales”- Use encriptación fuerte para almacenar contraseñas
- Implemente rotación automática de credenciales
- Registre todos los accesos para auditoría
- Use autenticación de dos factores cuando sea posible
🚨 Gestión de Errores
Section titled “🚨 Gestión de Errores”- Implemente límites de intentos fallidos
- Use timeouts apropiados para conexiones SRI
- Registre errores para análisis posterior
- Implemente alertas para fallos críticos
⚡ Rendimiento
Section titled “⚡ Rendimiento”- Use caché para validaciones frecuentes
- Implemente conexiones persistentes al SRI
- Optimice timeouts según el ambiente
- Considere validaciones asíncronas
📊 Monitoreo
Section titled “📊 Monitoreo”- Monitoree disponibilidad del servicio SRI
- Registre métricas de tiempo de respuesta
- Implemente alertas para errores de conexión
- Mantenga estadísticas de uso
Casos de Uso Específicos
Section titled “Casos de Uso Específicos”🔄 Configuración Inicial de Empresa
Section titled “🔄 Configuración Inicial de Empresa”const setupCompanySriConfig = async (accountId, sriCredentials) => { try { // 1. Validar credenciales con el SRI const validationResult = await checkMySriPassword({ sri_password: sriCredentials.password, validate_with_sri: true, environment: sriCredentials.environment });
if (!validationResult.payload.is_valid) { throw new Error('Credenciales SRI inválidas'); }
// 2. Actualizar contraseña en el sistema const updateResult = await updateCompanySriPassword(accountId, { sri_password: sriCredentials.password, confirm_password: sriCredentials.password, environment: sriCredentials.environment, validate_immediately: true, reason: 'Configuración inicial de empresa' });
// 3. Configurar parámetros adicionales await configureAdditionalSriSettings(accountId, { auto_send_documents: true, retry_failed_documents: true, notification_email: sriCredentials.notificationEmail });
return { success: true, message: 'Configuración SRI completada exitosamente', data: updateResult };
} catch (error) { console.error('Error en configuración SRI:', error); throw error; }};
🔧 Diagnóstico de Conexión SRI
Section titled “🔧 Diagnóstico de Conexión SRI”class SriConnectionDiagnostic{ public function runDiagnostic($accountId) { $results = [ 'account_id' => $accountId, 'timestamp' => now(), 'tests' => [] ];
// Test 1: Verificar credenciales almacenadas $results['tests']['credentials'] = $this->testStoredCredentials($accountId);
// Test 2: Conectividad con SRI $results['tests']['connectivity'] = $this->testSriConnectivity();
// Test 3: Validación de certificados $results['tests']['certificates'] = $this->testCertificates($accountId);
// Test 4: Permisos de facturación $results['tests']['permissions'] = $this->testBillingPermissions($accountId);
// Test 5: Estado de establecimientos $results['tests']['establishments'] = $this->testEstablishments($accountId);
$results['overall_status'] = $this->calculateOverallStatus($results['tests']); $results['recommendations'] = $this->generateRecommendations($results['tests']);
return $results; }
private function testStoredCredentials($accountId) { try { $credentials = $this->credentialManager->getSriCredentials($accountId);
return [ 'status' => 'pass', 'message' => 'Credenciales encontradas y accesibles', 'details' => [ 'has_password' => !empty($credentials['password']), 'has_ruc' => !empty($credentials['ruc']), 'environment' => $credentials['environment'] ?? 'unknown', 'last_updated' => $credentials['updated_at'] ?? null ] ]; } catch (Exception $e) { return [ 'status' => 'fail', 'message' => 'Error accediendo a credenciales: ' . $e->getMessage(), 'details' => [] ]; } }}
Notas Importantes
Section titled “Notas Importantes”- Seguridad: Las contraseñas del SRI se almacenan encriptadas en la base de datos
- Validación: Se recomienda validar credenciales directamente con el SRI periódicamente
- Límites: Máximo 3 intentos fallidos antes del bloqueo temporal
- Ambientes: Soporte para ambientes de producción y pruebas del SRI
- Auditoría: Todos los cambios de credenciales quedan registrados
- Rotación: Se recomienda cambiar contraseñas cada 90 días
- Monitoreo: El sistema monitorea la conectividad con el SRI continuamente