FinalYearKitFinalYearKit
All posts
Viva Prep14 min read·

Razorpay MERN ecommerce viva — payment verification and order flow

HMAC signature verification, test-mode keys, order state after payment, and catalogue admin — the ecommerce payment story examiners grill hardest.

R

Rajan

Founder & kit engineer

Payment integration is high risk in vivas — either you explain HMAC verification clearly, or the panel assumes you pasted a tutorial. Razorpay returns order_id, payment_id, and signature to the client; your server must verify the signature before marking an order paid. Never update order status from a client callback alone. That single rule is the difference between a defensible ecommerce project and a demo that collapses under one question.

This post is a viva-oriented walkthrough of checkout, verification, test mode, cart architecture, admin flows, and the questions Indian B.Tech / BCA / MCA panels actually ask. Use it with the MERN ecommerce kit. For stack-choice context when someone asks “why not an AI project?”, keep AI vs MERN for final year handy. Compare payment complexity with a non-payment MERN system like library management when the examiner asks what made ecommerce harder.

Why payments scare students (and how to stay calm)

Razorpay looks like “just open a modal.” The academic substance is trust boundaries: the browser is hostile; amounts and paid flags must be decided on the server; secrets stay in environment variables; test keys never become live keys in a submitted zip. If you can narrate that boundary while the modal runs, you sound like an engineer, not a UI clicker.

What “good” looks like in five minutes

Add a product to cart → checkout → server creates Razorpay order → modal opens with test keys → success → client POSTs ids + signature → server verifies → order history shows paid. Optionally fail once with a test failure card and show the order stays pending. That failure path is memorable and honest.

Checkout flow end to end

1. Cart to order intent

User reviews cart. Client sends product ids and quantities only — not a final price the client invented. Server loads products from MongoDB, recomputes line totals and grand total in paise, and creates an Order document in pending (or equivalent) with a price snapshot of each line item.

2. Create Razorpay order on the server

Server calls Razorpay with the computed amount (paise), currency INR, and a receipt/reference tied to your Order _id. Store the Razorpay order_id on your Order. Return to the client: Razorpay key_id (public), order_id, amount, and any prefill fields you allow.

3. Client opens checkout

Razorpay Checkout modal uses key_id + order_id. User pays with test UPI/card. On success, Razorpay gives the client payment_id, order_id, and signature.

4. Verify on your API

Client POSTs those three values (plus your internal order id if needed) to /api/payments/verify (name yours consistently). Server recomputes expected signature and only then sets order paid, decrements stock if not already reserved, and returns confirmation.

5. Show history

Order history page reads from MongoDB — not from Razorpay as source of truth for your UI. Razorpay is the payment rail; your Order collection is the business record.

HMAC verification (draw this on the board)

The formula

Expected signature = HMAC-SHA256 of order_id + "|" + payment_id using your key secret. Compare with the signature Razorpay sent.

Constant-time compare

Use a timing-safe comparison (for example Node’s crypto.timingSafeEqual on buffers) so you do not leak information through early exits. Mentioning this in viva shows you read past the happy-path blog post.

Only then mark paid

If signatures differ → 400, leave order pending/failed path. If order already paid → idempotent success (see below). Never trust handler success in the browser as authorization to mutate stock.

Whiteboard script

Boxes: Browser → Verify API → HMAC check → Update Order + Inventory. Cross out an arrow that goes “Browser success → mark paid directly.” Say: “That crossed arrow is the vulnerability.”

Never trust the client amount

Attack version of your app: user edits JavaScript and pays ₹1 for a ₹10,000 item. Defense: server recomputes from product documents and quantities. Client may display price for UX; server decides charge amount when creating the Razorpay order. Stock and price snapshots freeze at purchase time so later catalog price changes do not rewrite history.

Test mode without real money

Keys and .env

Razorpay test key_id / key_secret in .env. Ship .env.example with placeholders. Never commit live secrets. In viva: “Secrets are environment variables, not in git.”

Demo cards and UPI

Use Razorpay’s documented test instruments. Practice one success and one failure. Failure proves you did not only screenshot the green path.

Live keys on college Wi-Fi

Do not. External examiners sometimes ask whether the demo is test mode — answer yes, proudly. Real money on a student laptop is a liability, not a flex.

Order states you should be able to recite

A clean student model:

  • ▸pending — created, awaiting payment
  • ▸paid — signature verified
  • ▸shipped — admin advanced
  • ▸delivered — complete
  • ▸cancelled / failed — payment never completed or order voided; inventory restored if you decremented early

Be explicit about when stock decrements: at paid time (simpler for many kits) or at order creation with reservation (harder; explain rollback). Pick one and document it.

Webhook vs client callback

What panels want to hear

Client callback gives immediate UX after the modal. It can fail if the user closes the tab before your verify POST. Webhooks are the production reliability path: Razorpay notifies your server server-to-server. Many academic demos verify via client callback + HMAC; that is acceptable if you state: “Production would add webhook handlers for reconciliation.”

Do not pretend you built webhooks

If code has no webhook route, say so. Examiners prefer an honest gap over a fake architecture slide.

Idempotency and double payment

Q: What if verify is called twice?
A: If order already paid, return success without charging again or double-decrementing stock. Razorpay order creation should also be tied so you do not spawn duplicate unpaid chaos for the same checkout intent — store and reuse the Razorpay order id for that Order document.

Cart architecture (Redux and persistence)

Why Redux Toolkit appears in ecommerce kits

Cart is cross-route UI state: product page, cart page, header badge. Redux (or equivalent) keeps that coherent. Explain: cart in client state until checkout creates a server Order; you are not writing every quantity click to MongoDB.

localStorage optional

Persisting cart across refresh is UX polish. On login, merge guest cart carefully to avoid duplicates — if you did not implement merge, say guest cart is session-only.

Snapshot line items

When creating the Order, copy product name, unit price, quantity into the order. Later catalog edits must not rewrite past invoices.

Cloudinary (or image URL) flow

Admin uploads image → Multer temp file → Cloudinary SDK → store HTTPS URL on product document. Do not dump binary into MongoDB. Viva line: “Metadata in MongoDB, blobs in object storage.” If you use static URLs without Cloudinary, say that too — consistency beats buzzwords.

Admin features worth demoing

  • ▸Product CRUD with image and stock
  • ▸Order list with status badges
  • ▸Mark shipped / delivered
  • ▸Optional: simple search (MongoDB text index or careful regex — know which)

Admin demo path

Login admin → add product → logout → customer purchases → admin marks shipped. Full lifecycle in one story. Compare with non-payment admin flows in library management if asked how ecommerce differs: money + inventory + external API trust.

Inventory and failure paths

If you decrement stock on pay: verification success and stock update should be consistent (same request handler, careful error handling). If payment fails after a mistaken decrement, restore quantity — walk that path in code during viva if you implemented it. If stock only decrements after verify, say “failed payments never touch inventory.”

Failed payment UX

User sees retry; order remains pending; cart may remain. Demo a failed test card once. Panels remember students who show recovery.

Refunds: scope discipline

Refunds via Razorpay API, partial refunds, and settlement reports are easy scope creep. Prefer: “Out of scope; future work via Razorpay refund API; admin may flag dispute manually.” Do not show a Refund button that only toggles a boolean unless you explain it is not a real PSP refund.

Security questions to prepare

Where is the secret? Environment variable on the server; never shipped to the browser (only key_id is public).

HTTPS? Required for real deployments with JWT and payments; local demo may be HTTP — state production would enforce HTTPS.

CORS / cookies? Explain how your auth token is stored and why APIs reject cross-origin abuse according to your setup.

CSRF? If you use cookie sessions, discuss protections; if Authorization bearer tokens from localStorage, explain the tradeoff honestly.

Can I mark paid from DevTools? Without a valid signature, verify endpoint rejects — that is the point of HMAC.

Ecommerce scope: what to ship vs defer

Ship: catalog, cart, checkout, verify, order history, admin product CRUD, test-mode demo.

Defer with one-line future-work notes: wishlist, reviews, coupons, recommendations, COD, wallets beyond what you tested, multi-vendor marketplace. Half-built coupon UIs hurt demos more than honest “not implemented” answers.

Razorpay verification alone is enough complexity for an external examiner if the story is crisp and the test payment works on the presentation laptop.

Product search (if present)

If the search bar uses a MongoDB text index, say so. If it is client filter or regex, say so. Do not claim “Elasticsearch” or “Atlas Search” unless configured. Wrong vocabulary is a classic viva failure mode.

PDF invoices and extras

PDF invoice generation is optional stretch. If missing, future work. Order history with status badges is enough for most rubrics.

COD vs online payment

If you only built Razorpay, state COD out of scope. Otherwise examiners invent cash-drawer questions you did not design for.

Sample viva Q&A pack

Walk through payment after the modal closes. Client sends payment_id, order_id, signature; server HMAC; then paid.

Why paise? Razorpay amounts are integer subunits; floating rupees cause rounding bugs.

What is in the order document? User id, line snapshots, amounts, Razorpay order id, status timestamps.

Webhook? Not in demo / planned for production — be consistent with code.

Double submit? Idempotent verify.

Secret in GitHub? Never; rotate if leaked; use .env.

Why MERN? Full-stack ownership of UI + API + DB; payment logic lives in Node where secrets belong. See also stack framing in AI vs MERN.

Report mapping

Chapter 3: customer vs admin use cases; payment sequence diagram.
Chapter 4: Order and Product schemas; cart vs order distinction.
Chapter 5: Razorpay integration subsection with verify pseudocode.
Chapter 6: test cases — success pay, bad signature rejected, stock after pay, admin ship.
Limitations: test mode only, no webhook, no refunds API.

Pitfalls

  • ▸Marking paid in the frontend
  • ▸Trusting client price
  • ▸Live keys in submission
  • ▸No failure demo
  • ▸Claiming webhooks/refunds you did not build
  • ▸Feature creep (wishlist + coupons + AI recommendations) with a broken checkout

Pre-viva checklist

  • ▸[ ] Test keys load from .env on presentation machine
  • ▸[ ] Success payment rehearsed offline as far as network allows
  • ▸[ ] Bad signature / failed pay path known
  • ▸[ ] Board sketch of HMAC ready
  • ▸[ ] Admin add-product path works with image
  • ▸[ ] Abstract does not claim COD/webhooks/refunds falsely
  • ▸[ ] .env not in zip; .env.example is

Sequence diagram you should be able to redraw

Without looking at notes, redraw:

  1. ▸Browser → API: create order (productIds, qtys)
  2. ▸API → MongoDB: load products, compute paise, insert Order pending
  3. ▸API → Razorpay: create order
  4. ▸API → Browser: key_id + razorpay order_id
  5. ▸Browser → Razorpay Checkout
  6. ▸Browser → API: payment_id, order_id, signature
  7. ▸API: HMAC verify → update Order paid → adjust stock
  8. ▸Browser: order history

If you can redraw this in sixty seconds, HMAC questions become easy. Practice on paper the night before — not during the viva.

Amount edge cases worth one sentence each

Zero quantity rejected. Quantity above stock rejected before Razorpay order creation. Currency fixed to INR for the academic demo. Discount coupons out of scope unless implemented end-to-end with server-side recalculation — a client-only coupon field is a viva trap.

What “order snapshot” prevents

Admin changes product price after you paid. Your Order line still shows the price you were charged. That is intentional. Explain it as historical integrity, same idea as invoice immutability in larger systems.

Deployment talking points (honest, short)

If you deployed to Render/Railway/Vercel-style hosting, mention HTTPS and env vars there. If not, say local demo with production deployment as future work — do not invent a Kubernetes slide. Payment secrets on a free tier deserve rotation discipline: revoke test keys if you ever pasted them in a screenshot that went to WhatsApp groups.

Comparing complexity to other MERN kits

Library issue/return is authorization-heavy without money. Hotel booking is availability-heavy without PSP signatures. Ecommerce adds a third-party trust boundary. Use that sentence when asked “why is this harder than a CRUD portal?”

Related reading

Alongside AI vs MERN, review common viva mistakes so payment confidence does not turn into overclaiming.

Project kits

Takeaway: Draw the Razorpay verify flow on the board and never trust client-side payment success alone. Use test keys, freeze prices on the server, and keep the ecommerce kit’s verify endpoint as the single gate between “modal said OK” and “order is paid.”

Ready to work on your own project?

We build complete project kits with source code, report, slides, and viva prep — message us on WhatsApp to get started.

Ask about this on WhatsApp
Message us