On Feb 28, 2026, NPCI deprecated the UPI Collect flow for one-time P2M payments on Android and desktop. Four of our clients had production apps relying on Collect — a D2C beauty brand, an edtech SaaS for tuition centres, a B2B vendor invoicing app, and a regional OTT. We migrated all four between Jan and May. Two before the deadline, two after the deadline emergencies. This post is what broke, what worked, and the test deck we now run on every migration.
28 Feb
NPCI Deadline (2026)
+12.4%
Avg Success Rate Lift (Intent vs Collect)
−38%
Drop in Failed Checkouts
## The Answer in 60 Words
UPI Collect (where the merchant pushes a payment request to a typed VPA) is gone for Android and desktop merchant flows. The replacement: UPI Intent on mobile (deep-link into the user's chosen UPI app), UPI QR on desktop (scan with the phone). [Razorpay Intent](https://razorpay.com/docs/payments/payment-methods/upi/upi-intent/), PayU, Cashfree, and PhonePe all support it. Expect 10–15% higher success rates per [Razorpay's published benchmarks](https://razorpay.com/blog/upi-intent-vs-collect-success-rates/).
## Why This Matters Now
NPCI's circular went into effect Feb 28, 2026. Apps still using Collect for P2M on Android/desktop now see failed payments with a vague "your bank declined" message that users blame the app for. iOS retained Collect (for now), creating a confusing two-platform support story. Indian payment gateways pushed advisories from Dec 2025 onwards — but a lot of small/mid apps either missed the advisories or assumed it would be extended. We have done four migrations and seen the same seven failure modes each time.
## The 4 Clients (Specific Details)
| Client | City | Sector | UPI Volume | Pre-migration Success | Post-migration |
|---|---|---|---|---|---|
| BlushBox (D2C beauty) | Mumbai | E-commerce | ₹38L/mo | 79% | 91% |
| TuitionFlow (edtech) | Hyderabad | SaaS | ₹14L/mo | 81% | 94% |
| InvoiceQuick (B2B SaaS) | Delhi NCR | Vendor invoicing | ₹2.2 cr/mo | 84% | 95% |
| KannadaPlay (OTT) | Bengaluru | Streaming | ₹6.8L/mo | 76% | 92% |
The two we migrated before Feb 28: BlushBox (Jan) and TuitionFlow (early Feb). The two we did under fire after the deadline: InvoiceQuick (Mar 4–8) and KannadaPlay (Mar 14–21, after a brutal February of failed renewals).
## The 7 Things That Broke
### 1. The "send link to my UPI ID" affordance vanished
The Collect flow let a user type "ramesh@oksbi" on checkout. The Intent flow does not — the user picks their UPI app instead. Naive migration: replace the input field with a button that says "Pay with UPI." Better: detect the user's likely UPI app from the device, surface that app first in the picker. We use a heuristic: GPay default on Android, BHIM as fallback on rooted devices, PhonePe surfaced first if a PhonePe redirect cookie exists from a previous session.
### 2. iOS users get a different flow
iOS retained Collect because Apple does not allow deep-link interception the way Android does. Result: same app, two different UX flows. We added a platform check on the client and route iOS users to the Collect flow (still supported on iOS) and Android/desktop users to Intent + QR. Bookkeeping: log the flow used per payment for analytics — otherwise your success-rate dashboard will be misleading.
### 3. Webhooks fire at different times
In Collect, the webhook fires when the user authorises (with a known callback structure). In Intent, the webhook fires when the UPI app reports success — but the user has already left your app. We saw two specific issues: (a) users who closed the UPI app before the SUCCESS callback got stuck on a checkout spinner, (b) some apps fire the webhook before the back-navigation to merchant — so the order page renders before the webhook handler updates the DB.
Fix: poll the payment status server-side every 4 seconds for up to 90 seconds after redirect. Show a "Verifying payment..." UI to the user. Only mark "checkout complete" after webhook OR status-poll confirms.
### 4. Order amounts at the boundary fail silently
Some banks reject UPI transactions above ₹1 lakh per payment under the [NPCI limits](https://www.npci.org.in/what-we-do/upi/product-overview). Some merchants have their own caps. Some PG accounts have transaction-level caps configured per BIN. Collect failures historically said "transaction failed" — the user knew to call support. Intent flows often fail silently from the merchant's side because the failure is in the user's UPI app. Fix: pre-validate amount client-side (≤₹1 lakh for non-special-permitted MCC; B2B SaaS used a different flow), display a clear error before redirect, and log the rejection reason on the server.
### 5. The order ID gets lost in app-switching
When the user is deep-linked to GPay, returns to your app, your activity may have been killed by the OS (especially on low-RAM Android). The order ID stored in memory is gone. Fix: persist the order ID in localStorage or AsyncStorage (mobile) before redirect. On return, hydrate from persisted state, not from a fresh init.
### 6. WhatsApp / SMS payment links break
InvoiceQuick's main flow was: send the buyer an SMS with a payment link. The buyer opens it on their phone (probably WhatsApp). The link used to open Collect — typed VPA. Post-Feb 28, that fails on Android. Fix: server-generated UPI URI (
upi://pay?pa=...&am=...) which Android resolves into Intent automatically. On desktop, the same link shows a QR code on a landing page.
### 7. The success page redirect URL needs explicit verification
Intent does not always return to the exact URL you set as success_url — it returns to the host that initiated the deep link. Apps that hard-coded
/checkout/success?orderId=X saw users dropped on
/checkout/success with no orderId because the deep-link return didn't preserve query strings on certain Android OEM customisations (Xiaomi, Realme).
Fix: pass the order ID through the UPI URI's transaction reference (
tr parameter), then read it back from the webhook — not the URL fragment. The URL is unreliable; the webhook is the source of truth.
## The Replacement Pattern (Intent + QR)
📱
Android / mWeb
UPI Intent. Generate a upi:// URI server-side, redirect. User picks their UPI app from the chooser. Webhook + 90-second polling confirms.
🖥️
Desktop Web
UPI QR. Render the same upi:// URI as a QR. Display a "scan with your UPI app" instruction. Poll for payment status.
🍎
iOS App
Collect flow still supported (until NPCI extends the deprecation). Or use a webview-based Intent via Razorpay's iOS SDK if you want unified UX.
📨
SMS / WhatsApp Links
Send a link to a landing page that renders the upi:// URI as Intent on mobile or QR on desktop. Same backend, two front-end resolutions.
## The Test Deck (60 Tests We Run on Every Migration)
This is the artefact you cannot find on most PG documentation pages. We built it after KannadaPlay's emergency in March — the regression in production was a flow we had not even imagined.
### Device matrix (12 combinations we run live)
| OS | Browser/App | Network | UPI App |
|---|---|---|---|
| Android 13 (Xiaomi) | Chrome 122 | Jio 4G | GPay |
| Android 14 (Realme) | mWeb checkout | Airtel 5G | PhonePe |
| Android 12 (low-RAM Samsung) | App webview | Vi 4G | BHIM |
| iOS 17 (iPhone 12) | Safari | Jio 5G | GPay iOS |
| iOS 18 (iPhone 14) | Native app | Airtel 5G | PhonePe iOS |
| Desktop Win 11 | Chrome 122 | Broadband | (QR, scanned from phone) |
| Desktop macOS Sonoma | Safari | Broadband | (QR scan) |
| Android 13 (rooted) | Chrome | Wi-Fi | BHIM |
| Android 14 (Samsung S24) | App | 5G | Paytm |
| Android 13 | Instagram in-app browser | Wi-Fi | GPay |
| Android 13 | WhatsApp in-app browser | 4G | GPay |
| Tablet Android 13 | Chrome | Wi-Fi | PhonePe |
### Test cases per device (5 per device, 60 total)
1. Successful payment (₹49, smallest realistic amount)
2. User cancels at UPI app (back button before authorising)
3. User authorises, then app is force-killed before webhook
4. ₹1 lakh boundary (just below: ₹99,999) and just above (₹1,00,001)
5. Same order ID re-attempted after a successful payment (must be rejected)
We also test 4 webhook scenarios server-side: late webhook (60s delay), duplicate webhook, mismatched signature, and out-of-order webhook delivery.
The two failures that caught us at KannadaPlay both happened only on Xiaomi devices running MIUI 14 with a custom WebView. We added "Xiaomi MIUI 14 Chrome 122" as a permanent row in our device matrix after that.
## The Migration (How We Run It)
1
Day 1: Audit the current flow
List every place UPI is invoked: checkout, renewal, top-up, invoice link, WhatsApp share. Most apps surprised us with 3–5 distinct entry points.
2
Day 2: Update the PG SDK + enable Intent
Razorpay/PayU/Cashfree all have a single config flag. Update SDK to the latest version. Enable Intent in dashboard. Confirm Test Mode works on Android.
3
Days 3–5: Implement platform-aware routing
Server-side or client-side detection of platform. Intent on Android/mWeb, QR on desktop, Collect on iOS (transitionally). Persist order ID. Add post-redirect polling.
4
Days 6–8: Test deck pass
Run all 60 cases on a feature-flagged staging environment. Document failures. Re-test after fix. Three of our four migrations had ≥4 failures on the first pass.
5
Day 9: Canary 5% → 25% → 100%
A/B the new flow at 5% for 24 hours. Monitor success rate and abandonment. Roll forward only if success rate is ≥ old flow's last 14 days. We saw BlushBox jump from 79% to 89% in the first 5% canary — easy roll-forward.
6
Day 10: Decommission Collect-only paths
Remove the VPA input field for Android. Remove the "Send to my UPI ID" affordance from receipts. Keep iOS Collect alive until further NPCI guidance.
## The Outcomes (Per Client)
BlushBox: Success rate 79% → 91%. Cart abandonment dropped 11.2 percentage points. Estimated additional revenue: ₹4.4 lakh/month at their volume.
TuitionFlow: Renewal success 81% → 94%. The big win was the SMS link flow — Intent-deep-link on Android meant parents who used to ignore Collect requests (because typing a VPA from a 6-inch screen is hostile) now complete in 11 seconds median.
InvoiceQuick: B2B invoices in the ₹50k–₹3L range. Success 84% → 95%. The CFO's email after week 2: "stopped getting Friday afternoon calls from buyers saying 'your link is broken.'"
KannadaPlay: Subscription renewal 76% → 92%. They had 6 weeks of brutal churn in Feb-Mar before the migration completed. Recoverable. We did a one-week reactivation campaign with the new flow once it stabilised.
We benchmarked against [Razorpay's published Intent-vs-Collect data](https://razorpay.com/blog/upi-intent-vs-collect-success-rates/) — their median customer sees a 10–15% bump. Our four clients matched.
## When Not to Migrate (Yet)
Skip the migration if (a) you are an iOS-only app — iOS Collect is supported until NPCI says otherwise; you have time, (b) you process under ₹2 lakh/month UPI volume — the engineering hours are not yet worth it; you can survive on the iOS-Collect path for another quarter, or (c) you use a managed checkout that handles the platform routing for you (Razorpay's hosted Checkout already routes correctly; you only need a migration if you have a custom UPI build).
## The UPI Intent Migration Checklist
- Audit every UPI entry point (checkout, renewal, top-up, invoice link, WhatsApp share)
- Update PG SDK to the latest version with Intent support
- Implement platform-aware routing (Intent on Android/mWeb, QR on desktop, Collect on iOS)
- Persist order ID in localStorage/AsyncStorage before redirect
- Add 90-second server-side polling fallback after webhook
- Pre-validate amount client-side (≤ ₹1 lakh standard cap)
- Use the upi:// URI's tr (transaction ref) parameter for order ID — not URL fragment
- Idempotency key on every order-completion endpoint
- Run the 60-test device matrix before canary rollout
- Canary at 5% → 25% → 100% with success-rate gating
## Common Mistakes
Symptom: "Payments succeeding but orders not updating." Cause: relying on URL redirect for confirmation. Fix: webhook + server polling. URL is hint, webhook is source of truth.
Symptom: "Spinners forever on checkout." Cause: app waits for redirect that never returns. Fix: 90-second timeout on the client with a "didn't get a confirmation? check your UPI app" message.
Symptom: "Same payment charged twice." Cause: webhook + redirect both triggering order completion. Fix: idempotency key on order completion. Idempotent EVERYTHING that touches money.
Symptom: "Xiaomi users keep complaining." See the test deck. MIUI customisations break things. Test it.
Symptom: "Some users see a payment app picker, others get redirected straight to GPay." Cause: GPay setting "default UPI app" on the device. This is correct behaviour. Stop debugging it. Tell the user.
## FAQ
### Is UPI Collect completely gone?
No. On iOS for now, and for special MCC codes (stocks, IPOs), Collect remains. For typical P2M flows on Android and desktop, yes — it stopped working as the primary path on Feb 28, 2026.
### Can I keep Collect on Android too?
You can keep it as a fallback for cases where Intent fails, but you cannot present it as the primary option. Most PGs simply remove the option from their SDK on Android post-deadline.
### Does the migration need a payment gateway switch?
No. All major Indian PGs support Intent + QR. Razorpay, PayU, Cashfree, Easebuzz, PhonePe Business — same flow, different SDK calls. Stay with whichever PG you already use.
### What about WhatsApp Pay?
WhatsApp Pay is itself a UPI-PSP. It is one of the apps that gets surfaced in the Intent app picker on Android. Your migration unblocks WhatsApp Pay users who previously got nothing because Collect required them to give the merchant a VPA they didn't always remember.
### What if my SDK doesn't support Intent yet?
Update it. Every major PG SDK has shipped Intent support before Feb 2024. If you are on an older SDK, the upgrade is usually a 1–2 day job. If you have built a custom UPI integration without a PG SDK, the migration is closer to 1–2 weeks.
### Do I need to update mobile app users?
If your UPI integration is server-driven (you generate the upi:// URI on the backend and the app just renders it), no. If your mobile app has a hardcoded UPI module that uses Collect, yes — push an update before relying on the new flow.
### How long does this take in total?
For a single-checkout app: 7–10 working days from start to 100% rollout. For an app with multiple UPI touch points (checkout + invoices + renewals + share-to-buyer): 14–21 days. Add 5 days if you are also re-doing the iOS path.
Want Your App's UPI Flow Modernised?
We migrate Indian apps (D2C, edtech, SaaS, OTT) from UPI Collect to Intent + QR with the test deck above. Fixed-price, 10–15 working days, canary-rolled. First call is with the engineer who would lead the migration. Bonus: we'll tell you honestly if your PG's hosted checkout already does it for you.
Book a Migration Call