All posts

January 11, 2026 · 5 min read

A Pre-Launch Checklist for Anything That Touches Payments

Most of what I write about applies to any app: headers, keys, database rules, login checks. Payments add a second layer on top of all that, because now there's a specific incentive for someone to poke at your app, not just curiosity. If your project charges a card, issues refunds, or applies a discount code, here's what I check that goes beyond the usual list.

Never trust a price that came from the browser

This is the single most common payment mistake I see in fast-built apps. Somewhere in the checkout flow, the price of an item gets sent from the frontend to the backend, because that's the easiest way to wire it up, and it works fine in every normal test. The problem is that anything sent from the browser can be changed by whoever is using the browser. Open dev tools, edit the request, change the price field from 49.00 to 0.49, and if the backend just trusts that number, it charges 0.49.

The fix is not complicated. The backend should look up the real price itself, from its own database or its own product catalog, every single time, and ignore whatever price the frontend claims. The frontend can display a price. It should never be allowed to set one.

Webhook signatures are not optional

If you use Stripe or a similar processor, it sends your server a notification when a payment succeeds, called a webhook. That notification comes with a signature that proves it actually came from the payment processor and not from someone who found your webhook URL and is pretending. A lot of AI-scaffolded integrations get the webhook endpoint working, see that it fires correctly during testing, and never actually verify the signature on incoming requests. Without that check, anyone who finds your webhook URL can send a fake 'payment succeeded' message and get treated as a paying customer for free.

Discount and coupon logic gets abused fast

Discount codes are exactly the kind of feature that looks done once it works for the one code you tested. Before you launch, check: can the same code be applied more than once to the same order. Can a discount push the price below zero, and if so what happens. Is there a limit on how many times a code can be used total, enforced on the server, not just shown as a counter in the UI. None of these are exotic attacks. They're the first three things anyone curious would try, free of charge, with nothing more than the checkout page open.

Refunds need the same server-side thinking

If your app lets a user or an admin trigger a refund, check who is actually allowed to call that action, and against which order. A refund endpoint that only checks 'is this person logged in' rather than 'does this order actually belong to this person' can let one customer refund someone else's payment, or refund the same order repeatedly if there's no check for that.

A short list before you take a real payment

  • Confirm every price, tax, and total is calculated server-side, never trusted from a request body
  • Confirm webhook signature verification is actually implemented, not just the endpoint that receives it
  • Try applying a discount code twice on the same order and see what happens
  • Try triggering a refund on an order that isn't yours, or isn't real, and see what happens
  • Check your payment processor's dashboard for test-mode keys still active anywhere in production

None of this needs a finance background. It needs the same habit as everything else on this blog: stop trusting that a feature works just because it worked the one time you clicked through it. Money is just the one category of bug where someone has an actual reason to go looking.

Related reading

Harbova is a security service for apps built with AI tools. Start with a free scan, and if it finds something serious, we can fix it and prove it is closed.