Building Dynamic UPI Payment QR Generators with Vanilla JavaScript and Canvas API
The Unified Payments Interface (UPI) has transformed consumer purchasing behavior across India, handling billions of frictionless transactions every month. For digital product sellers, freelancers, and independent developers, accepting UPI payments directly is the most effective way to eliminate friction. Traditional credit card forms demand manual card numbers, CVVs, expiry dates, and OTP redirects, driving high checkout abandonment on mobile devices.
While merchant aggregators like Razorpay or Cashfree provide managed checkout experiences, high-volume developers often require custom, zero-dependency client-side payment interfaces. By utilizing the National Payments Corporation of India (NPCI) deep-linking specification combined with the HTML5 Canvas API and Vanilla JavaScript, you can render dynamic, order-specific UPI payment QR codes directly inside the browser with zero external server dependencies.
Step 1: Demystifying the NPCI UPI Deep Link Schema
At the architectural core of every UPI QR code and payment button is a standardized Uniform Resource Identifier (URI) scheme. When scanned by an application like Google Pay, PhonePe, Paytm, or CRED, the string is parsed by the mobile OS to auto-fill the transaction details.
The standard NPCI URI format requires specific key-value parameters:
pa(Payee Address): Your verified Virtual Payment Address / UPI ID (e.g.,merchant@okhdfcbank).pn(Payee Name): The business or legal individual name attached to the account.am(Amount): The exact numerical transaction value formatted with two decimals (e.g.,99.00).cu(Currency): Must be strictly set toINR.tn(Transaction Note): A concise description indicating what the payment covers (e.g.,Order_Tshirt_Pack_99).tr(Transaction Reference): A unique identifier or order hash used for auditing and tracking reconciliations.
upi://pay?pa=merchant@okhdfcbank&pn=DigitalKitPro&am=99.00&cu=INR&tn=Order_1042.
Step 2: Dual Device Routing: Mobile Intent vs. Desktop QR
An exceptional checkout interface must deliver responsive payment flows depending on whether the customer is browsing on a desktop workstation or a mobile smartphone.
Implement conditional device detection directly in your JavaScript logic:
- Mobile Browsers: On mobile devices, displaying a QR code creates severe friction because users cannot scan their own phone screen. Instead, attach the raw
upi://paylink directly to a prominent "Pay with Any UPI App" button. When tapped, the mobile browser invokes the native Android or iOS application intent chooser, allowing the user to select their preferred payment app directly. - Desktop Monitors: On desktop screens, users cannot click a native mobile URI scheme. In this environment, your code should dynamically render the URI string into a high-contrast QR code on an HTML5
<canvas>element, allowing the customer to scan their monitor with their phone's camera in seconds.
Step 3: Rendering the QR Matrix on HTML5 Canvas
Generating the QR code in the browser does not require a bulky server-side API or dynamic image hosting. Using lightweight client-side QR generation libraries (such as a minified qrcode.js bundle weighing under 10 KB), you can draw the matrix dynamically.
Here is the implementation architecture:
function generateUPIQR(amount, orderId) {
const vpa = "merchant@okhdfcbank";
const payeeName = "DigitalKitPro";
const upiUri = `upi://pay?pa=${vpa}&pn=${encodeURIComponent(payeeName)}&am=${amount}&cu=INR&tn=${orderId}`;
// Clear existing canvas
const container = document.getElementById("qr-container");
container.innerHTML = "";
// Render new QR Code
new QRCode(container, {
text: upiUri,
width: 220,
height: 220,
colorDark: "#09090b",
colorLight: "#ffffff",
correctLevel: QRCode.CorrectLevel.M
});
}
Because this execution runs entirely on the client side, QR codes render in less than 5 milliseconds without making external HTTP network calls.
Step 4: Handling Reconciliation and Webhook Verification
Generating the payment intent is only half the battle; verifying that funds have arrived before unlocking digital asset downloads is crucial for preventing fraud.
In a production architecture, dynamic UPI QR codes should be paired with backend capture verification:
- When the checkout starts, generate a unique order ID stored in your database or Google Sheets ledger.
- When the user submits the transaction in their UPI app, your bank or payment gateway webhook fires a confirmation payload to your automation endpoint (e.g., Make.com).
- Your frontend periodically polls a lightweight endpoint (or listens via WebSockets or Server-Sent Events) to confirm the order ID has flipped to "PAID".
- The instant payment clears, the frontend automatically redirects the customer to their private download dashboard, delivering an instant, seamless transactional loop.
Conclusion: Building Lightweight, High-Conversion Checkouts
Eliminating friction is the fundamental law of digital product sales. By leveraging NPCI's native UPI URI protocol, tailoring interactions based on device context, and rendering dynamic canvas QR codes directly in the browser, developers can construct fast, independent payment funnels that maximize conversion rates across India's booming digital economy.