One Sunday morning, an online grocery company’s monitoring showed something strange. Thousands of orders for ₹1 to ₹10, all paid by card, almost all failing. The few that succeeded were being cancelled immediately. Orders were coming from hundreds of IP addresses, but all with the same browser fingerprint.
It was card testing: someone with a list of stolen card numbers was using the checkout page to find out which cards still worked, before using the good ones for bigger fraud elsewhere. The grocery company didn’t lose much directly. But it got a spike in declined transactions, a warning from its gateway about unusual activity, a flood of chargebacks two weeks later from the cards that went through, and a lot of real customers getting SMS alerts from their banks about a small charge from “a grocery app” they had never used.
The fix took two days: a CAPTCHA on checkout after a few failed attempts, and simple velocity limits. This lesson is about building those defences before you need them.
Fraud Patterns You’ll Actually See
A few notes on the ones that are especially common in India:
OTP and “refund” scams. Fraudsters call customers pretending to be from your support team: “We’ll process your refund, just share the OTP you received” or “approve this request in your UPI app to receive your refund”. The customer ends up paying the fraudster. You can’t fully stop this, because it happens outside your system, but you can reduce it a lot:
- Never ask customers for OTPs or UPI PINs, anywhere, ever. Say so clearly in your app, emails and SMS.
- Make your real refund process visible in the app (“Refund of ₹499 initiated, no action needed from you”).
- Don’t expose customer phone numbers or order details where scammers can get them (public order tracking pages, unsecured APIs).
Fake payment screenshots. Common for businesses that take payments over WhatsApp or at delivery: the customer shows an edited “Payment successful” screenshot. The rule from Lesson 2 applies: only your server-verified status counts. For delivery staff collecting UPI at the door, give them an app that shows the confirmed status from your backend, not the customer’s phone.
Offer and cashback abuse. “₹100 off on your first order” gets used by the same person with 50 new accounts. Link accounts by device fingerprint, UPI ID, card token, phone number and delivery address. One UPI ID paying for 30 “first orders” is not 30 new customers.
Insider fraud. An ops agent refunds orders to their own UPI ID, or marks COD orders as “refunded” and pays themselves. Refund-to-source rules, maker-checker approvals and audit logs (Lesson 8) exist for this.
A Simple, Explainable Risk Check
You don’t need a machine learning model on day one. You need a few clear rules, in the right place in the flow, that you can explain to a customer or a colleague.
The most useful single tool is the velocity check: how many times has this user, card, device, IP or UPI ID done this in the last N minutes? Redis makes it easy:
import redis
r = redis.Redis()
def bump(key: str, window_s: int) -> int:
"""Increment a counter that expires after the window. Returns the new count."""
pipe = r.pipeline()
pipe.incr(key)
pipe.expire(key, window_s, nx=True) # set expiry only on first increment
count, _ = pipe.execute()
return count
RULES = [
# (name, key template, window seconds, limit, action)
("ip_payment_attempts", "va:ip:{ip}", 600, 20, "captcha"),
("device_payment_attempts", "va:dev:{device_id}", 600, 10, "captcha"),
("user_failed_payments", "vf:user:{user_id}", 3600, 5, "block_card_payments"),
("card_attempts", "va:card:{card_fp}", 3600, 4, "block"),
("upi_new_accounts", "na:vpa:{vpa}", 86400, 3, "review"),
]
def risk_check(ctx: dict) -> str:
"""Return 'allow', 'captcha', 'review' or 'block'. Log every rule that fires."""
worst = "allow"
order = ["allow", "captcha", "review", "block_card_payments", "block"]
for name, tmpl, window, limit, action in RULES:
try:
key = tmpl.format(**ctx)
except KeyError:
continue # signal not available for this request
count = bump(key, window)
if count > limit:
log_rule_hit(name, ctx, count)
if order.index(action) > order.index(worst):
worst = action
return worstcard_fp here is a fingerprint of the card your gateway gives you (or a token), not the card number itself. Many gateways provide a card fingerprint or token id precisely so merchants can do this kind of check without touching card data.
Where to put the check:
- Before creating the gateway order for checkout velocity (card testing shows up here).
- Before applying an offer for offer abuse.
- Before a refund or payout for refund abuse.
The feedback loop
Rules decay. Fraudsters adapt, your business changes, and a rule that made sense in January blocks real customers in October. So:
- Label outcomes. Every chargeback, confirmed fraud case and refund abuse case is a label. Check which rules fired (or didn’t) for those orders.
- Track false positives. Every blocked or challenged genuine customer is lost revenue and a bad experience. Track block and challenge rates by rule, and customer complaints about being blocked.
- Test new rules in “log only” mode for a week before enforcing them. You’ll see how many real orders they’d affect.
- Keep a rule changelog. When something changes, you’ll want to know which rule was added when, and why.
When you have enough data and volume, a scoring model can help. But a team that can’t explain its rules usually can’t explain its model either. Start simple.
Also remember that your gateway runs its own risk checks, and so do the card networks and banks. You’re not alone. Your job is mainly to catch abuse of your business logic (offers, refunds, COD, accounts), which only you can see.
Securing the Payment System
Fraud comes from outside. Security problems often come from inside your own systems. Payment systems need the usual good security practices, applied more strictly.
Secrets. Gateway keys, webhook secrets, bank API credentials and payout keys live in a secrets manager, not in config files or code. Different keys per environment. Rotation plan ready. Payout keys especially: they can send money out of your account.
Webhook endpoints. Signature verification (Lesson 4) is mandatory. Optionally also restrict by the gateway’s published IP ranges, but don’t rely on IPs alone.
Service-to-service access. Only the payments service should be able to call the gateway’s refund and payout APIs. Other services ask the payments service, through an authenticated internal API that applies the refund rules. A bug in your marketing service should never be able to issue a refund.
Database access. Separate DB users per service. The ledger tables are append-only (Lesson 7). Engineers don’t get write access to production payment tables; changes go through scripts that are reviewed and that use the same state transition functions as the application.
The ops console. This is where a lot of risk sits, because it’s the tool that can refund, cancel, and change things by hand.
- Role-based access: support can view, senior support can refund up to a limit, finance can approve above it.
- 2FA for everyone, and SSO if you have it.
- Maker-checker for anything above a threshold: one person requests, another approves.
- Audit log of every action: who, what, when, from where, and why (reason required).
- Mask personal data (show last 4 digits of phone, partial UPI ID) unless the role needs it.
Kill switches. A feature flag per payment method and per gateway, so you can turn off cards for an hour during a card-testing attack, or switch to the backup gateway when the primary one is down, without a deploy.
Logs. No card numbers, CVVs, OTPs, UPI PINs, or full bank account numbers in logs. Use the masking filter from Lesson 3, and check your error tracker and analytics events too.
Compliance: A Map for Engineers
Payments in India come with a lot of rules. Most of them are the gateway’s, the bank’s or the network’s responsibility, but several reach into your system. Here’s a map to start conversations with your legal, compliance and finance teams.
PCI DSS. Covered in Lesson 3. Keep card data out of your systems with hosted checkout, and your PCI obligations become small (usually a self-assessment questionnaire). Your gateway can tell you which one applies.
Card tokenisation (RBI). Don’t store card numbers. Use tokens and display data like the last 4 digits.
Authentication and e-mandates (RBI). Additional factor of authentication for card payments, and the recurring payment rules from Lesson 10. Mostly handled by gateway flows, but your billing logic must respect limits and notification rules.
Data localisation (RBI). RBI requires payment system data to be stored in India. The obligation is primarily on payment system providers like your gateway, but if your systems store payment data (transaction details, for example), ask your compliance team how it applies to you. Practically: know where your database, logs, backups, analytics tools and third-party services (error trackers, CRMs, support tools) store data. A US-hosted error tracker that captures full payment payloads can be a problem.
DPDP Act, 2023. India’s data protection law covers personal data, which payment systems are full of: names, phone numbers, addresses, UPI IDs. Engineering work: collect only what you need, define retention periods, build deletion flows (and know what you must keep for legal or tax reasons even after a deletion request), and secure access.
Payment Aggregator guidelines (RBI). Gateways that collect money for merchants need RBI authorisation and must follow rules on escrow accounts and settlement. For you, the practical points: use an authorised gateway, and if you run a marketplace that collects money for sellers, design the money flow with your gateway and legal team, because a marketplace holding sellers’ money has its own rules.
PPI / wallet rules. If you want to build a “wallet” where customers keep money that can be used outside your own app, that’s a regulated prepaid payment instrument. Store credit usable only in your app is treated differently. Talk to legal before building anything called a wallet.
Tax. GST on gateway fees, GST on your sales, and for e-commerce operators, specific TDS and TCS rules. Engineering’s job: store the data finance needs (fee and tax per transaction, seller-wise totals) and produce reliable reports.
Audit and retention. Regulators, auditors and banks may ask about transactions from years ago. Keep the ledger, payment events, refund approvals and ops audit logs for the required period (your finance and legal teams will tell you how long), in append-only form.
None of this is legal advice, and rules change. The engineering habit that helps most: write down which rules apply to you, who owns each one, and where in the system it’s handled. Review that document every few months, and whenever RBI or NPCI publishes something new that affects your payment methods.
Pitfalls to Avoid
- No velocity limits on checkout. Card testing will find you. Add limits and a CAPTCHA before it does.
- Asking customers for OTPs or PINs anywhere, for any reason. It trains them to fall for scams.
- Trusting screenshots or the customer’s phone for payment status.
- Offers without abuse checks. Link accounts by device, UPI ID, card token and address.
- Rules nobody reviews. Label outcomes, track false positives, test in log-only mode, keep a changelog.
- Any service can call refund or payout APIs. Only the payments service, with rules applied.
- An ops console without roles, 2FA, maker-checker and audit logs.
- No kill switch per method and gateway.
- Sensitive data in logs and third-party tools, possibly outside India.
- Treating compliance as someone else’s problem. Map the rules, owners and system touch points, and review regularly.
Quick Recap
- Common fraud: card testing, OTP scams, friendly fraud, refund and offer abuse, insider refunds, fake screenshots, account takeover.
- Start with explainable velocity rules, CAPTCHA and step-up, and close the loop with labelled outcomes.
- Secure secrets, webhooks, internal APIs, databases and especially the ops console. Keep kill switches ready.
- Know your compliance map: PCI DSS, tokenisation, AFA and mandates, data localisation, DPDP, PA and PPI rules, tax, audit.
That’s every building block. In the final lesson, we put them together into one design for a real product, with a launch checklist and a plan for big sale days.