WIFI & CAPTIVE PORTALS WiFi Published 2020

Monaco Telecom

Yacht crews, port guests, and berth tenants at the port of Monaco book their WiFi access directly in the browser, pay by card via Ingenico β€” and receive credentials plus a PDF invoice by email, all in minutes and without a concierge desk.
Pattern WiFi platforms & captive portals
  • Java Spring Boot Backend
  • React Frontend
  • Ucopia WLAN Controller

THE STARTING POINT

The starting point

Yachts of various sizes lie at the port of Monaco year-round. With seasonality β€” from Grand Prix weekend to summer peak β€” WiFi demand swings between "quiet" and "massive". What shouldn't swing: the guest experience. Anyone wanting to buy a WiFi ticket wants to do it in the browser. Not at the harbour master's desk. Not tomorrow morning. Now, in their own language.

Before this, allocation was manual. Which didn't scale β€” especially during seasonal peaks, when the harbour master's desk has plenty to do anyway. It also didn't produce clean self-service data for accounting, tax, and customer-specific repeat purchases.

A standard captive portal solution with "free WiFi" isn't an option here β€” port WiFi is a paid service, with tariff tiers and VAT obligations.

WHAT WE BUILT

What we built

An end-to-end solution from tariff selection in the browser through to provisioning in the Ucopia WiFi controller, supported by a Java Spring Boot API, a React frontend, and consistently GDPR-aware data handling.

The order workflow in detail

  1. Tariff selection: the guest opens the SEPM refill page β€” via a registration link in the captive portal detail or directly by URL. The frontend shows the available tariff packages (hour / day / week / month).
  2. Registration: entering contact details + (optional) captcha validation against automated requests.
  3. Persistence: customer data goes into MariaDB; the payment process is initialised through the Ingenico Direct API.
  4. Ingenico Hosted Payment Page (four steps): select the payment method β†’ enter card details β†’ confirmation or rejection β†’ return to the refill page via a return URL.
  5. Confirm endpoint: the refill page calls /api/v1/sepm/confirm. In one orchestrated step:
    • reload customer data from MariaDB
    • generate account name and password
    • verify the payment status finally with the Ingenico API
    • allocate the next invoice number
    • load tariff details from the configuration file mt-packages.yml
    • create or refill the account via the Ucopia Deleg API (depending on the chosen refill mode)
    • send a credentials email to the guest
    • generate a PDF invoice and send a second email
    • apply the GDPR strategy to the customer record (see below)
    • send a status email to the SEPM operator
  6. Confirmation page: display the credentials in the browser. Reload behaviour is cleanly idempotent β€” anyone reloading the page gets the confirmation, not a second booking.

The API exposes three public endpoints (packages, checkout, confirm) plus internal endpoints for status monitoring and customer management β€” including a deleteexpired endpoint typically called by a cron job daily.

Three refill modes for the Ucopia controller

Ucopia knows three ways of giving an account identity new validity β€” we covered all three, because different port contexts have different requirements:

Refill mode How Strengths Weaknesses
profile Validity via profile simple not very flexible, not cumulative
account Set directly on creation flexible, simple not cumulative
voucher Validity via voucher natively cumulative voucher packages must be maintained

Default mode is account β€” fits most port scenarios (easy to maintain, sufficiently flexible). voucher is recommended for scenarios where guests want to buy more during an active validity period (cumulative).

Customer data under GDPR governance

MariaDB holds customer data only as long as it's actually needed β€” and the operator decides per lifecycle phase how the data is handled. Three configurable strategies are available:

  1. Keep β€” data stays, repeat customers are recognised, statistics are usable
  2. Anonymise β€” data is anonymised, only statistical analysis remains possible
  3. Delete β€” data is deleted, no more reload of the confirmation page

The choice sits with the SEPM operator, not in the code. A configuration entry, not a migration script.

Twelve service configuration fields that make a difference

The API's mt-settings.yml controls behaviour at a level of detail that's the difference between "works in the standard case" and "works in edge cases too":

  • Language: multilingual frontend (DE / EN / FR β€” the latter being a regional necessity in the MonΓ©gasque context)
  • Tariff logic: packages in mt-packages.yml, with profile or voucher mapping
  • Email templates: credentials, invoice, status β€” per language
  • Invoice PDF templates: SEPM branding, VAT reporting, sequential numbering
  • Ingenico authentication mode: SALE or other β€” direct pass-through to the payment provider
  • Ucopia connection: Deleg API endpoint, credentials, connection pool

Container-first with Kubernetes scaling

Backend and frontend are packaged separately in Docker and orchestrated via Kubernetes / OpenShift. The seasonality argument isn't academic here: during Grand Prix weeks or summer peaks, the API pods scale elastically β€” outside the season, the system runs on a minimal footprint. No hardware investment for the peak, no idle hardware in the off-season.

WHAT IT GIVES THEM

What it gives them

  • The concierge desk becomes self-service. The harbour master can focus on what they're actually there for.
  • Multilingual without friction. International clientele β€” French, English, Italian, German β€” gets the order process in their own language.
  • Seasonal peaks are absorbed via K8s scaling. No reserve hardware, no performance breakdown.
  • GDPR compliance is configuration, not codebase intervention. Operator chooses keep/anonymise/delete depending on the use case.
  • Three refill modes cover different business models β€” port tariffs aren't the same everywhere.
  • Confirmation reload idempotency prevents double bookings and double charges β€” structurally, not "by being careful".

WHAT WE DELIBERATELY DID NOT AUTOMATE

What we deliberately did not automate

  • We don't operate the Ucopia WiFi controller. Monaco Telecom does that themselves as operator.
  • We don't process our own identity beyond the payment data. Anyone paying with a valid card gets access. Done.
  • We don't run our own customer care. Customer queries go to Monaco Telecom. We provide status emails and API status endpoints for the internal operations teams.
  • We don't choose which tariffs are currently available. That sits in mt-packages.yml, maintained by the operator.

WHY THIS PATTERN TRANSFERS

Why this pattern transfers

The setup works wherever public WiFi is offered as a paid service element and the captive portal operator needs a self-service solution with real depth in payment, accounting, and compliance β€” marinas, ports, airports, trade fairs, festivals, co-working spaces, hospitality chains, stadiums, tourist hubs, bus and train stations.

The pattern: branded captive portal with multilingual support β†’ tariff and voucher logic β†’ payment integration via Ingenico (or Saferpay / Stripe / similar) β†’ connection to a Ucopia controller via the Deleg API β†’ MariaDB as a minimal data holder under GDPR configuration β†’ container deployment via K8s with elastic seasonal scaling.

The SEPM solution has been in production since 2021. The pattern has since been reused multiple times in variations β€” different payment providers, different languages, different port and transport contexts.

Talk to us

Two doors, one address.

Specific bottleneck?

Let us talk for 30 minutes about your use case.

No obligation, no cost, with concrete next steps at the end.

Book a 30-minute call

Your own AI platform?

See CompanyWizard live in action.

Demo with your own data is possible. We bring the pseudonymisation set up and ready.

Request a demo