§ blog · Development06/26/2026
← All articles

Per-trip e-invoicing for taxi fleets: a real-time system architecture

Vietnam's Circular 32/2025/TT-BTC requires electronic invoices to be issued at the exact moment a trip ends. This article breaks down three real technical challenges and the event-driven architecture that solves them — from mechanical taximeters to digital signing and automated reconciliation.

DevelopmentIoTe-invoiceFintech8 min read
By KonexForge Engineering Team
NGUỒN SỰ KIỆNTaxi truyền thốngĐồng hồ + ESP32/4Gpulse → fare eventTaxi công nghệApp → Webhook APItrip_completed eventStore-and-forwardqueue khi mất 4GINVOICE PIPELINEEvent BrokerKafka / MQTT topicInvoice Builderbiển số + tuyến đườngTT32/2025/TT-BTCDigital SigningHSM / cloud certRetry + Idempotencytrip_id dedup keyĐẦU RACơ quan thuếHĐĐT khởi tạo từ MTT≤ 5s kể từ chuyến kết thúcGiao hóa đơnSMS / App / EmailPDF + XMLĐối soátLedger + daily reporttự động T+1TT 32/2025/TT-BTC · CV 6022/CT-CS · Biển số + tuyến đường · Thời điểm kết thúc chuyếncompliance envelopeEVENT-DRIVEN · REAL-TIME · OFFLINE-SAFEkonexforge.com

Since June 1, 2025, Circular 32/2025/TT-BTC (replacing Circular 78/2021) explicitly requires that electronic invoices for passenger transportation be issued at the moment each trip ends — not at day's end, not at shift's end. Official Dispatch 6022/CT-CS issued in December 2025 tightened this further: invoices must state the vehicle license plate and route, not just a generic "transportation fee." For large taxi fleets operating thousands of vehicles, this has shifted from a compliance concern to an engineering problem that must be solved correctly from the start.

Three real technical challenges

**First: mechanical taximeters have no API.** A traditional taximeter only knows how to count distance and calculate a fare — it has no API, no network connection. When a trip ends, the driver reads the display, collects cash, and the passenger leaves. No event is emitted for an invoice system to catch.

**Second: the amount paid often doesn't match the meter reading.** With app-based taxis, the displayed fare may have a voucher applied, a digital wallet cashback, or a corporate booking where a business and the passenger split the fare — one invoice won't cover both payers. With traditional taxis on corporate contracts, drivers may bill by the hour or a fixed route, not the meter.

**Third: 4G connectivity is not guaranteed at trip end.** Taxis pass through tunnels, suburban areas, and dead zones — the vehicle may have no connectivity at the exact moment a trip completes. The regulation does not permit "issue the invoice later"; the invoice must reference the trip's end time, though it's acceptable to transmit it to the tax authority once connectivity is restored, with the original timestamp.

The solution architecture: event-driven end to end

The key insight is to treat "trip ends" as an **event** — not as a synchronous transaction. All downstream processing (invoice creation, digital signing, tax authority submission, customer delivery) is pipelined and handled asynchronously, but with enough metadata attached to reconstruct anything needed later.

Event Ingestion Layer

  • **Traditional taxis**: attach an IoT module (ESP32 + 4G modem) to the taximeter's pulse output. When the driver taps "end trip," the module captures the pulse, reads the final fare from the meter's serial port (if supported), combines GPS data for the route, and publishes a `trip_completed` event to the message broker. If 4G is unavailable, the event is written to local flash memory and retried when connectivity returns — this **store-and-forward** pattern is standard for constrained IoT deployments.
  • **App-based taxis**: the app or dispatch server calls a webhook API when the trip ends. The payload includes: `trip_id`, `vehicle_plate`, `driver_id`, `start_location`, `end_location`, `fare_amount`, `payment_method`, `discount_applied`. Much simpler on the hardware side, but requires strict schema validation to prevent missing fields.

Invoice Pipeline

Events land on a Kafka topic (or MQTT broker for pure IoT architectures). A consumer service handles:

  • **Invoice Builder**: maps trip data to an e-invoice template conforming to Circular 32 — vehicle plate, route (pickup and drop-off addresses), trip end timestamp, 10% VAT. For multi-payer trips, the service splits the payload into multiple invoice objects before signing.
  • **Idempotency guard**: uses `trip_id` as a deduplication key. If the same `trip_id` arrives twice (a retry from a temporarily disconnected IoT module), only one invoice is created.
  • **Digital Signing**: sends the invoice payload to an HSM (Hardware Security Module) or a cloud signing service to attach an XML digital signature per the General Department of Taxation's standard.

Tax Authority Integration (MTT)

The signed invoice is submitted to the tax authority's system (MTT) via the API of a licensed e-invoice provider (VNPT, Viettel, or another certified provider). With the "at trip end" requirement, the target end-to-end latency from `trip_completed` event to tax authority confirmation should be under **30 seconds** — entirely achievable with an optimized pipeline.

Invoice Delivery and Reconciliation

Once the tax authority returns a confirmation code, the system delivers the invoice to the passenger via SMS/Zalo/Email (PDF + XML). In parallel, a reconciliation module compares the trip ledger against issued invoices nightly — automatically flagging any trips missing an invoice or with a failed invoice for manual follow-up.

Implementation notes

  • **Never make a synchronous API call inside the payment flow**: if the e-invoice system is slow or down, the entire payment flow blocks. Event-driven architecture solves this — the driver collects payment and ends the trip normally; invoice processing happens asynchronously in the background.
  • **Store-and-forward is mandatory, not optional**: the IoT module on the vehicle must have a local buffer large enough for at least 24 hours of trip data, plus retry logic with exponential backoff. When the vehicle returns to a depot with WiFi, the buffer flushes automatically.
  • **The timestamp must be trip end time, not invoice transmission time**: log `trip_end_time` on the IoT module or app before network connectivity is confirmed — this field is required for the invoice to be valid under Circular 32.
  • **Test against the tax authority sandbox before going live**: the General Department of Taxation provides a test environment for validating e-invoice schemas. Run the full pipeline through the sandbox and fix any schema errors before production.

Conclusion

Per-trip e-invoicing is not an added burden — it's an opportunity to standardize the operational data flow of a fleet. A properly implemented event-driven pipeline not only meets the tax compliance obligation but also gives fleet managers real-time visibility: revenue by vehicle, by driver, by route — instead of waiting for an end-of-day report. At KonexForge's Development layer, this is the type of Pilot Build we deliver in 6–8 weeks for taxi companies and corporate fleet operators.

Have a similar problem to solve?

Contact the team