The Rise of UPI
Unified Payments Interface (UPI) has revolutionized digital payments in India, processing billions of transactions monthly. For any "India-first" business, prioritizing UPI isn't just an option—it's a necessity.
While gateways like Razorpay handle the complexity, understanding the underlying Intent Flow (Deep Linking) is crucial for optimizing conversion rates on mobile devices.
The Problem with Traditional Web Flows
On a desktop, a user enters their VPA (e.g., user@upi) and gets a collect request on their phone.
However, on mobile, asking a user to switch apps, approve a request, and switch back leads to high drop-offs.
The Solution: UPI Intent flow
The Intent Flow allows your web app to directly trigger installed UPI apps (PhonePe, GPay, Paytm) on the user's device.
How it works
- Construct the URI: A standard UPI URI looks like this:
upi://pay?pa=merchant@bank&pn=MerchantName&tr=TransactionID&am=100.00&cu=INR - Trigger the Intent: On mobile web, this is a simply a link (
<a href="...">).
Implementation in React
If you are building a P2P app or have a direct banking integration (rare for small startups), you might construct this link manually. However, most developers use a gateway's "Seamless UPI" flow.
Here is how you handle the "Intent" mode if you were redirecting users manually (e.g., for a donation link or P2P transfer).
import React from 'react';
const UPILink = ({ amount, vpa, name }) => {
// Construct the UPI Deep Link
const upiLink = `upi://pay?pa=${vpa}&pn=${encodeURIComponent(name)}&am=${amount}&cu=INR`;
return (
<div className="p-4 border rounded-lg shadow-md max-w-sm mx-auto mt-10">
<h2 className="text-xl font-bold mb-2">Pay via UPI</h2>
<p className="text-gray-600 mb-4">Click below to pay ₹{amount}</p>
{/*
On mobile, this will open the sheet to choose an app (GPay, PhonePe).
On desktop, this will likely do nothing or prompt to open an app.
*/}
<a
href={upiLink}
className="block w-full bg-green-600 text-white text-center py-3 rounded-lg font-bold"
>
Pay ₹{amount} with UPI App
</a>
<p className="text-xs text-gray-400 mt-2 text-center">
Only works on mobile devices with UPI apps installed.
</p>
</div>
);
};
export default UPILink;
PhonePe Integration (Python/Django)
PhonePe has emerged as a massive player. If you want to integrate their Payment Gateway directly (bypassing aggregators):
1. The Payload
PhonePe requires a base64 encoded payload and a checksum (X-VERIFY) header.
import base64
import hashlib
import json
import requests
SALT_KEY = "your_salt_key"
SALT_INDEX = "1"
def initiate_phonepe_payment(amount_in_paise, transaction_id, user_id):
payload = {
"merchantId": "YOUR_MERCHANT_ID",
"merchantTransactionId": transaction_id,
"merchantUserId": user_id,
"amount": amount_in_paise,
"redirectUrl": "https://yourwebsite.com/api/payment/callback",
"redirectMode": "POST",
"callbackUrl": "https://yourwebsite.com/api/payment/webhook",
"mobileNumber": "9999999999",
"paymentInstrument": {
"type": "PAY_PAGE"
}
}
# Encode payload
payload_str = json.dumps(payload)
base64_payload = base64.b64encode(payload_str.encode('utf-8')).decode('utf-8')
# Calculate Checksum
string_to_hash = base64_payload + "/pg/v1/pay" + SALT_KEY
sha256_hash = hashlib.sha256(string_to_hash.encode('utf-8')).hexdigest()
x_verify = f"{sha256_hash}###{SALT_INDEX}"
# Make Request
headers = {
'Content-Type': 'application/json',
'X-VERIFY': x_verify
}
response = requests.post(
"https://api.phonepe.com/apis/hermes/pg/v1/pay",
json={'request': base64_payload},
headers=headers
)
return response.json()
Conclusion
For Indian businesses:
- Razorpay is the easiest "all-in-one" solution.
- UPI Intent Flow is critical for mobile conversion.
- PhonePe offers a competitive alternative with deep market penetration.
Choosing the right stack depends on whether you need a quick setup (Razorpay) or deeper direct integration (PhonePe/UPI Direct).
Comments
Sign in to join the conversation