FleetbaseFleetbase
Back to blog
Blog articleJune 25, 20264 min read

GNU Taler in Fleetbase Ledger: Privacy-Preserving Wallet Payments

Fleetbase Ledger can now take payments through GNU Taler, the open, privacy-preserving payment system from the GNU project. You generate an invoice, present a taler://pay QR code, and the payer settles it from a Taler wallet — no card network, no account, no tracking of the payer. The invoice stays pending until the exchange confirms settlement, so your books only ever show money that actually moved. This work is funded through the NGI TALER fund (NLnet). Here's what's new. Written by Shiv Tha

Written byShiv Thakker
GNU Taler in Fleetbase Ledger: Privacy-Preserving Wallet Payments

Fleetbase Ledger can now take payments through GNU Taler, the open, privacy-preserving payment system from the GNU project. You generate an invoice, present a taler://pay QR code, and the payer settles it from a Taler wallet — no card network, no account, no tracking of the payer. The invoice stays pending until the exchange confirms settlement, so your books only ever show money that actually moved.

This work is funded through the NGI TALER fund (NLnet). Here's what's new.

Written by Shiv Thakker

A public Fleetbase invoice presenting a GNU Taler payment panel with a QR code and a taler://pay URI.

Why GNU Taler, and why it's different

Most payment integrations assume a card-and-redirect model: you send the customer to a hosted page, they pay, you get a webhook, done. GNU Taler works differently, and the driver had to respect that. Taler orders are claimed and then paid asynchronously through the payer's wallet, amounts use a value-and-fraction representation rather than a fixed two decimal places, and the wallet — not a hosted checkout page — is where the money actually moves. Building it properly meant getting the driver, the public invoice flow, and the multi-currency handling all aligned with how a real Taler exchange behaves.

To make that verifiable, we also stood up a complete Taler stack anyone can test against: a bank, a merchant backend, and an exchange.

Driver hardening and API correctness

The foundation is a Taler payment driver that behaves correctly against a real merchant backend and never double-charges. Orders are now created with a deterministic order_id generated per payment attempt, which guarantees idempotent order creation — Taler orders aren't idempotent unless you supply the ID yourself, so retries no longer risk creating duplicates. Before any of that runs, configuration is validated up front: the backend URL, merchant instance ID, token format and scope, supported currencies, and live connectivity are all checked when you save the gateway rather than failing mid-payment.

The driver also understands Taler properly. It parses the real order states — unpaid, claimed, paid, refunded, and wired — alongside KYC, legal-limit, and refund-deadline errors, and it handles bearer, secret-token, and scoped login tokens with expiry handling and admin diagnostics. Crucially, amount handling now uses Taler's value/fraction model instead of the old fixed two-decimal assumption that only ever fit EUR and USD.

GNU Taler payment gateway configured inside Fleetbase Ledger.
The GNU Taler gateway configured in Ledger — Sandbox, Active, with purchase, refund, webhooks, and sandbox capabilities and a registered webhook URL.

Public invoice checkout and wallet payment

On the front end, every online-capable driver now routes through a single PaymentService::charge() path that returns a normalized payload — payment_urlpayment_uriprovidergateway_transaction_id, and status — instead of the previous Stripe-only redirect. The public invoice UI understands Taler's taler://pay URI, not just a hosted checkout_url, redirects to the wallet, and then reflects pending, paid, or cancelled state when the payer returns.

Behind that, the purchase() implementation maps an invoice to a Taler order and contract terms, generating both a payment link and a QR code for wallet-based checkout. Currency configuration is aligned to the Taler exchange's supported currencies, and there's initial payment-status tracking for the asynchronous claim-and-pay flow, plus the first developer documentation.

The QR on a Taler invoice encodes a real pay URI that any Taler wallet can open:taler://pay/merchant.taler.fleetbase.io/instances/default/2026.175-02W0JHM6VC226/?c=MQ17AWBGFG70ZFCJYP95Z6T4Y8The full flow end to end: create the invoice, present the taler://pay QR, pay from the GNU Taler wallet against the test exchange, and land back on the invoice as it settles. Also hosted on Google Drive.

When the payment completes, the payer lands back on the invoice with confirmation, and the status only flips once the exchange confirms settlement — it's never optimistically marked paid.

A public invoice after payment showing a payment completed successfully message.
Back on the invoice after the wallet payment completes, with the success state shown on return.

Inside Ledger, the same invoice is denominated in KUDOS — a non-EUR/USD Taler currency that exercises the new value/fraction handling — with its linked Taler order and a live payment summary tracking total, amount paid, and balance due.

Ledger invoice detail in KUDOS currency with a linked Taler order and a payment summary.
The invoice in Ledger, billed in KUDOS, with its linked Taler order and payment summary.

Trying it yourself

The whole thing is reproducible against the public stack. Install Fleetbase 0.7.48 (or add the Ledger 0.0.6 extension to an existing instance), then configure a Taler gateway pointing at merchant.taler.fleetbase.io with a merchant instance and access token. The driver validates the URL, instance, token scope, currencies, and connectivity on save. Generate an invoice and you'll get a taler://pay link and QR; pay it from a Taler wallet funded via the test bank, settling against the test exchange. The invoice holds at pending through the claim-and-pay flow and flips to paid only on confirmed settlement, and repeated attempts reuse the same order_id.

What's included, and what's coming

GNU Taler support ships as part of Fleetbase 0.7.48, with Ledger at 0.0.6. It adds the Taler gateway driver and integration, invoice QR checkout, public invoice payment flow improvements, multi-currency value/fraction handling, currency lookup and formatting utility improvements, and local Taler testing utilities. There's more coming: full settlement and refund lifecycle handling, tenant-safe webhook provisioning, and an end-to-end sandbox with a public demo.

Upgrading

bash# Pull latest version
git pull origin main --no-rebase
# Update docker
docker compose pull
docker compose down && docker compose up -d
# Run deploy script
docker compose exec application bash -c "./deploy.sh"

As always, if you run into anything, join us on GitHub Discussions or drop by #fleetbase on Discord.

Ready to put these ideas into practice?

Explore the platform, docs, and open-source modules behind the workflows we write about on the Fleetbase blog.

Explore Fleetbase