Short answer
To test a checkout flow for card payment, point the checkout at your processor's sandbox, submit the published test card numbers that produce a known result code, and check three things after each attempt: the screen the buyer sees, the order record your server writes, and the webhook your processor sends. You need to cover five states before you go live: approval, decline, authentication challenge, timeout, and refund. Sandbox cards move no real money, so you can run the same flow as many times as you need.
Card Checkout Verification Process
Prerequisites
- Sandbox or test API keys, kept separate from live keys
- A staging build of the checkout with request and response logging turned on
- Your processor's list of test card numbers and the result code each one triggers
- Access to the webhook event log and to your own order database
- A browser profile with no autofill data for card fields
Steps
- Load the staging checkout and confirm the payment form posts to the sandbox endpoint, not the live one. Check the network tab for the host name before you enter any card data.
- Add one item to the cart and advance to the payment step. Write down the cart total and the currency your app displays.
- Enter the generic success card number from the processor's test list, with a future expiry date and any three digit CVC.
- Submit the form and confirm the confirmation screen appears only after the processor returns an authorized status. A confirmation screen that renders before the response is a bug.
- Open the webhook log and match the event to the order. Confirm your server marked the order paid once, not twice.
- Repeat the flow with the generic decline card. Confirm the buyer sees a message tied to the card field, and confirm no paid order record was created.
- Run the other negative cards one at a time: insufficient funds, expired card, incorrect CVC, and processing error. Each one should map to its own message.
- Test authentication by using the card that requires a 3D Secure challenge. Walk both branches, the one where the buyer passes and the one where the buyer fails or closes the challenge window.
- Test the timeout path. Throttle the network or point the checkout at a mock endpoint that never responds, then confirm the form unlocks and the buyer can retry.
- Submit the same payment twice in a row with the same idempotency key. Confirm the processor charges once and your order table holds one record.
- Refund the payment in the sandbox, then refund a partial amount on a second order. Confirm the order state, the refund record, and the webhook all agree.
- Re-run the approval and decline steps on a mobile viewport at a narrow width to check that error text stays visible and the keyboard does not cover the submit button.
What to verify in each state
An approval must produce three consistent signals: an authorized response, a paid order, and a captured webhook event. A decline must produce a readable error, an unpaid order, and no webhook that marks the order paid. An authentication challenge must return the buyer to your page with the result attached to the same payment attempt. A timeout must leave the attempt open for retry rather than showing a success screen. A refund must reduce the captured amount and write its own event.
Failure cases worth a second pass
- Browser back button after a successful payment reopens the form with the card fields still filled
- Double click on the submit button creates two payment attempts
- Webhook arrives before the buyer returns to your confirmation page, so the page reads a stale order state
- Error message shows the raw processor code instead of a message the buyer can act on
- Test card data left in a log file or a database row in the staging environment