Chuck Wagon

Apparently, zero of the imagineers building this Disneyland Paris cafe conceived that “Chuck Wagon” sounds like what a cowboy would call a wheeled vomit trough. 😂

Faux Old-West building painted with lettering identifying it as the Chuck Wagon Cafe.

×

Contactless Transport in London vs Paris

Paris’s public transport tickets suck… for now!

In his blog post yesterday, Terence Eden observed that of all the cities he’s travelled to over the last year, Paris had the most-ridiculously-unhelpful public transport ticketing system:

Fuck Paris. The only way to buy a metro ticket is to download an app. Fair enough. But, after downloading the app it tells you to install another app!

Navigo app saying I have to install another app.

What the actual fuck? A convoluted, messy, and frustrating situation which has resulted in awful reviews for them.

Trains and metro travel require separate tickets at different prices. You can’t easily hop from one to another. You need to think carefully about the route you’re taking. A more convoluted route may be significantly cheaper because it doesn’t involve swapping between services.

This absolutely parallels my experience of hopping around the Paris’s metro area, last time I was there.

Dan, a white man with a ponytail and a goatee, site in a Parisian cafe sipping a glass of white wine.
If I’ve got to navigate my way through Paris’s public transport network… I’m going to need a drink first.

I was interested to hear, though, that by 2030 virtually all of Paris’s public transport will accept contactless payment, bringing its convenience level to a similar level to that of London. Cool.1

From the sounds of things, this is clearly designed as a convenience for visitors to the city, not regulars and locals:

Dès le 30 juin 2026, les touristes et les voyageurs hyperoccasionnels pourront opter pour valider leur titre en sortie de l’aéroport d’Orly sur la ligne 14 avec la carte bancaire.2

Paris’s relationship with tourists is different from London’s

But the bit that surprised me is Paris’s pricing for the parts they’ve deployed so far:

Les prix des titres de transport via les bornes d’achat sont les suivants :

  • Bus/tram/funiculaire : 2,55 € (soit + 0,50 € sur le prix classique) ;
  • Métro/train/RER : 3,35 € (soit + 0,80 € sur le prix classique) ;
  • Aéroports : 14,80 € (soit + 0,80 € sur le prix classique).

Buying transport tickets in Paris using a contactless card… costs 0.50 € to 0.80 € more. Paris will charge you for the convenience of tapping in and out with your carte bancaire.

A row of ticket gates in a London Underground station.
Tap in, tap out. Unless you’re eligible for discounted travel, you probably might as well use your debit card to get around London. Photo by Luca Sammarco.

Contactless is clearly more-convenient for city visitors, but I think the difference between London and Paris’s attitude to it says something about the relationship both cities have with their tourists. In London, most travellers can use whatever bank card and mobile wallet they’ve already got… and they’ll get as good a deal as possible. But in Paris, doing the same will invariably cost more than a conventional ticket would. You pay a convenience-tax.

Both cities get tens of millions of annual visitors and extract billions of euros worth of financial benefit from their tourist economies. Paris doing slightly better overall, but they’re closely-comparable enough that differences like this probably mean something.

Crowds file down the escalator into Charles de Gaulle-Étoile station.
Tap in, pay a premium for the privilege. Thanks, Paris! Photo by Candelario Benítez.

I’m not saying that London loves tourists and Paris hates them! It’s not so simple as that. But I think perhaps the cites try to present themselves in a different way.

London’s public transport says: we’ll work around you. You can learn the rules as you go; you don’t have to “learn London” to get around. Just use your usual contactless card wherever you go; we’ll work out the details, and your daily cost will get capped just the same as if you chose to pick up an Oyster card. Visiting the city as a tourist is an ordinary use-case for the transport network.

Paris’s public transport says: you should learn the rules. You’re welcome to visit, but you either need to do the work to be a “temporary Parisian”… or you can just use your usual contactless card but we’ll charge you a premium for the convenience. Visiting the city as a tourist is a special case that the transport network sees differently from being a local.

Neither approach is “wrong”… but I think it’s interesting. And now I’m wondering what the approach is like across other European cities.

Footnotes

1 I’ll almost-certainly have to tackle the current-generation of Paris’s public transport at some point before then, but I’ll look forward to the improved version once it rolls-out.

2 “From 30 June 2026, tourists and hyper-ocassional travellers will be able to pay by bank card on Line 14 out of Orly Airport.” Emphasis mine.

× × ×

The secret API I used to tell LeShuttle about different outbound and return passengers

I’ve got an upcoming trip to France: I’ll be driving there through the Channel Tunnel, via LeShuttle. But owing to a quirk in our family travel arrangements, we’ve have a slightly different set of passengers in the car for the outbound leg than for the return journey.

LeShuttle’s broken website

This is something that LeShuttle’s Advance Passenger Information registration form ought to be able to handle… but it very-much can’t.

Screenshot showing a web form with Dan Q and three other passengers on the outbound leg of a journey. Personal details appear to be blurred, but are actually spoofed AND blurred, per Dan's tradition. A 'Return passenger information is the same' checkbox is checked.
You’d think that to specify different passengers for the return leg, all I’d have to do is uncheck that checkbox, right? Wrong!

I was able to provide all of the personal and passport details of everybody on the outbound leg, but un-checking the “Return passenger information is the same” checkbox did… nothing. In fact, when saving the form and logging in again, the checkbox would be automatically re-checked.1

This is the point at which a normal person would either:

  1. Add the details of all passengers, both outbound and returning, to the form, and just hope they can sort out the confusion at the terminal, or,
  2. Try to get hold of a human Help Centre/Contact Us system (good luck!) who can sort it out.

Fortunately, I am not a normal person. I… am a software security engineer.

API reverse-engineering

My browser debug tools quickly indicated how this entire process works, and gave a clue as to what was broken in LeShuttle’s systems.

  1. When you log in, it makes a POST request to https://nextus-api-prod.leshuttle.com/b2c-api/GuestApi/Read?bookRef=...&surname=..., including your booking reference and surname (which acts as your password) in the relevant parameters.
  2. This returns all of your details in a JSON document. Prettified, and with all of the actual data replaced with explanatory comments, it looks something like this:
{
  "loginDetails": {
    /* credentials you used and other metadata */
  },
  "bookingDetails": {
    "outboundTravelDetails": {
      /* details about your outbound train and vehicle */
    },
    "returnTravelDetails": {
      /* details about your return train and vehicle */
    },
    "leadName": {
      /* details of the person who booked the trip */
    },
    "outboundPaxDetails": {
      /* For the outbound journey: */
      "paxLine": [
        /* First passenger: */
        {
          "paxDets": {
            /* - name, nationality, gender, DOB */
          },
          "docDets": {
            /* - passort number, expiry, issuing country */
          }
        },
        /* Second passenger: */
        {
          /* ... and so on .... */
        },
      ],
      /* Total number of passengers: */
      "noOfPax": "4"
    },
    "returnPaxDetails": {
      /* For the return journey: */
      "paxLine": [
        /* ... each passenger: same format as outbound... */
      ],
      /* Total number of passengers: */
      "noOfPax": "5"
    },
    "storedPaxDetails": {
      /* Pre-saved details? All blank for me */
    },
    /* More metadata */
  },
  "status": {
    /* Yet more metadata */
  },
  /* Even more metadata */
}
  1. Once you’ve made some changes, you press “Save”. This triggers a POST request to https://nextus-api-prod.leshuttle.com/b2c-api/GuestApi/Save with Content-Type: application/json and the entire JSON document from before, with your modifications, passed back.2

If you’re a programmer, you’re probably already making a guess as to what the underlying problem is. And you’re probably right:

  • The “Return passenger information is the same” checkbox value is not stored in the data that gets passed back and forth.
  • Instead, it’s derived by looking at the outbound and return passenger information. If it matches, it gets checked.
  • If it’s initially checked… the form doesn’t bother loading the UI that allows return passenger details to be modified.
  • But… this means that it never loads that UI:
    • the first time you visit the page the passenger list is empty both ways, which matches: anything you enter will necessarily be recorded into both the outbound and return fields, so
    • the next time you visit, it also matches… so it still doesn’t load the fields,
    • and so on.3

“Fixing” the problem

Knowing how the API worked, I was able to simply take the JSON document from the /Read endpoint, modify it so that the outboundPaxDetails and returnPaxDetails each contained the correct details for that leg of the journey (being sure also to update the total number of passengers noOfPax, which is for some reason a stored value rather than a derived one), and then submit it back via the /Save endpoint.

Having done this, I hit the /Read endpoint again to confirm that the data had, indeed, retained the data I submitted. When logging in again to the Web interface, I noticed that the checkbox now doesn’t automatically check itself. The correct data gets passed back and forth4.

Obviously LeShuttle need to fix their damn site. But at least – thanks to a little API reverse-engineering – I was able to submit the details they wanted from us.

Footnotes

1 Before anybody asks: yes, I tried all of the obvious things like using different browsers, clearing caches, disabling plugins, etc. I even had another passenger, using a different computer and operating system, give it a go. This one’s definitely a bug in LeShuttle’s systems.

2 I choose to assume that they’re doing some kind of server-side validation to ensure that a customer can’t, for example, modify details they’re not permitted to without a charge, such as which train they’re booked onto or the registration plate of the vehicle they’re bringing. But obviously I haven’t tested this, because it’s not among the information that I’m authorised to modify. Ethical hackers get permission before they poke at things they’re not sure whether they’re supposed to… especially if it’s a travel-related system and they’re somebody who has an unusual name that routinely gets them stopped and questioned at the UK border in general. 🤭

3 It occurs to me that possibly LeShuttle provide access to the relevant form only after the outbound journey has been made? Which would be a terrible design for the system and would represent terrible UI (why provide the checkbox if it doesn’t do anything?). I decided not to chance that this could be the expected approach, though, and just “fixed” the data up-front.

4 I haven’t tried modifying any of the outbound details to see if this re-breaks the return details. I suspect it would be fine, based on my analysis that the bug exists only in the front-end. But I can’t be sure without testing, and proper testing is something that LeShuttle’s own techies are getting paid to do. I don’t care enough about their website to do it for free!

×

Freedom of the Mountain

During a family holiday last week to the Three Valleys region of the French Alps for some skiing1, I came to see that I enjoy a privilege I call the freedom of the mountain.

In black skiwear, Dan looks into the camera from a bench in the snow, his skis upright behind him.
“Mornin’. Let’s go skiing.”

The Freedom

The freedom of the mountain is a privilege that comes from having the level of experience necessary to take on virtually any run a resort has to offer. It provides a handful of benefits denied to less-confident skiers:

  • I usually don’t feed to look at a map to plan my next route; whichever way I go will be fine!
  • When I reach one or more lifts, I can choose which to take based on the length of their queue, rather than considering their destinations.
  • When faced with a choice of pistes (or an off-piste route), my choice can be based on my mood, how crowded they are, etc., rather than their rated difficulty.
A snow-covered Alpine glacier sandwiched into a gully of exposed rocks.
Let’s tear this up, yo.

The downside is that I’m less well-equipped to consider the needs of others! Out skiing with Ruth one morning I suggested a route back into town that “felt easy” based on my previous runs, only to have her tell me that – according to the map – it probably wasn’t!

Approaching the Peak

The kids spent the week in lessons. It’s paying off: they’re both improving fast, and the eldest has got all the essentials down and it’s working on improving her parallel turns and on “reading the mountain”. It’s absolutely possible that the eldest, and perhaps both of them, will be a better skier than me someday2.

I’m not perfect, mind. While skiing backwards and filming, I misjudged the height of an arch and hit the back of the head with it… despite the child shouting to warn me! 😅

Maybe, as part of my effort to do what I’m bad at, I should have another go at learning to snowboard. I always found snowboarding frustrating because everything I needed to re-learn was something that I could already do much better and easier on skis. But perhaps if I can reframe that frustration through the lens of learning itself as the destination, I might be in a better place. One to consider for next time I hit the piste.

Footnotes

1 Also a little geocaching and some mountainside Where’s Wally?

2 Assuming snow is still a thing in ten years time.

× ×

Dan Q found GCADXC6 Tour de France

This checkin to GCADXC6 Tour de France reflects a geocaching.com log entry. See more of Dan's cache logs.

My very first “ski-o-cache” was 9 years ago, down in La Tania: this was my second! Found the host easily at the coordinates and found the cache in the third hiding place I tried. It’s quite stiff and hard to extract right now! Needed to wait to return it while some other skiers took pictures of one another at the GZ, but got there in the end. Salutations d’Oxford, en Angleterre. MPLC!

Dan, in a wintery mountainous landscape, poses for a selfie by a sculpture of a bicycle marking part of the route of the Tour de France.

×

Dan Q couldn’t find GC629TH EABDG : La vache qui tourne dans le Tour de France

This checkin to GC629TH EABDG : La vache qui tourne dans le Tour de France reflects a geocaching.com log entry. See more of Dan's cache logs.

Salutations d’Angleterre.

On a skiing holiday I took a day to go geocaching. Even with the hint, unable to find this cache: suspect it must be buried under ice and snow? If that’s possible, perhaps worth adding to the cache description or else removing the “winter” attribute? (Or maybe I just gave up too easily!)