All posts

Money

Razorpay is the source of truth. We are not.

Every payment bug you have ever read about is a variation of one mistake: believing the browser. Here are the three rules we wrote down before we took a single rupee.

Published
May 20, 2026
Author
Bolt 958
Read
5 min

The browser is not a witness. It is a rendering engine sitting on a stranger's laptop, and anything it tells you is a suggestion from someone you have never met.

This is obvious right up until you are three weeks into building a checkout, at which point it becomes extremely convenient to forget. The price is already in the frontend. Posting it back would save a query. Nobody would bother editing it.

Somebody would absolutely bother editing it.

Rule one: the client never names the price

When a guest books, their browser sends us what they want — this service, this slot. It does not send what it costs. It could not; we would not read it.

The price is calculated on our servers from the host's configuration, and that number is what goes to Razorpay. There is no code path where a number typed by a client becomes a number we charge. Not a validated one, not a checked one. The field does not exist.

This sounds paranoid for a platform with almost no traffic. It is much cheaper to be paranoid now than to discover, at scale, that ₹2,000 sessions have been quietly selling for ₹1.

Rule two: the payment is a snapshot

Prices change. Hosts raise rates, run offers, restructure services. All of that is normal, and all of it is a trap for anyone who stores a booking as a *pointer* to a price rather than a copy of one.

If a booking references the service's current price, then editing the service silently rewrites history. A session sold in May for ₹1,500 becomes a session that was apparently sold for ₹2,000, because the host raised their rate in July. Your records now disagree with the guest's bank statement, and the bank statement is going to win.

So a booking snapshots what was actually charged, at the moment it was charged. It is denormalised on purpose. The past does not get to change because the present did.

Rule three: verify the signature, not the redirect

This is the one that catches people, because the happy path works perfectly without it.

A payment completes and the user comes back to your site with a success parameter. It is right there. It says success. Marking the booking paid at that moment is a single line, and it works flawlessly in testing, and it means anyone who can construct a URL can buy anything you sell for free.

Razorpay signs its payment responses. We verify that signature server-side, with our secret, before a booking is worth anything. If the signature does not verify, the payment did not happen — regardless of what the URL, the browser, or the user says.

The rule underneath all three

When our records and the payment provider disagree, the payment provider is right. It has the money. We have an opinion.

And the webhook, because users close tabs

The redirect is a courtesy, not a guarantee. People pay and then close the tab, lose signal in a lift, or wander off. If the redirect is your only way of learning a payment succeeded, then a percentage of your paying customers simply never get what they paid for, and you will not find out from them — they will just leave.

So the webhook is the real notification, arriving server-to-server whether or not a human is still holding the phone. It is signed too, and verified the same way.

None of this is clever. All of it is the difference between a checkout and a hole.

Common questions

Should payment amounts be sent from the client?

Never. Calculate the price server-side from your own configuration and send that to the payment provider. A price the browser can name is a price a user can change.

Why verify the Razorpay signature server-side?

Because a success redirect is just a URL, and anyone can construct one. The signature is verified with your secret on your server; without that check, anything you sell can be bought for free.

Why snapshot the price on the booking?

So that changing a service price later does not rewrite what past bookings were charged. A booking that points at a live price makes your records disagree with the guest's bank statement.

Why handle webhooks if you already handle the redirect?

Users close tabs. The redirect only fires if a human stays on the page; the webhook arrives server-to-server regardless, so payments are never lost to a lift with no signal.

Want this for your own bookings?

Set up your page, sync your calendar, and start getting paid at 0% commission.

Become a host