21/04/2026
๐๐๐ซ๐ญ๐ข๐๐ฅ ๐๐๐ฒ๐ฆ๐๐ง๐ญ๐ฌ ๐๐๐ฎ๐ ๐ก๐ญ ๐๐ ๐ญ๐จ ๐๐ญ๐จ๐ฉ ๐๐ก๐ข๐ง๐ค๐ข๐ง๐ ๐ข๐ง ๐๐ข๐ง๐๐ซ๐ฒ
I kept approaching it like a simple yes or no. Either the payment went through or it didn't. But this booking system didn't work that way. Some users were paying partially upfront and settling the rest at the venue.
Some were booking slots, others full classes. The payment state wasn't a single moment it was a sequence, and Laravel had to hold that sequence together reliably across different booking types.
The webhook issue surfaced there.
A partial payment would come in, Stripe would confirm it, but our system was listening for a full capture signal that was never going to come at that stage. So the booking would sit in a pending state it shouldn't have been in.
Once I understood that, the fix became clear. We needed to handle authorized and captured states separately, and track how much had actually been paid against what was expected not just whether Stripe fired a success event.
The real shift wasn't technical. It was realizing that payment logic should reflect how the business actually works, not how we assumed payments behave.
Laravel gave us the structure. But the clarity had to come first.