Skip to content
Payments⏱️ 12 min read·

Dynamic Fonepay QR Integration in Next.js: A Beginner’s Guide

Generate and display real-time dynamic Fonepay merchant QR codes in Next.js App Router. Allow customers to pay using any Nepali mobile banking app and poll transaction status automatically.

Need this wired into a product? See payment gateway integration.

MN
Manoj NeupaneSoftware Developer & Programming Instructor
#Fonepay#QR Code#Next.js#App Router#TypeScript#Payment Gateway
🎯 Who This Tutorial Is For

📋 Prerequisites
  • ✓A Next.js 14/15 project using the App Router
  • ✓Fonepay merchant test credentials from merchant.fonepay.com
  • ✓A client-side QR rendering library (e.g. 'qrcode.react')

🚀 What You Will Learn & Build

  • ▸How Fonepay dynamic QR generation works via their Merchant API
  • ▸Creating a Next.js Server Route Handler (/api/fonepay/generate-qr)
  • ▸Rendering dynamic QR codes on the frontend using SVG
  • ▸Implementing client-side status polling until payment is verified
1

1. The Fonepay Dynamic QR Architecture

Static QR stickers pasted on shops require the customer to type the amount manually. **Dynamic QR codes** generated via the Fonepay API embed the exact amount, merchant code, and unique invoice ID into the EMV QR string. When the customer scans the QR with their mobile banking app (e.g. Nabil SmartBank, Global Smart Plus), the app automatically loads the exact NPR amount and merchant name. The user simply taps "Confirm".
2

2. Next.js Server Route Handler (app/api/fonepay/qr/route.ts)

In Next.js App Router, keep your Fonepay merchant secrets inside server route handlers:
app/api/fonepay/qr/route.ts
import { NextResponse } from "next/server";
import crypto from "crypto";

export async function POST(req: Request) {
  try {
    const { amount, orderId } = await req.json();

    const merchantCode = process.env.FONEPAY_MERCHANT_CODE || "FNPLTEST";
    const secretKey = process.env.FONEPAY_SECRET_KEY || "fonepay_test_key";
    
    // Format timestamp
    const dateStr = new Date().toISOString().replace(/[-:T.Z]/g, "").slice(0, 14);
    
    // Hash fields for Fonepay API signature
    const hashData = `${merchantCode},${orderId},${amount},${dateStr}`;
    const signature = crypto.createHmac("sha512", secretKey).update(hashData).digest("hex");

    // Call Fonepay Dynamic QR API
    const res = await fetch("https://dev-clientapi.fonepay.com/api/merchant/merchantDetailsForThirdParty/thirdPartyMerchantQR", {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({
        merchantCode,
        amount,
        remarks1: `Order ${orderId}`,
        prn: orderId,
        date: dateStr,
        signature
      })
    });

    const data = await res.json();
    return NextResponse.json({ success: true, qrString: data.qrMessage });
  } catch (error) {
    return NextResponse.json({ error: "Failed to generate QR" }, { status: 500 });
  }
}

✨ Expected Output & Verification

A high-conversion checkout screen displaying a dynamic QR code that automatically updates to 'Payment Verified' when scanned.

🧪 How to Test the Implementation

  1. 1Send a POST request to /api/fonepay/qr with amount and orderId
  2. 2Render the returned qrMessage string in a React QRCode component
  3. 3Simulate payment using Fonepay developer sandbox portal

⚠️ Common Errors & How to Fix Them

❌Signature mismatch on Fonepay API

Root Cause: Fonepay uses SHA512 (not SHA256) with specific parameter order.

Fix: Verify that crypto.createHmac('sha512', key) is used with the exact merchant code and timestamp.

🛡️ Security Considerations & Best Practices

  • !Always verify payment status on the server before fulfilling digital downloads or credits.

❓ Frequently Asked Questions (FAQ)

Yes, over 50 commercial, development, and microfinance banks in Nepal are members of the Fonepay network.

📌 Summary of Key Takeaways

Dynamic Fonepay QR integration in Next.js allows customers to pay with any Nepali bank app without leaving your website.

Official References & Further Reading