Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/Pratyay360/upiqrcode/llms.txt

Use this file to discover all available pages before exploring further.

This guide walks you through integrating upiqrcode into a React application. Because upiqrcode is compiled to WebAssembly, you need to initialize the WASM module before calling any of its functions — this guide shows you exactly how to do that with useEffect and how to manage loading, error, and result states cleanly.
Prerequisites: React 18 or later, a bundler with WASM support (Vite is recommended), and upiqrcode installed in your project.

Vite configuration

If you are using Vite, add the following option to vite.config.ts to prevent Vite from pre-bundling the WASM package, which would break the module:
vite.config.ts
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'

export default defineConfig({
  plugins: [react()],
  optimizeDeps: {
    exclude: ['upiqrcode'],
  },
})

Steps

1

Install the package

Install upiqrcode from npm:
npm install upiqrcode
2

Create the component

Create a new file UPIQRCode.tsx and set up state for the QR SVG, the intent URL, a loading flag, and an error message:
UPIQRCode.tsx
import { useState, useEffect } from 'react'
import init, { upiqrcode, type UpiqrcodeResult } from 'upiqrcode'

interface UPIQRCodeProps {
  payeeVPA: string
  payeeName: string
  amount?: string
  transactionNote?: string
}

export function UPIQRCode({
  payeeVPA,
  payeeName,
  amount,
  transactionNote,
}: UPIQRCodeProps) {
  const [qr, setQr] = useState<string>('')
  const [intent, setIntent] = useState<string>('')
  const [loading, setLoading] = useState<boolean>(true)
  const [error, setError] = useState<string>('')

  useEffect(() => {
    const generateQR = async () => {
      setLoading(true)
      setError('')
      try {
        await init()
        const result = (await upiqrcode({
          payeeVPA,
          payeeName,
          amount,
          transactionNote,
        })) as UpiqrcodeResult

        setQr(result.qr)
        setIntent(result.intent)
      } catch (err) {
        setError(err instanceof Error ? err.message : String(err))
      } finally {
        setLoading(false)
      }
    }

    generateQR()
  }, [payeeVPA, payeeName, amount, transactionNote])

  if (loading) return <div>Generating QR code...</div>
  if (error) return <div>Error: {error}</div>

  return (
    <div>
      <h2>UPI Payment QR Code</h2>
      <div dangerouslySetInnerHTML={{ __html: qr }} />
      <a href={intent} rel="noopener noreferrer">
        Open in UPI app
      </a>
    </div>
  )
}
The init() call loads the WASM binary. You must await it before calling upiqrcode(). Placing both inside useEffect ensures the WASM module is only loaded in the browser, not during server-side rendering.
3

Add error handling

The try/catch block above already captures errors from both init() and upiqrcode(). Validation errors — such as a payeeVPA shorter than 5 characters or a payeeName shorter than 4 characters — are thrown as strings and surfaced through the error state:
} catch (err) {
  // err may be a string (from WASM validation) or an Error object
  setError(err instanceof Error ? err.message : String(err))
}
4

Render the QR code and intent link

The result.qr value is raw SVG markup. Use dangerouslySetInnerHTML to inject it directly into the DOM. The result.intent value is a upi:// deep link that opens the user’s default UPI payment app on mobile:
return (
  <div>
    <h2>UPI Payment QR Code</h2>
    {/* Render SVG markup inline */}
    <div dangerouslySetInnerHTML={{ __html: qr }} />
    {/* UPI deep link for mobile */}
    <a href={intent} rel="noopener noreferrer">
      Open in UPI app
    </a>
  </div>
)

Using the component

Import and render UPIQRCode anywhere in your app. Pass at minimum a payeeVPA and payeeName:
App.tsx
import { UPIQRCode } from './UPIQRCode'

export default function App() {
  return (
    <main>
      <UPIQRCode
        payeeVPA="merchant@upi"
        payeeName="Acme Store"
        amount="250.00"
        transactionNote="Order #1042"
      />
    </main>
  )
}
On a mobile browser, the upi:// intent URL opens the device’s default UPI payment app directly. You can style the link as a button to make it more prominent:
<a
  href={intent}
  rel="noopener noreferrer"
  style={{
    display: 'inline-block',
    padding: '12px 24px',
    background: '#241c24',
    color: '#fff',
    borderRadius: '6px',
    textDecoration: 'none',
  }}
>
  Pay with UPI
</a>
On mobile browsers the intent URL opens the default UPI app. On desktop, no UPI app is installed, so display the QR code instead and let the user scan it with their phone.

Next steps

API reference: upiqrcode()

See the full parameter reference, return type, and validation rules for the upiqrcode function.

Build docs developers (and LLMs) love