Integrating Midtrans into a booking flow
How I added Indonesian payments to a surf-booking flow without tanking performance or over-engineering the stack.
When a Bali business wants to take bookings online, “just add Stripe” usually isn’t the answer — local guests pay with GoPay, OVO, bank transfer and QRIS. Midtrans is the pragmatic choice, and here’s how I wire it into an otherwise static, performance-first Astro site without dragging the whole build down.
The constraint
The site is static by default and scores 90+ on Lighthouse. A payment flow is inherently dynamic, so the trick is to keep the static parts static and only reach for a server when money is actually changing hands.
The shape of the integration
- Collect the booking details in a lightweight, vanilla-JS form — dates, package, guest info — with client-side validation. No framework runtime, no payment logic yet.
- Create the transaction server-side. A single serverless endpoint talks to Midtrans’s Snap API with the secret server key and returns a transaction token. The secret key never touches the client.
- Open Snap on the client with that token. Midtrans handles the actual payment UI, the local payment methods, and the 3-D-secure dance.
- Verify via webhook. Never trust the browser’s “success” callback alone — the source of truth is Midtrans’s server-to-server notification, verified with a signature hash before the booking is marked paid.
What I’d flag to a client
- Sandbox first. Midtrans’s sandbox mirrors production closely; test every payment method a real guest might use before going live.
- Idempotency matters. Webhooks can fire more than once — handle repeats so a guest is never double-charged or double-booked.
- Keep the fast path fast. Everything except the payment step stays static, so the performance budget that makes the site convert in the first place survives.
This is exactly the kind of feature that lives in the Booking / Custom tier — the rest of the site stays simple, and the complexity is contained to the one place that genuinely needs it.