Skip to content

kdandy/QRIS-Hook

Repository files navigation

QRIS Hook

documentation the QRIS Hook project

Quick Summary

QRIS Hook upgrades a static QRIS payload into a dynamic one by injecting a random three-digit suffix into the transaction amount, recalculating the checksum, and returning a ready to scan QR code image. It is built with the Next.js App Router and meant for merchant teams who want a quick way to validate incoming payments.

Key Features

  • Browser form that accepts a static payment amount and calls the API in real time.
  • API endpoint POST /api/generate that transforms a static QRIS payload into a dynamic payload.
  • Automatic CRC-16/CCITT-FALSE checksum recalculation aligned with EMVCo guidelines.
  • Smart reassembly of QRIS tags (switching tag 01 to dynamic, rebuilding tag 54, preserving locality tags).
  • QR code rendering to a PNG Data URL using the qrcode package.

How It Works

  1. The user enters a payment amount in the web form (app/page.tsx).
  2. The form posts to POST /api/generate with the amount.
  3. The API handler (app/api/generate/route.ts):
    • Validates the request payload.
    • Reads the original static QRIS payload from the inputQris environment variable.
    • Generates a randomized amount using helpers in lib/qris.ts.
    • Rebuilds the QRIS payload and recomputes the CRC.
    • Produces a QR code image (PNG Data URL) and returns it along with metadata.

Tech Stack

  • Framework: Next.js 14 (App Router) on top of React 18.
  • Language: TypeScript.
  • QR Generator: qrcode for PNG Data URLs.
  • Hosting Targets: Vercel, Netlify, Render, or any Next.js-compatible platform.

Prerequisites

  • Node.js 18 LTS or newer.
  • npm 9+ (or a compatible pnpm/yarn release).
  • A valid static QRIS payload string that you are allowed to use.

Getting Started

  1. Clone the repository

    git clone https://github.com/kdandy/QRIS-Hook.git
    cd QRIS-Hook
  2. Install dependencies

    npm install
  3. Create a local environment file

    cp .env-development to .env

Configuration

Set the static QRIS payload via environment variables:

inputQris="<your_static_qris_payload_here>"

Guidelines:

  • The payload must be the full QRIS string with no whitespace.
  • Keep this value secret; do not commit .env.local to version control.

Running the Project

  • Development server

    npm run dev

    Then open http://localhost:3000.

  • Production build

    npm run build
    npm run start
  • Lint check

    npm run lint

API Reference

POST /api/generate

  • Request body

    {
      "amount": "10000"
    }

Notes:

  • amount accepts either a string or a number.

  • Provide at least four digits so the helper can randomize the last three.

  • Successful response (200)

    {
      "originalNominal": "10000",
      "randomizedNominal": "10795",
      "randomSuffix": "795",
      "qris": "010212...6304ABCD",
      "qrImage": "data:image/png;base64,iVBORw0..."
    }

Fields:

  • originalNominal: sanitized amount received from the request.

  • randomizedNominal: amount after the random suffix is applied.

  • randomSuffix: the generated three-digit suffix.

  • qris: the final QRIS payload ready for validation or storage.

  • qrImage: PNG Data URL of the QR code, convenient for <img> tags.

  • Error responses

    • 400: malformed JSON, missing/invalid amount, nominal too short, or other validation issues.
    • 500: environment variable inputQris missing or unexpected server error.

Important Helpers

All located in lib/qris.ts:

  • randomizeNominal(input): sanitizes the amount and swaps its last three digits with a random value (000-999).
  • prosesQris(qrString, nominal): converts tag 01 from static to dynamic (010211010212), rebuilds tag 54 with the new nominal, and recalculates CRC using crc16CcittFalse.
  • generateQrPngData(qrisData): wraps the payload into a PNG Data URL via QRCode.toDataURL with error correction level L.

Testing & Validation

  • Automated tests are not yet included. Consider adding unit tests for randomizeNominal and prosesQris to lock down the business logic.
  • Perform manual QA by generating multiple amounts and scanning the resulting QR codes with a QRIS-compatible payment app.

Deployment Tips

  • Set inputQris in your hosting platform's environment variable settings.
  • No NEXT_PUBLIC_ prefix is required because the variable is only read on the server side.
  • Restart the deployment whenever you rotate the QRIS payload.

Troubleshooting

  • "Environment variable 'inputQris' belum diisi."
    • Ensure .env.local exists locally, or the production env var is configured.
  • Unexpected nominal value
    • The API always randomizes the last three digits; use randomizedNominal for actual reconciliation.
  • QR code fails to scan
    • Verify your static QRIS payload is valid and complete before conversion.

Ideas for Future Enhancements

  1. Allow configuring the number of randomized digits.
  2. Persist conversion history for auditing.
  3. Expose a verification endpoint to confirm that incoming payments match generated suffixes.

Maintained and documented by Dandy.

About

QRIS Statis to Dinamis Converter Payment Gateway

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors