-
Notifications
You must be signed in to change notification settings - Fork 6
API dell'app Trenitalia
Nota bene: in tutte le richieste presentate qui bisogna avere cura di sostituire AppVersion
con la versione dell'app che si sta usando e DeviceId
con un UUID univoco da utilizzare in tutte le richieste a partire dall'autenticazione.
Uno studio dettagliato sul processo di autenticazione può essere trovato nel post sul mio blog. Qui si riassume brevemente come procedere.
POST /Trenitalia50/apps/services/api/Trenitalia/android/init HTTP/1.1
Content-type: application/x-www-form-urlencoded; charset=UTF-8
x-wl-app-version: 5.0.1.0004
Host: gw71.mplat.trenitalia.it:444
{
"challenges": {
"wl_antiXSRFRealm": {
"WL-Instance-Id": "e81721e39345450298539c176d"
},
"wl_deviceNoProvisioningRealm": {
"token": "5f1aa92653944e668d1f79df88"
}
}
}
### Richiesta di autenticazione
POST /Trenitalia50/apps/services/api/Trenitalia/android/init HTTP/1.1
Content-type: application/x-www-form-urlencoded; charset=UTF-8
x-wl-app-version: 5.0.1.0004
Host: gw71.mplat.trenitalia.it:444
WL-Instance-Id: e81721e39345450298539c176d
Authorization: {"wl_deviceNoProvisioningRealm":{"ID":{"token":"5f1aa92653944e668d1f79df88","app":{"id":"Trenitalia","version":"5.0.1.0004"},"device":{"id":"8d593fde-ea26-4191-a487-23ac82a7c36c","os":"6.0.1","model":"Nexus 5","environment":"android"},"custom":{}}}}
Nota: preservare i cookie impostati durante la prima richiesta.
POST /Trenitalia50/apps/services/api/Trenitalia/android/init HTTP/1.1
Content-type: application/x-www-form-urlencoded; charset=UTF-8
x-wl-app-version: 5.0.1.0004
Host: gw71.mplat.trenitalia.it:444
WL-Instance-Id: e81721e39345450298539c176d
Nota: preservare i cookie impostati durante la prima richiesta.
Tutte le richieste dell'API sono POST al seguente endpoint:
https://gw71.mplat.trenitalia.it:444/Trenitalia50/apps/services/api/Trenitalia/android/query
Il corpo della richiesta richiede tre parametri: adapter
, procedure
e parameters
. Quest'ultimo è una stringa contenente dati in formato JSON. Le risposte sono file JSON puri o racchiusi in tag di tipo /*-secure-[payload]*/
con la seguente struttura:
{
"statusCode": 200,
"errors": [],
"isSuccessful": true,
"Envelope": {
"Body": {
"NOME_RISPOSTA": {
"Body": {
"CORPO_RISPOSTA"
}
"AdditionalInformation": {
"nil": "true"
}
}
},
"Header": {
"ResponseHeader": {
"MessageInfo": {
"nil": "true"
},
"mustUnderstand": "1",
"UnitOfWork": "101808532219417696"
}
}
},
"statusReason": "OK",
"responseHeaders": {
"Date": "Tue, 04 Sep 2018 15:56:23 GMT",
"Content-Length": "113306",
"Content-Type": "text\/xml; charset=utf-8",
"Server": "Microsoft-IIS\/7.5",
"X-Powered-By": "ASP.NET",
"x-SCR-APM": "09"
},
"warnings": [],
"responseTime": 211,
"totalTime": 215,
"info": []
}
La risposta in sé, quindi ciò che interessa, si trova in corrispondenza del placeholder "CORPO_RISPOSTA"
alla riga 9.
Le date sono in formato 1970-01-01T12:00:00+02:00
(nell'ordine: anno, mese, giorno, ora, minuto, secondo, offset rispetto a UTC in ore e minuti), oppure talvolta senza l'offset rispetto a UTC; tutte le durate sono in formato ISO 8601. Il valore null
in alcuni casi viene rappresentato come un dizionario {"nil": true}
. Molto spesso, ma non sempre, gli interi sono passati sotto forma di stringa. Prestate attenzione agli esempi.
-
adapter
:StationsAdapter
-
procedure
:GetStations
-
parameters
:
[
{
"UnitOfWork": 0,
"Language": "IT",
"Credentials": null,
"PlantId": "android",
"PointOfSaleId": 3,
"CredentialsAlias": null,
"AppVersion": "5.0.1",
"DeviceId": "8d593fde-ea26-4191-a487-23ac82a7c36c"
},
{
"GetStationsRequest": {
"Body": {
"Name": "milano"
}
}
},
{
"extractOnlyItalianStations": false
}
]
-
Name
è il nome (anche parziale) della stazione da cercare; -
extractOnlyItalianStations
determina se i risultati devono essere solo stazioni italiane o meno.
{
"StationDetail": [
{
"name": "Milano Affori",
"longitude": "9.165794",
"stationcode": "830025005",
"latitude": "45.518497",
"favorite": 0,
"railwaycode": "83",
"zoomlevel": 1
}
]
}
-
adapter
:SearchAndBuyAdapter
-
procedure
:SearchTravels
-
paramters
:
[
{
"UnitOfWork": 0,
"Language": "IT",
"Credentials": null,
"PlantId": "android",
"PointOfSaleId": 3,
"CredentialsAlias": null,
"AppVersion": "5.0.1",
"DeviceId": "8d593fde-ea26-4191-a487-23ac82a7c36c"
},
{
"SearchTravelsRequest": {
"Body": {
"PagingCriteria": {
"StartIndex": 0,
"EndIndex": 9,
"SortDirection": null
},
"OriginStationId": "830008409",
"DestinationStationId": "830000219",
"DepartureDateTimeRange": {
"Start": "2018-09-05T05:00:00+02:00",
"End": null
},
"ArrivalDateTimeRange": null,
"ReturnDateTimeRange": null,
"ArrivalReturnDateTimeRange": null,
"IsReturn": false,
"Passengers": {
"PassengerQuantity": [
{
"Type": "Adult",
"Quantity": 1
},
{
"Type": "Child",
"Quantity": 0
}
]
},
"FidelityCardCode": null,
"PostSaleCriteria": null,
"TrainType": "All",
"MaxNumberOfChanges": "99",
"CompatibleFares": {
"OutwardSelectedFare": {
"ServiceId": "30005"
}
}
}
}
}
]
-
StartIndex
eEndIndex
indicano la porzione di soluzioni da mostrare. La prima ha indice 0; -
OriginStationId
è il codice della stazione di partenza; -
DestinationStationId
è il codice della stazione di arrivo; -
DepartureDateTimeRange
indica l'intervallo di date di partenza per cui mostrare soluzioni. Il parametroEnd
è semprenull
e viene ignorato; -
ArrivalDateTimeRange
indica l'intervallo di date di arrivo per cui mostrare soluzioni. Valgono le stesse considerazioni fatte sopra; -
ReturnDateTimeRange
: comeDepartureDateTimeRange
ma per il viaggio di ritorno; -
ArrivalReturnDateTimeRange
: comeArrivalDateTimeRange
ma per il viaggio di ritorno; -
IsReturn
indica se si sta cercando il viaggio di ritorno (come parte di un viaggio andata e ritorno); -
PassengerQuantity
indica la quantità di ogni tipologia di passeggero (adulti e bambini); -
TrainType
indica il tipo di treno da cercare; può esserenull
per tutti i tipi di treno,Frecce
, oRegional
per cercare solo treni regionali; -
MaxNumberOfChanges
indica il massimo numero di cambi. Se non si imposta un limite, l'app invia il valore di default"99"
; -
CompatibleFares
è presente solo se si sta cercando il viaggio di ritorno. Contiene il codice della soluzione selezionata per il viaggio di andata in modo da mostrare solo soluzioni compatibili (a livello tariffario).
-
adapter
:TrainRealtimeInfoAdapter
-
procedure
:TrainRealtimeInfo
-
parameters
:
[
{
"UnitOfWork": 0,
"Language": "IT",
"Credentials": null,
"PlantId": "android",
"PointOfSaleId": 3,
"CredentialsAlias": null,
"AppVersion": "5.0.1",
"DeviceId": "8d593fde-ea26-4191-a487-23ac82a7c36c"
},
{
"TrainRealtimeInfoRequest": {
"Body": {
"Train": {
"Number": "9600",
"CategoryCode": null,
"CategoryName": null,
"Notifiable": null
},
"DepartureStationId": null,
"DepartureDate": null,
"ArrivalStationId": null
}
}
}
]
-
Number
è il numero del treno da cercare, come stringa; -
ArrivalStationId
è il codice della stazione di arrivo, facoltativo; -
DepartureStationId
è il codice della stazione di partenza, facoltativo; -
DepartureDate
è la data di partenza, facoltativa.
Gli altri parametri sembrano essere sempre ignorati.
{
"RealtimeTrainInfoWithStops": {
"ScheduledTrack": "9",
"Train": {
"CategoryCode": "FR",
"CategoryName": "FRECCIAROSSA",
"Number": "9600",
"Notifiable": true
},
"ActualTrack": "",
"DepartureStation": {
"Name": "ROMA TERMINI",
"Latitude": "41.900503",
"Longitude": "12.502027",
"Id": "8409"
},
"ScheduledArrival": "2018-09-05T10:05:00+02:00",
"LastReachedCheckPoint": "TORINO PORTA NUOVA",
"ScheduledDeparture": "2018-09-05T06:00:00+02:00",
"ScheduledDuration": "PT4H5M",
"Stops": {
"RealtimeTrainStop": [
{
"Station": {
"Name": "ROMA TERMINI",
"Latitude": "41.900503",
"Longitude": "12.502027",
"Id": "8409"
},
"Reached": true,
"StopType": "Departure",
"ActualInfo": {
"Departure": "2018-09-05T06:02:00+02:00",
"Arrival": {
"nil": true
},
"Track": ""
},
"ScheduledInfo": {
"Departure": "2018-09-05T06:00:00+02:00",
"Arrival": {
"nil": true
},
"Track": "9"
}
}
]
},
"ArrivalStation": {
"Name": "TORINO PORTA NUOVA",
"Latitude": "45.060971",
"Longitude": "7.677471",
"Id": "219"
},
"LastReachedCheckPointBase": {
"nil": true
},
"Delay": "PT12M",
"LastCheckPointTime": "2018-09-05T10:17:00",
"IsViaggiaTreno": true
}
}
- se la ricerca trova più di un treno,
RealtimeTrainInfoWithStops
identifica una lista con le informazioni di ogni treno; altrimenti identifica direttamente le informazioni dell'unico treno trovato (non una lista con un solo elemento); - se il treno non è valido o se è stato cancellato, il parametro generale
statusCode
è500
estatusReason
spiega il motivo dell'errore, tuttavia il codice di risposta HTTP è sempre200 OK
; - le fermate possono essere di quattro tipi
Departure
,Arrival
,Stop
,Transit
. L'ultimo caso indica che il treno non ferma nella località in questione, ma ci transita solamente. Le fermate di tipoTransit
normalmente sono nascoste nell'interfaccia dell'applicazione; - i dati mostrati sono, naturalmente, gli stessi di ViaggiaTreno. Si tratta di un sistema più affidabile, tuttavia le informazioni sono molto meno dettagliate.
Qui si trova una lista degli altri endpoint usati dall'applicazione, che non sono stati approfonditi perché poco utili o interessanti. I nomi sono abbastanza chiari e dovrebbero lasciar intuire a grandi linee il loro scopo.
/Trenitalia50/authorization/v1/clients/instance
/Trenitalia50/authorization/v1/authorization
/Trenitalia50/apps/services/api/Trenitalia/android/notifications
/Trenitalia50/apps/services/api/Trenitalia/android/login
/Trenitalia50/apps/services/api/Trenitalia/android/heartbeat
/Trenitalia50/apps/services/api/Trenitalia/android/friendlyname
/Trenitalia50/apps/services/configprofile
/Trenitalia50/apps/services/loguploader
/Trenitalia50/apps/services/j_security_check
/Trenitalia50/invoke