Refactor: reorganización completa del proyecto y documentación consolidada

Esta actualización reorganiza el proyecto de reverse engineering de la API de ADIF con los siguientes cambios:

Estructura del proyecto:
- Movida documentación principal a carpeta docs/
- Consolidados archivos markdown redundantes en CLAUDE.md (contexto completo del proyecto)
- Organización de tests en carpeta tests/ con README explicativo
- APK renombrado de base.apk a adif.apk para mayor claridad

Archivos de código:
- Movidos adif_auth.py y adif_client.py a la raíz (antes en api_testing_scripts/)
- Eliminados scripts de testing obsoletos y scripts de Frida no utilizados
- Nuevos tests detallados: test_endpoints_detailed.py y test_onepaths_with_real_trains.py

Descubrimientos:
- Documentados nuevos hallazgos en docs/NEW_DISCOVERIES.md
- Actualización de onePaths funcionando con commercialNumber real (devuelve 200)
- Extraídos 1587 códigos de estación en station_codes.txt

Configuración:
- Actualizado .gitignore con mejores patrones para Python e IDEs
- Eliminados archivos temporales de depuración y logs
This commit is contained in:
2025-12-05 11:22:13 +01:00
parent aa02d7c896
commit 68fac80520
42 changed files with 66402 additions and 4876 deletions

160
tests/README.md Normal file
View File

@@ -0,0 +1,160 @@
# Tests - ADIF API
Scripts de prueba para validar la funcionalidad de la API de ADIF.
## 🧪 Tests Activos
### test_endpoints_detailed.py
Test exhaustivo de todos los endpoints con información de debug completa.
**Características**:
- Muestra status codes, headers y respuesta JSON
- Prueba múltiples variaciones de payload
- Identifica errores 400, 401 y sus causas
- Útil para debugging de nuevos endpoints
**Uso**:
```bash
python3 tests/test_endpoints_detailed.py
```
**Salida esperada**:
- Información detallada de cada petición
- Análisis de errores con mensajes del servidor
- Diferenciación entre errores de payload vs permisos
---
### test_onepaths_with_real_trains.py
Test funcional que obtiene trenes reales y prueba el endpoint `onepaths`.
**Características**:
- Consulta `departures` para obtener trenes circulando
- Extrae `commercialNumber`, `launchingDate`, códigos de estación
- Prueba `onepaths` con datos reales
- Valida que el endpoint funciona correctamente
**Uso**:
```bash
python3 tests/test_onepaths_with_real_trains.py
```
**Requisitos**:
- Ejecutar durante el día (cuando hay trenes circulando)
- Si se ejecuta de noche/madrugada puede no encontrar trenes
**Salida esperada**:
```
======================================================================
PASO 1: Obteniendo trenes reales de Madrid Atocha
======================================================================
✅ Obtenidos 25 trenes
======================================================================
PASO 2: Probando onePaths con trenes reales
======================================================================
✅ SUCCESS! onePaths funciona con datos reales
```
---
## 📁 Tests Archivados
La carpeta `archived/` contiene tests antiguos que fueron útiles durante el desarrollo pero ya no son necesarios:
- `test_all_endpoints.py` - Versión simple sin debug
- `test_complete_bodies.py` - Pruebas de payloads completos
- `test_corrected_api.py` / `test_corrected_api_v2.py` - Versiones anteriores
- `test_real_auth.py` - Tests de autenticación básicos
- `test_simple.py` - Test minimalista
- `test_with_auth_headers.py` - Validación de headers
- `test_without_auth.py` - Test sin autenticación
- `debug_auth.py` - Debug del algoritmo HMAC
Estos tests se mantienen por si son útiles como referencia, pero los tests activos son más completos.
---
## 🔧 Estructura de un Test
### Template Básico
```python
from adif_auth import AdifAuthenticator
import requests
import uuid
ACCESS_KEY = "and20210615"
SECRET_KEY = "Jthjtr946RTt"
def test_endpoint():
auth = AdifAuthenticator(access_key=ACCESS_KEY, secret_key=SECRET_KEY)
url = "https://circulacion.api.adif.es/portroyalmanager/secure/..."
payload = {
# Tu payload aquí
}
user_id = str(uuid.uuid4())
headers = auth.get_auth_headers("POST", url, payload, user_id=user_id)
headers["User-key"] = auth.USER_KEY_CIRCULATION
response = requests.post(url, json=payload, headers=headers, timeout=10)
assert response.status_code == 200
print(f"✅ Test passed: {response.json()}")
if __name__ == "__main__":
test_endpoint()
```
### Análisis de Status Codes
```python
if response.status_code == 200:
print("✅ SUCCESS - Endpoint funcional")
data = response.json()
elif response.status_code == 204:
print("⚠️ NO CONTENT - Autenticación correcta pero sin datos")
elif response.status_code == 400:
print("❌ BAD REQUEST - Payload incorrecto")
print(f"Error: {response.json()}")
elif response.status_code == 401:
print("❌ UNAUTHORIZED - Sin permisos")
print(f"Error: {response.json()}")
```
---
## 📊 Resultados Esperados
### Endpoints Funcionales (200)
- `/departures/traffictype/`
- `/arrivals/traffictype/`
- `/onepaths/` (con commercialNumber real)
- `/stationsobservations/`
### Endpoints Bloqueados (401)
- `/betweenstations/traffictype/`
- `/onestation/`
- `/severalpaths/`
- `/compositions/path/`
---
## 💡 Tips para Crear Nuevos Tests
1. **Usar `test_endpoints_detailed.py` como base** - Tiene buen manejo de errores
2. **Validar timestamps** - Usar milisegundos, no segundos
3. **Probar con datos reales** - Como hace `test_onepaths_with_real_trains.py`
4. **Diferenciar errores**:
- 400 = Payload incorrecto → Revisar campos
- 401 = Sin permisos → Las claves no tienen acceso
- 204 = Sin datos → Autenticación OK, pero respuesta vacía
---
**Última actualización**: 2025-12-05

View File

@@ -0,0 +1,180 @@
#!/usr/bin/env python3
"""
Test de endpoints de Adif con autenticación HMAC-SHA256
"""
import sys
from pathlib import Path
# Agregar raíz del proyecto al path para importar adif_auth
sys.path.insert(0, str(Path(__file__).parent.parent))
import requests
import json
from adif_auth import AdifAuthenticator
# Claves extraídas con Frida
ACCESS_KEY = "and20210615"
SECRET_KEY = "Jthjtr946RTt"
USER_ID = "0c8c32dce47f8512"
# Crear autenticador
auth = AdifAuthenticator(ACCESS_KEY, SECRET_KEY, USER_ID)
def test_departures():
"""Probar endpoint de salidas"""
print("\n" + "="*70)
print("TEST: Salidas de Madrid Atocha (Cercanías)")
print("="*70)
host = "circulacion.api.adif.es"
path = "/portroyalmanager/secure/circulationpaths/departures/traffictype/"
url = f"https://{host}{path}"
payload = {
"stationCode": "10200",
"commercialService": "BOTH",
"commercialStopType": "BOTH",
"page": {"pageNumber": 0},
"trafficType": "CERCANIAS"
}
payload_str = json.dumps(payload)
# Firmar petición
headers = auth.sign_request(
method="POST",
host=host,
path=path,
payload=payload_str
)
print(f"\nURL: {url}")
print(f"Payload: {payload_str}")
print(f"\nHeaders:")
for k, v in headers.items():
if k == "Authorization":
print(f" {k}: {v[:50]}...")
else:
print(f" {k}: {v}")
# Hacer petición
try:
response = requests.post(url, headers=headers, data=payload_str, timeout=10)
print(f"\nStatus Code: {response.status_code}")
if response.status_code == 200:
print("✅ SUCCESS!")
data = response.json()
print(f"\nRespuesta (preview):")
print(json.dumps(data, indent=2, ensure_ascii=False)[:1000])
else:
print(f"❌ ERROR")
print(f"Response: {response.text[:500]}")
except Exception as e:
print(f"❌ EXCEPTION: {e}")
def test_station_details():
"""Probar endpoint de detalles de estación"""
print("\n" + "="*70)
print("TEST: Detalles de estación Madrid Atocha")
print("="*70)
host = "estaciones.api.adif.es"
path = "/portroyalmanager/secure/stations/onestation/"
url = f"https://{host}{path}"
payload = {"stationCode": "10200"}
payload_str = json.dumps(payload)
headers = auth.sign_request(
method="POST",
host=host,
path=path,
payload=payload_str
)
print(f"\nURL: {url}")
print(f"Payload: {payload_str}")
try:
response = requests.post(url, headers=headers, data=payload_str, timeout=10)
print(f"\nStatus Code: {response.status_code}")
if response.status_code == 200:
print("✅ SUCCESS!")
data = response.json()
print(f"\nRespuesta (preview):")
print(json.dumps(data, indent=2, ensure_ascii=False)[:1000])
else:
print(f"❌ ERROR")
print(f"Response: {response.text[:500]}")
except Exception as e:
print(f"❌ EXCEPTION: {e}")
def test_arrivals():
"""Probar endpoint de llegadas"""
print("\n" + "="*70)
print("TEST: Llegadas a Madrid Atocha (Todos los tipos)")
print("="*70)
host = "circulacion.api.adif.es"
path = "/portroyalmanager/secure/circulationpaths/arrivals/traffictype/"
url = f"https://{host}{path}"
payload = {
"stationCode": "10200",
"commercialService": "BOTH",
"commercialStopType": "BOTH",
"page": {"pageNumber": 0},
"trafficType": "ALL"
}
payload_str = json.dumps(payload)
headers = auth.sign_request(
method="POST",
host=host,
path=path,
payload=payload_str
)
print(f"\nURL: {url}")
try:
response = requests.post(url, headers=headers, data=payload_str, timeout=10)
print(f"\nStatus Code: {response.status_code}")
if response.status_code == 200:
print("✅ SUCCESS!")
data = response.json()
print(f"\nRespuesta (preview):")
print(json.dumps(data, indent=2, ensure_ascii=False)[:800])
else:
print(f"❌ ERROR")
print(f"Response: {response.text[:500]}")
except Exception as e:
print(f"❌ EXCEPTION: {e}")
if __name__ == "__main__":
print("\n" + "="*70)
print("PRUEBAS DE API ADIF CON AUTENTICACIÓN HMAC-SHA256")
print("="*70)
print(f"\nUsando claves:")
print(f" ACCESS_KEY: {ACCESS_KEY}")
print(f" SECRET_KEY: {SECRET_KEY}")
print(f" USER_ID: {USER_ID}")
# Ejecutar tests
test_departures()
test_station_details()
test_arrivals()
print("\n" + "="*70)
print("TESTS COMPLETADOS")
print("="*70)

204
tests/test_endpoints.py Executable file
View File

@@ -0,0 +1,204 @@
#!/usr/bin/env python3
"""
Script para probar diferentes endpoints de la API de Adif
"""
import sys
from pathlib import Path
# Agregar raíz del proyecto al path para importar adif_auth
sys.path.insert(0, str(Path(__file__).parent.parent))
import requests
import json
from datetime import datetime
# Headers descubiertos
HEADERS_CIRCULATION = {
"Content-Type": "application/json;charset=utf-8",
"User-key": "f4ce9fbfa9d721e39b8984805901b5df"
}
HEADERS_STATIONS = {
"Content-Type": "application/json;charset=utf-8",
"User-key": "0d021447a2fd2ac64553674d5a0c1a6f"
}
HEADERS_AVISA = {
"Content-Type": "application/json;charset=utf-8",
"Authorization": "Basic YXZpc3RhX2NsaWVudF9hbmRyb2lkOjh5WzZKNyFmSjwhXypmYXE1NyNnOSohNElwa2MjWC1BTg=="
}
# URLs base
BASE_CIRCULATION = "https://circulacion.api.adif.es"
BASE_STATIONS = "https://estaciones.api.adif.es"
BASE_AVISA = "https://avisa.adif.es"
def test_endpoint(name, method, url, headers, data=None):
"""Probar un endpoint y mostrar resultado"""
print(f"\n{'='*60}")
print(f"TEST: {name}")
print(f"{'='*60}")
print(f"Method: {method}")
print(f"URL: {url}")
print(f"Headers: {json.dumps(headers, indent=2)}")
if data:
print(f"Body: {json.dumps(data, indent=2)}")
try:
if method == "GET":
response = requests.get(url, headers=headers, timeout=10)
elif method == "POST":
response = requests.post(url, headers=headers, json=data, timeout=10)
else:
print(f"❌ Método {method} no soportado")
return
print(f"\nStatus: {response.status_code}")
if response.status_code == 200:
print("✅ SUCCESS")
result = response.json()
print(f"\nResponse Preview:")
print(json.dumps(result, indent=2, ensure_ascii=False)[:1000] + "...")
else:
print(f"❌ ERROR")
print(f"Response: {response.text[:500]}")
except Exception as e:
print(f"❌ EXCEPTION: {str(e)}")
def main():
print("=" * 60)
print("PRUEBAS DE ENDPOINTS DE ADIF API")
print("=" * 60)
# Test 1: Obtener salidas con diferentes formatos de body
test_endpoint(
"Salidas - Formato Simple",
"POST",
f"{BASE_CIRCULATION}/portroyalmanager/secure/circulationpaths/departures/traffictype/",
HEADERS_CIRCULATION,
{
"stationCode": "10200",
"commercialService": "BOTH",
"commercialStopType": "BOTH",
"page": {"pageNumber": 0},
"trafficType": "CERCANIAS"
}
)
# Test 2: Probar con State YES
test_endpoint(
"Salidas - State YES",
"POST",
f"{BASE_CIRCULATION}/portroyalmanager/secure/circulationpaths/departures/traffictype/",
HEADERS_CIRCULATION,
{
"stationCode": "10200",
"commercialService": "YES",
"commercialStopType": "YES",
"page": {"pageNumber": 0},
"trafficType": "ALL"
}
)
# Test 3: Detalles de una ruta específica
test_endpoint(
"Detalles de Ruta",
"POST",
f"{BASE_CIRCULATION}/portroyalmanager/secure/circulationpathdetails/onepaths/",
HEADERS_CIRCULATION,
{
"commercialNumber": "C1",
"allControlPoints": False
}
)
# Test 4: Entre estaciones
test_endpoint(
"Entre Estaciones",
"POST",
f"{BASE_CIRCULATION}/portroyalmanager/secure/circulationpaths/betweenstations/traffictype/",
HEADERS_CIRCULATION,
{
"originStationCode": "10200",
"destinationStationCode": "10302",
"commercialService": "BOTH",
"commercialStopType": "BOTH",
"page": {"pageNumber": 0},
"trafficType": "ALL"
}
)
# Test 5: Detalles de estación
test_endpoint(
"Detalles de Estación",
"POST",
f"{BASE_STATIONS}/portroyalmanager/secure/stations/onestation/",
HEADERS_STATIONS,
{
"stationCode": "10200"
}
)
# Test 6: Observaciones de estación
test_endpoint(
"Observaciones de Estación",
"POST",
f"{BASE_STATIONS}/portroyalmanager/secure/stationsobservations/",
HEADERS_STATIONS,
{
"stationCode": "10200"
}
)
# Test 7: Composición de tren
test_endpoint(
"Composición de Tren",
"POST",
f"{BASE_CIRCULATION}/portroyalmanager/secure/circulationpaths/compositions/path/",
HEADERS_CIRCULATION,
{
"commercialNumber": "AVE 1001",
"originStationCode": "10200",
"destinationStationCode": "71801"
}
)
print("\n" + "="*60)
print("RESUMEN")
print("="*60)
print("""
Las pruebas han finalizado. Revisa los resultados arriba.
NOTAS:
- Algunos endpoints pueden requerir códigos/números válidos
- Los códigos de estación son numéricos (ej: 10200 para Madrid Atocha)
- Los números comerciales varían según el tipo de tren
- Algunos datos pueden no estar disponibles en tiempo real
CÓDIGOS DE ESTACIÓN COMUNES:
- 10200: Madrid Puerta de Atocha
- 10302: Madrid Chamartín
- 71801: Barcelona Sants
- 50000: Valencia Nord
- 11401: Sevilla Santa Justa
TIPOS DE TRÁFICO:
- CERCANIAS: Trenes de cercanías
- MEDIA_DISTANCIA: Media distancia
- LARGA_DISTANCIA: Larga distancia
- ALL: Todos los tipos
ESTADOS:
- YES: Solo servicios/paradas comerciales
- NOT: Sin servicios/paradas comerciales
- BOTH: Ambos tipos
""")
if __name__ == "__main__":
main()

View File

@@ -0,0 +1,182 @@
#!/usr/bin/env python3
"""
Prueba detallada de endpoints con mensajes de error completos
"""
import sys
from pathlib import Path
# Agregar raíz del proyecto al path para importar adif_auth
sys.path.insert(0, str(Path(__file__).parent.parent))
import requests
from adif_auth import AdifAuthenticator
import uuid
import json
from datetime import datetime, timedelta
import time
ACCESS_KEY = "and20210615"
SECRET_KEY = "Jthjtr946RTt"
def test_endpoint_detailed(name, url, payload, use_stations_key=False):
"""
Prueba un endpoint y muestra información detallada
"""
auth = AdifAuthenticator(access_key=ACCESS_KEY, secret_key=SECRET_KEY)
user_id = str(uuid.uuid4())
headers = auth.get_auth_headers("POST", url, payload, user_id=user_id)
if use_stations_key:
headers["User-key"] = auth.USER_KEY_STATIONS
else:
headers["User-key"] = auth.USER_KEY_CIRCULATION
print(f"\n{'='*70}")
print(f"Testing: {name}")
print(f"{'='*70}")
print(f"URL: {url}")
print(f"Payload: {json.dumps(payload, indent=2)}")
try:
response = requests.post(url, json=payload, headers=headers, timeout=10)
print(f"\nStatus Code: {response.status_code}")
print(f"Headers: {dict(response.headers)}")
try:
response_json = response.json()
print(f"Response Body: {json.dumps(response_json, indent=2, ensure_ascii=False)[:1000]}")
except:
print(f"Response Body (text): {response.text[:500]}")
if response.status_code == 200:
print("✅ SUCCESS")
return True
else:
print(f"❌ FAILED - Status {response.status_code}")
return False
except Exception as e:
print(f"❌ ERROR: {e}")
return False
# Obtener timestamps
now = datetime.now()
# Fecha actual al inicio del día en milisegundos
today_start = int(datetime(now.year, now.month, now.day).timestamp() * 1000)
# Fecha de mañana al inicio del día
tomorrow_start = int((datetime(now.year, now.month, now.day) + timedelta(days=1)).timestamp() * 1000)
print(f"Testing con fechas:")
print(f"Today (start): {today_start} = {datetime.fromtimestamp(today_start/1000)}")
print(f"Tomorrow (start): {tomorrow_start} = {datetime.fromtimestamp(tomorrow_start/1000)}")
# Test betweenStations (401)
test_endpoint_detailed(
"BetweenStations",
"https://circulacion.api.adif.es/portroyalmanager/secure/circulationpaths/betweenstations/traffictype/",
{
"commercialService": "BOTH",
"commercialStopType": "BOTH",
"originStationCode": "10200",
"destinationStationCode": "71801",
"page": {"pageNumber": 0},
"trafficType": "ALL"
}
)
# Test onePaths con variaciones (400)
print("\n\n" + "="*70)
print("TESTING ONEPATHS CON DIFERENTES VARIACIONES")
print("="*70)
# Variación 1: Con commercialNumber válido
test_endpoint_detailed(
"OnePaths - Con commercialNumber '03194'",
"https://circulacion.api.adif.es/portroyalmanager/secure/circulationpathdetails/onepaths/",
{
"allControlPoints": True,
"commercialNumber": "03194",
"destinationStationCode": "71801",
"launchingDate": today_start,
"originStationCode": "10200"
}
)
# Variación 2: Sin commercialNumber
test_endpoint_detailed(
"OnePaths - Sin commercialNumber (null)",
"https://circulacion.api.adif.es/portroyalmanager/secure/circulationpathdetails/onepaths/",
{
"allControlPoints": True,
"commercialNumber": None,
"destinationStationCode": "71801",
"launchingDate": today_start,
"originStationCode": "10200"
}
)
# Variación 3: Sin el campo commercialNumber completamente
test_endpoint_detailed(
"OnePaths - Sin campo commercialNumber",
"https://circulacion.api.adif.es/portroyalmanager/secure/circulationpathdetails/onepaths/",
{
"allControlPoints": True,
"destinationStationCode": "71801",
"launchingDate": today_start,
"originStationCode": "10200"
}
)
# Variación 4: Solo con originStationCode (sin destination)
test_endpoint_detailed(
"OnePaths - Solo originStationCode",
"https://circulacion.api.adif.es/portroyalmanager/secure/circulationpathdetails/onepaths/",
{
"allControlPoints": True,
"launchingDate": today_start,
"originStationCode": "10200"
}
)
# Variación 5: Estructura mínima
test_endpoint_detailed(
"OnePaths - Estructura mínima",
"https://circulacion.api.adif.es/portroyalmanager/secure/circulationpathdetails/onepaths/",
{
"commercialNumber": "03194",
"launchingDate": today_start
}
)
# Test OneStation con onestation (401)
test_endpoint_detailed(
"OneStation",
"https://estaciones.api.adif.es/portroyalmanager/secure/stations/onestation/",
{
"stationCode": "10200",
"detailedInfo": {
"extendedStationInfo": True,
"stationActivities": True,
"stationBanner": True,
"stationCommercialServices": True,
"stationInfo": True,
"stationServices": True,
"stationTransportServices": True
}
},
use_stations_key=True
)
# Variación: OneStation simple
test_endpoint_detailed(
"OneStation - Simple",
"https://estaciones.api.adif.es/portroyalmanager/secure/stations/onestation/",
{
"stationCode": "10200"
},
use_stations_key=True
)
print("\n" + "="*70)
print("PRUEBA COMPLETADA")
print("="*70)

View File

@@ -0,0 +1,126 @@
#!/usr/bin/env python3
"""
Primero obtenemos trenes reales de departures, y luego probamos onePaths con esos números
"""
import sys
from pathlib import Path
# Agregar raíz del proyecto al path para importar adif_auth
sys.path.insert(0, str(Path(__file__).parent.parent))
import requests
from adif_auth import AdifAuthenticator
import uuid
import json
from datetime import datetime
ACCESS_KEY = "and20210615"
SECRET_KEY = "Jthjtr946RTt"
auth = AdifAuthenticator(access_key=ACCESS_KEY, secret_key=SECRET_KEY)
# Paso 1: Obtener trenes reales de departures
print("="*70)
print("PASO 1: Obteniendo trenes reales de Madrid Atocha")
print("="*70)
url = "https://circulacion.api.adif.es/portroyalmanager/secure/circulationpaths/departures/traffictype/"
payload = {
"commercialService": "BOTH",
"commercialStopType": "BOTH",
"page": {"pageNumber": 0},
"stationCode": "10200", # Madrid Atocha
"trafficType": "AVLDMD" # Alta Velocidad
}
user_id = str(uuid.uuid4())
headers = auth.get_auth_headers("POST", url, payload, user_id=user_id)
headers["User-key"] = auth.USER_KEY_CIRCULATION
response = requests.post(url, json=payload, headers=headers, timeout=10)
if response.status_code != 200:
print(f"❌ Error obteniendo departures: {response.status_code}")
print(response.text)
exit(1)
data = response.json()
trains = data.get('circulations', [])
print(f"✅ Obtenidos {len(trains)} trenes\n")
# Mostrar los primeros 5 trenes
print("Primeros 5 trenes:")
for i, train in enumerate(trains[:5]):
commercial_number = train.get('commercialNumber')
destination = train.get('destination', {})
dest_name = destination.get('longName', 'Unknown')
origin = train.get('origin', {})
origin_name = origin.get('longName', 'Unknown')
planned_time = train.get('plannedTime', 'Unknown')
print(f"\n{i+1}. Tren {commercial_number}")
print(f" Origen: {origin_name}")
print(f" Destino: {dest_name}")
print(f" Hora salida: {planned_time}")
# Paso 2: Probar onePaths con trenes reales
print("\n" + "="*70)
print("PASO 2: Probando onePaths con trenes reales")
print("="*70)
for i, train in enumerate(trains[:3]): # Probar los primeros 3
commercial_number = train.get('commercialNumber')
destination = train.get('destination', {})
dest_code = destination.get('stationCode')
origin = train.get('origin', {})
origin_code = origin.get('stationCode')
# Obtener launchingDate del tren
planned_time_str = train.get('plannedTime', '')
# El plannedTime es algo como "08:30" - necesitamos convertirlo a timestamp
now = datetime.now()
today_start = int(datetime(now.year, now.month, now.day).timestamp() * 1000)
print(f"\n{'='*70}")
print(f"Test {i+1}: Tren {commercial_number}")
print(f"{'='*70}")
url_onepaths = "https://circulacion.api.adif.es/portroyalmanager/secure/circulationpathdetails/onepaths/"
payload_onepaths = {
"allControlPoints": True,
"commercialNumber": commercial_number,
"destinationStationCode": dest_code,
"launchingDate": today_start,
"originStationCode": origin_code
}
print(f"Payload: {json.dumps(payload_onepaths, indent=2)}")
user_id = str(uuid.uuid4())
headers = auth.get_auth_headers("POST", url_onepaths, payload_onepaths, user_id=user_id)
headers["User-key"] = auth.USER_KEY_CIRCULATION
response = requests.post(url_onepaths, json=payload_onepaths, headers=headers, timeout=10)
print(f"\nStatus: {response.status_code}")
if response.status_code == 200:
print("✅ SUCCESS!")
try:
data = response.json()
print(f"Response: {json.dumps(data, indent=2, ensure_ascii=False)[:2000]}")
except:
print(f"Response text: {response.text[:500]}")
elif response.status_code == 204:
print("⚠️ 204 No Content - Autenticación correcta pero sin datos")
else:
print(f"❌ FAILED - Status {response.status_code}")
try:
print(f"Error: {response.json()}")
except:
print(f"Response text: {response.text}")
print("\n" + "="*70)
print("PRUEBA COMPLETADA")
print("="*70)