Search topics
Checkouts that take payment with no review or undo
A booking form charges a saved card the moment Pay is pressed, and the tickets can't be refunded, so a slip in the date or the number of tickets is paid for with nothing to check it before or undo it after.
The problem
People who slip when they type, tap or speak pay for tickets they didn't mean to buy, with no chance to see the mistake first or take it back after.
A theatre's booking page asks for two things: which performance, Friday 13 November or Saturday 14 November, and how many tickets, at $24 each. The visitor is signed in, so their card is saved. Under the fields, a line says tickets can't be refunded or exchanged, and a button says Pay now.
They want one ticket for Friday. On the way, their hand slips and the number goes up to 2. They press Pay now. The card is charged $48 at once, and the next page says "Booking confirmed", with no way to change it and no way to cancel. The mistake was there to see, but nothing showed it to them before it counted.
Success criterion 3.3.4, Error Prevention (Legal, Financial, Data), is level AA. When a page causes a legal commitment or a financial transaction, changes or deletes data people control, or submits their test answers, at least one of three things must be true. The submission can be reversed; the entries are checked for input errors and people can correct them; or there is a way to review, confirm and correct the information before it is final. This form does none of them.
For a purchase, W3C's sufficient techniques are a step to review and correct the answers before submitting (G98), a stated time within which the order can be changed or cancelled after it is placed (G164), and a checkbox to confirm, in addition to the submit button (G155). Checking entries is the second way in the criterion, but it covers input errors: a value missing, or outside what the form accepts. Two tickets and the wrong night are valid choices that no check can catch, and W3C lists client-side validation only as advisory for this criterion. Validation still matters for 3.3.1 and 3.3.3; it isn't the fix for a valid choice that was never meant.
The sentence about refunds doesn't help either. It tells people the mistake will be permanent; it doesn't give them a chance to find it.
The cost lands on the people least able to absorb it. A wrong booking for someone on a tight budget can mean going without, and asking for an exception means a phone call or an email, which are their own barriers.
5 of 10 groups affected
- No vision (affected)
- Low vision (affected)
- Colour vision (not affected)
- No hearing (not affected)
- Hard of hearing (not affected)
- No speech (not affected)
- Motor (affected)
- Reach, strength (affected)
- Cognitive (affected)
- Seizures (not affected)
- Limited reach and strength People with tremors press the + twice or tap the next date down, and the slip goes straight through to the charge.
- Limited manipulation Voice input can hear "two" for "to", and a switch can step one option past the one meant; without a read-back, people find out what the software chose from their bank statement.
- Limited language, cognitive and learning abilities People with memory, attention or reading difficulties, or with dyscalculia, may pick the wrong night or misread a total, and need to see it again, set out plainly, before it counts.
- Without vision Screen reader users hear the form one field at a time, so the date chosen several fields earlier is never read again before Pay now.
- Limited vision People who zoom in see a few fields at a time, so the date, the number of tickets and the Pay button are never on screen together.
Each field has a label, the button has a name, and the page passes every automated check. Whether an order can be reviewed or cancelled is spread over several pages and the server behind them, and a scanner never presses Pay on a live site. EaseWeb's audit flags forms that take a payment or place an order for a person to check, but it doesn't submit them, so it can't tell which of the three ways, if any, a site uses. A code assistant asked to "prevent errors" on this form adds min and max to the number field, which stops 0 and 99 tickets but not 2.
Try it
Book 1 ticket for Friday, but let your hand slip: set Tickets to 2. Then pay.
Does anything show you the slip before the money goes, or let you take it back after?
Broken Can you fix this?
The fix
Read the order back before the charge, or let people cancel it within a stated time.
- 1Never let one press place an order, take a payment or sign an agreement with no way to check it first or cancel it after.
- 2Read the choices back in words, with a way to change each one, or state how long people have to cancel.
- 3Name what the final button commits to, with the total.
<form method="post" action="/book"> <label for="night">Performance</label> <select id="night" name="night"> <option>Friday 13 November, 7:30 pm</option> <option>Saturday 14 November, 7:30 pm</option> </select> <label for="tickets">Tickets ($24 each)</label> <input id="tickets" name="tickets" type="number" value="1"> <p>Paid with your saved card ending 4242. Tickets can't be refunded or exchanged.</p> <button type="submit">Pay now</button></form>A step to check the booking before paying
<!-- Step 1: the same form, but Continue only saves the choices --><form method="post" action="/book/review"> <label for="night">Performance</label> <select id="night" name="night"> <option>Friday 13 November, 7:30 pm</option> <option>Saturday 14 November, 7:30 pm</option> </select> <label for="tickets">Tickets ($24 each)</label> <input id="tickets" name="tickets" type="number" value="1"> <p>Paid with your saved card ending 4242. Tickets can't be refunded or exchanged.</p> <button type="submit">Continue</button></form>Why this fix: Read the order back before it is final
The server charges the saved card and issues the tickets as soon as the form arrives. Nothing reads the choices back, nothing asks for confirmation, and nothing can be cancelled, so one press is final.
Continue saves the choices without charging anything, and the next page reads them back in words, with the total. Each Change link goes back to its field with every answer kept, so fixing the slip takes one change, not a new booking. Only "Confirm and pay $48" charges the card, and its name says how much. The heading and the page's title say which step this is, so screen reader users know they have arrived at the check, not at a confirmation.
All three pass 3.3.4. Use the review step: it stops the slip before any money moves, for every kind of order, and needs no refund process behind it. Add a cancel window as well when the business can take bookings back; it also catches mistakes people only notice later, such as a clash with another plan. Use the checkbox only on a one-page checkout that can't gain a step yet, and replace it with a review when you can.
Keep the choices on the server between the steps, in the booking session, not only in the page. Then the Back button, a Change link and a reload all come back with every answer in place, as checkout forms that ask for the same address twice explains.
On the review step, write each choice out in full and as people would say it: "Friday 13 November, 7:30 pm", not "13/11 19:30" or a seat code. Give the total, how it will be paid, and any condition that matters, such as no refunds, before the button.
A payment provider's hosted page often charges as soon as its own button is pressed. Put your review step before handing over, so the provider's page is the last step and says what it will take.
Some actions need the same care without money: deleting an account or a project, sending a signed form, submitting an exam. For a delete, a confirmation that says what will be lost, or an Undo right after, does the job; see confirmation dialogs that don't read out their question and toasts that vanish before you can read or undo them.
Don't disable the final button to prevent a second press. Make the server accept each order once, with a token in the form, so a double press books once and the button still works if the first press failed.
Fixing this with an AI coding assistant? Get this guide as Markdown, or get every guide in your coding agent.
Verify the fix
5 checks, no mouse.
Test with: Keyboard, Screen reader, Zoom, Touch
Record the OS, browser and assistive-technology versions, the build, the date, and the actual result of each step. Repeat after the checkout's steps or its payment provider change.
Limits
This is a starting pattern, not a guarantee for every process. The example is a ticket booking; shops, subscriptions, loans, applications and tests need the same check at the step that commits. 3.3.4 doesn't ask for a confirmation every time someone saves or edits their own data, only where a mistake would be costly or hard to undo. Test the complete process, including the emails it sends, with the people and tools your users rely on.
This is a recreated teaching example, not a finding about a named client. The code is a starting pattern: test it in your own product. No completed assistive-technology test is claimed here.
Keep this fixed as your code changes.
Turn guides like this into rules your coding agents and CI follow, then have the result retested with a keyboard and screen readers.