DEV Community

Karina Egle
Karina Egle

Posted on

Checkout bugs that aren't actually bugs

When clients call saying "checkout is broken," it's usually not broken. It's a payment processing issue dressed up as a frontend problem. Learning to tell the difference saves a lot of wasted dev time.

The most common ones:

Card declines that look like failed form validation. A buyer enters their card, clicks pay, and gets a generic error. Your QA can't reproduce it because their test card always works. What's actually happening: the issuing bank is declining the charge, often for reasons that have nothing to do with your checkout — insufficient funds, cardholder-initiated fraud hold, cross-border risk rule. The processor returns a decline code; your UI flattens it to "something went wrong."

The fix isn't frontend. It's surfacing the real decline reason to the user (within what the processor lets you show) and offering a path — retry with a different card, switch to PayPal, try Apple Pay. A well-built checkout should degrade gracefully when any single payment method fails.

3DS friction. SCA regulations in Europe and parts of Asia require strong customer authentication on most ecommerce transactions. If you're not triggering 3DS correctly, issuers will decline. If you're triggering it on every transaction unnecessarily, you're adding checkout friction and losing conversions. The processor's API has flags — request exemption, attempt frictionless flow, force challenge — and getting these right is worth real money. US-centric teams building for European clients miss this constantly.

Webhook gaps. A buyer pays, the processor confirms the charge, but the order never moves from "pending" to "paid" in the database. Root cause is almost always webhook handling — a dropped event, a retry storm, a race condition where two webhooks update the same order out of order. The fix is idempotency keys, exponential backoff on retries, and a reconciliation job that runs every few hours and fixes anything the webhooks missed.

Refund and dispute flows that don't exist. A lot of ecommerce builds ship with a fully functional charge flow and zero handling of refunds, partial refunds, or chargebacks. Three months in, the client's CS team is doing everything manually in the processor dashboard, and the order status in your system is always wrong. Building the inverse flows at the start is ten times cheaper than retrofitting them.

Stored payment methods and SCA. If your client wants to support saved cards, subscriptions, or one-click reorders, you need to implement setup intents (or the equivalent) correctly. A common bug: cards get saved, then fail on the second charge because the initial intent wasn't configured for off-session use. This is a gotcha that only surfaces weeks after launch.

The through-line: most of these aren't really bugs. They're payment processing concepts the checkout UI needs to respect.

Top comments (0)