Skip to content
Mehedi Hasan Sarkar
All case studies

Stripe manual capture for court booking payments

Stripe · Australia and SwedenIndependent Contractor, 2026 to present · Padel Mates, 2022 to 2024

Problem

On a court booking platform, charging the customer at the moment they book looks simple. But every change after that becomes a refund. A change can be a cancellation, a moved slot or a friend leaving a group booking. And refunds lead to disputes.

Stripe can also send the same webhook more than once. A webhook is a message Stripe sends to the server when a payment event happens. This is dangerous for payment logic. If the server handles the same event twice, it can confirm or refund a booking twice.

There is also the other side of the money. The platform collects payments on behalf of venues and clubs. So each one must receive its correct share, on time. It also needs a record it can check.

Solution

On the Australian platform, I designed a hold-first payment model with Stripe manual capture. The payment is authorised (the money is held) when the player books. It is captured (taken) later, based on the deadlines of the booking.

  1. Player books
  2. Card authorised, money held
  3. Booking deadline passes
  4. Captured: the booking takes placeReleased: the booking is cancelled
The card is charged only at the last step, when the booking is really going to happen.

Webhook processing uses a store of processed events, so the server handles every event exactly once. Every status change that involves money is applied atomically. This means it saves fully or not at all.

Customers see a cancellation preview before they cancel. The preview and the real cancellation use the same policy engine. So the refund a customer is promised is the refund they get. Group bookings can split the payment between players.

Venues receive their share through Stripe Connect destination charges, with a platform fee that can be configured. A payout workflow tracks what each venue is owed.

On the Swedish app, I built the mobile payment flows. They include 3D Secure for European cards, Apple Pay and Google Pay. I made sure a booking always ends in the right state after a payment succeeds, fails or is interrupted. I also built the automated club payout system end to end. It calculates each club's payout, generates receipts and sends them from an admin dashboard.

The trade-off. Manual capture has a cost. A card authorisation lasts only a few days. So a scheduled job captures each payment shortly before play. It captures earlier if the authorisation would expire first. For a booking made further ahead than that, the card is charged before the game. A later cancellation then becomes a refund again. The system works out the capture date at booking time. So the player is never promised a hold that the card cannot keep. I accepted this extra part of the system for a reason. Charging up front turned every cancellation into a refund, and every refund lost the processing fee.

Impact

  • Money is captured shortly before play instead of at booking, unless the card's authorisation would expire first.
  • The refund a customer sees before cancelling is the refund they receive.
  • A repeated webhook can no longer confirm or refund a booking twice.
  • Club payouts moved from manual work to a process the operations team runs and checks in one place.
  • The Swedish padel app that uses these payment flows has 100K+ downloads on Google Play.

Related case studies

Have a similar problem?

Tell me what is breaking or what you need built. I will reply with how I would approach it.

Let's talk