public-transport / db-tickets

A library to retrieve ticket information from Deutsche Bahn
12 stars 2 forks source link

DB Navigator will be moved to DB Next Navigator and different endpoints probably #4

Closed arnebr closed 10 months ago

arnebr commented 1 year ago

Hi, just to be ready for the future the DB will move their DB Next Navigator to the normal Navigator. Source: DB Pressemeldung Then some of the endpoints will change, but I think they will leave the endpoint open for some time for legacy systems.

The new endpoint and response could be seen here: https://next.bahn.de/buchung/meine-reisen It will be devided then in two requests one authentication request, which will respond with a jwt access token to query the ticket endpoint. Ticket-Endpoint: https://next.bahn.de/web/api/buchung/auftrag/.

The response then will provide much more detailed data then now eg. invoice address, so would need to have redact to post it here

derhuerst commented 1 year ago

Thanks for reporting this so far in advance!

It will be devided then in two requests one authentication request, which will respond with a jwt access token to query the ticket endpoint.

Will there be anonymous authentication, as in "I'm a random computer retrieving a ticket"? Or will it always have to be tied to a user authenticating (e.g. via single sign-on)?

The response then will provide much more detailed data then now eg. invoice address, so would need to have redact to post it here

It would be great if you could post (a redacted version of) the response of the new ticket API here! This way, whoever has time and motivation to work on this can get started right away.

vkrause commented 1 year ago

The anonymous option has a captcha, so the account-based one might actually end up being more viable.

However, the old API is also used inside the web-based Komfort Check-In, so there is a chance of that staying around for a bit.

derhuerst commented 1 year ago

@vkrause In case you'll investigate or even implement the new API at some point in the future, please let me know! 🙌

arnebr commented 1 year ago

Auth Request:

POST /web/api/buchung/auftrag/authenticate HTTP/1.1
Host: next.bahn.de
X-Hcaptcha-Response: P1_ey..
Content-Type: application/json
Content-Length: 55

{"auftragsnummer":"123456789101","nachname":"Nachname"}

Auth Repsonse JWT Token

{
    "accessToken": "ey..."
}

Ticket Request using Auftragsnummer and Bearer Auth

GET /web/api/buchung/auftrag/123456789101 HTTP/1.1
Host: next.bahn.de
Authorization: Bearer ey..

The actual ticket response:


{
    "gesamtreiseId": "XX62045a-XXX-XXX-XXX-1326972XXX",
    "status": "ABGESCHLOSSEN",
    "anlagedatum": "2023-01-01T08:51:26Z",
    "email": "email@example.com",
    "hauptadresse": {
        "vorname": "Firstname",
        "nachname": "Lastname",
        "anrede": "HR",
        "email": "email@example.com",
        "adresse": {
            "land": "DEU",
            "ort": "Berlin",
            "plz": "10785",
            "strasse": "Potsdamer Platz 2"
        }
    },
    "gesamtangebot": {
        "hinfahrt": {
            "angebot": {
                "instanzId": "XX0200d5-XXX-XXX-XXX-0dax7a6aXXXX",
                "name": "Flexpreis",
                "konditionsAnzeigen": [
                    {
                        "anzeigeUeberschrift": "Freie Zugwahl",
                        "iconId": "201",
                        "prioritaet": 1,
                        "textKurz": "Freie Zugwahl",
                        "textLang": "Mit Ihrer ICE-Fahrkarte können Sie alle Züge nutzen."
                    },
                    {
                        "anzeigeUeberschrift": "Stornierung vor 1. Geltungstag kostenfrei",
                        "iconId": "201",
                        "prioritaet": 2,
                        "textKurz": "Stornierung vor 1. Geltungstag kostenfrei",
                        "textLang": "Sie können Ihre Fahrkarte bis einschließlich 01.01.2023 kostenfrei stornieren. Danach ist eine Stornierung gegen 19,00 € Entgelt möglich."
                    },
                    {
                        "kategorie": "PLUS_CITY",
                        "anzeigeUeberschrift": "City-Ticket",
                        "iconId": "201",
                        "prioritaet": 3,
                        "textKurz": "City-Ticket in Hamburg und Berlin inklusive",
                        "textLang": "Ihre Fahrkarte enthält ein City-Ticket in Hamburg, Großbereich Hamburg (Ringe A + B) und Berlin, Tarifbereiche A und B."
                    }
                ],
                "preis": {
                    "betrag": 46.25,
                    "waehrung": "EUR",
                    "mwst": [
                        {
                            "betrag": 3.03,
                            "brutto": 46.25,
                            "netto": 43.22,
                            "satz": 7,
                            "literal": "D"
                        }
                    ]
                },
                "klasse": "KLASSE_2"
            },
            "sitzplatzAngebote": [],
            "stellplatzAngebote": [],
            "hauptReisender": {
                "nachname": "Lastname",
                "vorname": "Firstname",
                "anrede": "HR"
            },
            "isKundenwunschStorniert": false,
            "isFahrtstatusEntwertet": false,
            "leistungsbuendelId": "XX0X0X0X",
            "isReiseVergangen": true,
            "upgradefaehigkeit": false,
            "kundenwunschId": "2ce916f6-xxxx-xxx-xxxx-61fba9421xxx",
            "isFahrtStorniert": false,
            "verbindung": {
                "tripId": "0x00xx0x_0",
                "ctxRecon": "¶HKI¶T$A=1@O=Pinneberg@L=8004819@a=128@$A=1@O=Hamburg-Altona@L=8002553@a=128@$202301080752$202301080804$NBE81759$$1$$$$$$§T$A=1@O=Hamburg-Altona@L=8002553@a=128@$A=1@O=Berlin Hbf (tief)@L=8098160@a=128@$202301080818$202305081020$ICE  507$$1$$$$$$¶KC¶#VE#2#CF#100#CA#0#CM#0#SICT#0#AM#395#AM2#0#RT#7#¶KRCC¶#VE#1#",
                "verbindungsAbschnitte": [
                    {
                        "risNotizen": [],
                        "himMeldungen": [],
                        "priorisierteMeldungen": [],
                        "abfahrtsZeitpunkt": "2023-01-08T07:52:00",
                        "abfahrtsOrt": "Pinneberg",
                        "abfahrtsOrtExtId": "8004819",
                        "abschnittsDauer": 720,
                        "abschnittsAnteil": 8.96,
                        "ankunftsZeitpunkt": "2023-01-08T08:04:00",
                        "ankunftsOrt": "Hamburg-Altona",
                        "ankunftsOrtExtId": "8002553",
                        "halte": [
                            {
                                "abfahrtsZeitpunkt": "2023-01-08T07:52:00",
                                "gleis": "5",
                                "name": "Pinneberg",
                                "risNotizen": [],
                                "himMeldungen": [],
                                "priorisierteMeldungen": []
                            },
                            {
                                "ankunftsZeitpunkt": "2023-01-08T08:04:00",
                                "gleis": "9",
                                "name": "Hamburg-Altona",
                                "risNotizen": [],
                                "himMeldungen": [],
                                "priorisierteMeldungen": []
                            }
                        ],
                        "verkehrsmittel": {
                            "produktGattung": "REGIONAL",
                            "kategorie": "DPN",
                            "name": "NBE81759",
                            "nummer": 81759,
                            "richtung": "Hamburg-Altona",
                            "typ": "PUBLICTRANSPORT",
                            "zugattribute": [
                                {
                                    "kategorie": "BEFÖRDERER",
                                    "key": "BEF",
                                    "value": "Nordbahn Eisenbahngesellschaft"
                                },
                                {
                                    "kategorie": "BARRIEREFREI",
                                    "key": "EA",
                                    "value": "Behindertengerechte Ausstattung"
                                },
                                {
                                    "kategorie": "FAHRRADMITNAHME",
                                    "key": "FB",
                                    "value": "Fahrradmitnahme begrenzt möglich"
                                },
                                {
                                    "kategorie": "INFORMATION",
                                    "key": "KL",
                                    "value": "Klimaanlage"
                                }
                            ],
                            "kurzText": "NBE",
                            "mittelText": "NBE RB71",
                            "langText": "NBE RB71 (81759) / NBE RB71 (83859)"
                        }
                    },
                    {
                        "risNotizen": [],
                        "himMeldungen": [],
                        "priorisierteMeldungen": [],
                        "abfahrtsZeitpunkt": "2023-01-08T08:18:00",
                        "abfahrtsOrt": "Hamburg-Altona",
                        "abfahrtsOrtExtId": "8002553",
                        "abschnittsDauer": 7320,
                        "abschnittsAnteil": 91.04,
                        "ankunftsZeitpunkt": "2023-01-08T10:20:00",
                        "ankunftsOrt": "Berlin Hbf (tief)",
                        "ankunftsOrtExtId": "8098160",
                        "halte": [
                            {
                                "abfahrtsZeitpunkt": "2023-01-08T08:18:00",
                                "gleis": "11",
                                "name": "Hamburg-Altona",
                                "risNotizen": [],
                                "himMeldungen": [],
                                "priorisierteMeldungen": []
                            },
                            {
                                "abfahrtsZeitpunkt": "2023-01-08T08:27:00",
                                "ankunftsZeitpunkt": "2023-01-08T08:26:00",
                                "gleis": "4",
                                "name": "Hamburg Dammtor",
                                "risNotizen": [],
                                "priorisierteMeldungen": [],
                                "himMeldungen": []
                            },
                            {
                                "abfahrtsZeitpunkt": "2023-01-08T08:34:00",
                                "ankunftsZeitpunkt": "2023-01-08T08:31:00",
                                "gleis": "8",
                                "name": "Hamburg Hbf",
                                "risNotizen": [],
                                "priorisierteMeldungen": [],
                                "himMeldungen": []
                            },
                            {
                                "abfahrtsZeitpunkt": "2023-01-08T10:10:00",
                                "ankunftsZeitpunkt": "2023-01-08T10:08:00",
                                "gleis": "5",
                                "name": "Berlin-Spandau",
                                "risNotizen": [],
                                "priorisierteMeldungen": [],
                                "himMeldungen": []
                            },
                            {
                                "ankunftsZeitpunkt": "2023-01-08T10:20:00",
                                "gleis": "1",
                                "name": "Berlin Hbf (tief)",
                                "risNotizen": [],
                                "himMeldungen": [],
                                "priorisierteMeldungen": []
                            }
                        ],
                        "verkehrsmittel": {
                            "produktGattung": "ICE",
                            "kategorie": "ICE",
                            "name": "ICE 507",
                            "nummer": 507,
                            "richtung": "Erfurt Hbf",
                            "typ": "PUBLICTRANSPORT",
                            "zugattribute": [
                                {
                                    "kategorie": "BEFÖRDERER",
                                    "key": "BEF",
                                    "value": "DB Fernverkehr AG"
                                },
                                {
                                    "kategorie": "BORDBISTRO",
                                    "key": "BR",
                                    "value": "Bordrestaurant"
                                },
                                {
                                    "kategorie": "FAHRRADMITNAHME",
                                    "key": "FR",
                                    "value": "Fahrradmitnahme reservierungspflichtig"
                                },
                                {
                                    "kategorie": "FAHRRADMITNAHME",
                                    "key": "FB",
                                    "value": "Fahrradmitnahme begrenzt möglich"
                                },
                                {
                                    "kategorie": "INFORMATION",
                                    "key": "CK",
                                    "value": "Sicher & kontaktlos ohne Ticketkontrolle reisen mit Komfort Check-in"
                                },
                                {
                                    "kategorie": "INFORMATION",
                                    "key": "EH",
                                    "value": "Fahrzeuggebundene Einstiegshilfe vorhanden"
                                },
                                {
                                    "kategorie": "INFORMATION",
                                    "key": "text.journeystop.product.or.direction.changes.journey.message",
                                    "value": "Verkehrt ab Berlin-Spandau als ICE 507 in Richtung München Hbf"
                                }
                            ],
                            "kurzText": "ICE",
                            "mittelText": "ICE 507",
                            "langText": "ICE 507"
                        }
                    }
                ],
                "umstiegsAnzahl": 1,
                "verbindungsDauerInSeconds": 8880,
                "ezVerbindungsDauerInSeconds": 8880,
                "isAlternativeVerbindung": false,
                "himMeldungen": [],
                "risNotizen": [],
                "priorisierteMeldungen": [],
                "reservierungsMeldungen": [],
                "isAlterseingabeErforderlich": false,
                "tripUUID": "8b4e6cfd-ef75-418d-xxx-d1fb63dc0000"
            },
            "reisende": [
                {
                    "typ": "ERWACHSENER",
                    "ermaessigungen": [
                        {
                            "klasse": "KLASSE_2",
                            "art": "BAHNCARD50"
                        }
                    ],
                    "anzahl": 1,
                    "alter": []
                }
            ],
            "isReservierungStorniert": false,
            "isStellplatzreservierungStorniert": false,
            "materialisierungsKanalNames": [
                "MOBILE",
                "WEB"
            ],
            "zeitlicheGueltigkeit": {
                "ersterGeltungszeitpunkt": "2023-01-07T22:00:00Z",
                "letzterGeltungszeitpunkt": "2023-01-10T01:00:00Z"
            },
            "isLastMinuteKontingentVerwendet": false
        },
        "leistungstyp": "REISEANGEBOT"
    },
    "privaterKundenkontobezug": true,
    "rechnungsausstellung": "RECHNUNG",
    "kundenprofilId": "003e5e1c-XXX-XXXX-XXXX-c48b2c1700000",
    "reisendeList": [
        {
            "typ": "ERWACHSENER",
            "alter": [],
            "anzahl": 1,
            "ermaessigungen": [
                {
                    "art": "BAHNCARD50",
                    "klasse": "KLASSE_2"
                }
            ]
        }
    ]
}
arnebr commented 1 year ago

I today booked a ticket on the next and it for the first time showed on the old navigator as well. It seems the merged the systems in die Background.And if you try to enter the booking number on the Bahn.de Website it already redirects to next.bahn.de for me

The endpoint is still https://fahrkarten.bahn.de/mobile/dbc/xs.go? and the format still the same.

arnebr commented 1 year ago

But the request has a new parameter

POST https://fahrkarten.bahn.de/mobile/dbc/xs.go
<?xml version="1.0"?><rqorderdetails version="1.0">'
    + '<rqheader  l="de" v="23040000" d="iPhone16.4.1" os="iOS_14.7" app="NAVIGATOR"/>'
    + '<rqorder on="00000000" kwid="NEU!"/><authname tln="Lastname"/></rqorderdetails>'

I´m unsure what the kwid does, if it is missing, it fails and if if set it to something random, I got

<error nr="30003" sev="error">
        <txt>Auftrag ist nicht DBCompanion-fähig</txt>
    </error>

I´ve tried different bookings, the kwid always changes for the every booking. But there is no other auth request at the moment so it seems it's generated in the client. `

What's more interesting if I enter and "old" booking code like X0X0X if fails with the error above and there I need to leave the parameter kwid out, for it to work.

arnebr commented 1 year ago

New update. I reversed engineered a little bit more. So maybe something new to implement for @vkrause or @derhuerst. I wrote about the kwid parameter. There is a call to get the parameter to a rqfindorder method:

POST https://fahrkarten.bahn.de/mobile/dbc/xs.go?
<?xml version="1.0"?>
<rqfindorder version="1.0"><rqheader tnr="xxx" ts="2023-08-11T11:36:51" l="de" v="23080000" d="xxx" os="xxx" app="NAVIGATOR"/><rqorder on="INT-UP-TO-12"/><authname tln="Lastname"/></rqfindorder>

Which answers with

<?xml version="1.0" encoding="UTF-8"?>
<rporderheadlist version="1.0">
    <rpheader tnr="xxx" ts="2023-08-11T11:41:31" />
    <orderheadlist>
        <orderhead kwid="f3978f1d-7309-46e3-96f5-0c108600000" ldt="2023-08-06T11:37:17" on="INT-UP-TO-12" />
    </orderheadlist>
</rporderheadlist>

With the kwid parameter we can now go back to the old rqorderdetails

<?xml version="1.0"?>

If you input a 6 letter code in the rqfindorder you will get a hkey back

<?xml version="1.0" encoding="UTF-8"?>
<rporderheadlist version="1.0">
    <rpheader tnr="xxx" ts="2023-08-11T12:48:41" />
    <orderheadlist>
        <orderhead hkey="randomMD5" ldt="2023-06-17T10:02:48" on="XXXXX" />
    </orderheadlist>
</rporderheadlist>

The hkey is not used on the following rqorderdetails request though

vkrause commented 1 year ago

With tickets booked today none of the above seems to work anymore (including DB's own web form). Could be that some of this is temporary fallout of the transition though.

arnebr commented 1 year ago

The website is working for me for a historical ticket. Didn‘t had the chance to test the api for now. What error do you get? The API is working for me as well. @vkrause which type of "auftragnummer" do you have, you need the rqfindorder request first since the booking number now is with the new format and needs the kid

vkrause commented 1 year ago

It's always some variation of "Auftragsnummer nicht gefunden", tickets from a few days ago still work here as well, with the API and the website.

I have a 12 digit "Auftragsnummer" and a 8 char alpha-numeric "Ticketcode", neither works. I also have the kwid ("Kundenwunsch ID" apparently?) obtained from when being logged in, API requests with that also don't work.

arnebr commented 1 year ago

Maybe due the v parameter in the call. A ticket booked on 3th of September works for me:


<?xml version="1.0"?><rqorderdetails version="2.0">'
    + '<rqheader  l="de" v="23040000" d="iPhone16.4.1" os="iOS_14.7" app="NAVIGATOR"/>'
    + '<rqorder on="XXXX" /><authname tln="Nachname"/></rqorderdetails>
vkrause commented 1 year ago

Yes, tickets up to September 4th work for me as well, only tickets booked starting on September 6th don't.

arnebr commented 1 year ago

I have a ticket booked today, with a Auftragsnummer and it works for me 😇 IMG_3677

vkrause commented 1 year ago

I have a ticket booked today, with a Auftragsnummer and it works for me 😇

Happy to hear that, so I guess I just have an outlier here and there's hope I can salvage most of my code relying on this :) I'll retest once I have a new ticket.

arnebr commented 1 year ago

It seems that the reason for failure is in the v parameter, when ich change it up to 23080000 it works, with 22060000 it does not! I will provide a pull request with a Auftragnummer-Bridge as well :)

arnebr commented 1 year ago

One hour later and here we go: #5 is up and waiting for a merge :) @vkrause maybe you could test if it works for your edge case as well

vkrause commented 10 months ago

I finally figured out why this was failing here, the passenger name is now case-sensitive, unlike before... I can reproduce your results now with my tickets as well.

arnebr commented 10 months ago

Great to hear 😃