npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@januarfonti/qris-dynamic-conversion

v1.0.1

Published

QRIS Static to Dynamic Converter - Convert static QRIS codes to dynamic ones with customizable amount and fee

Readme

QRIS Dynamic Conversion

npm version License: MIT TypeScript

A TypeScript library to convert static QRIS (Quick Response Code Indonesian Standard) to dynamic QRIS with customizable amount and fee. This library allows you to generate dynamic payment QR codes for Indonesian payment systems.

Features

  • 🚀 Convert static QRIS to dynamic QRIS
  • 💰 Set custom transaction amounts
  • 📊 Support for percentage or fixed fee
  • ✅ QRIS validation with detailed error messages
  • 📦 TypeScript support with full type definitions
  • 🪶 Lightweight with zero dependencies
  • 🧪 Thoroughly tested

Installation

npm install @januarfonti/qris-dynamic-conversion

Or using yarn:

yarn add @januarfonti/qris-dynamic-conversion

Or using pnpm:

pnpm add @januarfonti/qris-dynamic-conversion

Usage

Basic Usage

import { generateDynamicQRIS } from '@januarfonti/qris-dynamic-conversion'

const staticQRIS = 'YOUR_STATIC_QRIS_STRING_HERE'

// Convert to dynamic QRIS with amount only
const dynamicQRIS = generateDynamicQRIS({
  qrisStatic: staticQRIS,
  amount: 50000 // IDR 50,000
})

console.log(dynamicQRIS)

With Percentage Fee

import { generateDynamicQRIS } from '@januarfonti/qris-dynamic-conversion'

const dynamicQRIS = generateDynamicQRIS({
  qrisStatic: staticQRIS,
  amount: 100000, // IDR 100,000
  taxType: 'p',  // percentage
  fee: 2.5        // 2.5% fee
})

With Fixed Amount Fee

import { generateDynamicQRIS } from '@januarfonti/qris-dynamic-conversion'

const dynamicQRIS = generateDynamicQRIS({
  qrisStatic: staticQRIS,
  amount: 100000, // IDR 100,000
  taxType: 'r',  // rupiah (fixed amount)
  fee: 1000       // IDR 1,000 fee
})

QRIS Validation

import { validateQRIS } from '@januarfonti/qris-dynamic-conversion'

const validationResult = validateQRIS(qrisString)

if (validationResult.isValid) {
  console.log('QRIS is valid!')
} else {
  console.log('QRIS validation errors:', validationResult.errors)
}

API Reference

generateDynamicQRIS(options)

Converts a static QRIS to dynamic QRIS with specified amount and optional fee.

Parameters

  • options (GenerateDynamicQRISOptions): Configuration object with the following properties:
    • qrisStatic (string): The static QRIS string to convert
    • amount (string | number): Transaction amount in IDR
    • taxType (optional, 'p' | 'r'): Type of fee - 'p' for percentage, 'r' for rupiah (fixed amount). Default: 'p'
    • fee (optional, string | number): Fee value. Default: '0'

Returns

  • string: The generated dynamic QRIS string

Throws

  • Error: If the input QRIS is invalid or amount is zero

validateQRIS(qris)

Validates a QRIS string and returns detailed validation results.

Parameters

  • qris (string): The QRIS string to validate

Returns

  • QRISValidationResult: Object containing:
    • isValid (boolean): Whether the QRIS is valid
    • errors (string[]): Array of validation error messages

Utility Functions

The library also exports utility functions that can be used independently:

  • pad(num): Pad a number with leading zeros
  • toCRC16(data): Calculate CRC16 checksum
  • isValidQRIS(qris): Quick validation check

Examples

Integration with Nuxt 3

<template>
  <div>
    <input v-model="amount" type="number" placeholder="Enter amount" />
    <button @click="generateQRIS">Generate Dynamic QRIS</button>
    <div v-if="dynamicQRIS">
      <p>{{ dynamicQRIS }}</p>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref } from 'vue'
import { generateDynamicQRIS } from '@januarfonti/qris-dynamic-conversion'

const amount = ref(0)
const dynamicQRIS = ref('')
const staticQRIS = 'YOUR_STATIC_QRIS_HERE'

const generateQRIS = () => {
  try {
    dynamicQRIS.value = generateDynamicQRIS({
      qrisStatic: staticQRIS,
      amount: amount.value
    })
  } catch (error) {
    console.error('Error generating QRIS:', error)
  }
}
</script>

Integration with Next.js

import { useState } from 'react'
import { generateDynamicQRIS } from '@januarfonti/qris-dynamic-conversion'

export default function QRISGenerator() {
  const [amount, setAmount] = useState('')
  const [dynamicQRIS, setDynamicQRIS] = useState('')
  const staticQRIS = 'YOUR_STATIC_QRIS_HERE'

  const handleGenerate = () => {
    try {
      const result = generateDynamicQRIS({
        qrisStatic: staticQRIS,
        amount: amount
      })
      setDynamicQRIS(result)
    } catch (error) {
      console.error('Error generating QRIS:', error)
    }
  }

  return (
    <div>
      <input 
        type="number" 
        value={amount} 
        onChange={(e) => setAmount(e.target.value)}
        placeholder="Enter amount" 
      />
      <button onClick={handleGenerate}>Generate Dynamic QRIS</button>
      {dynamicQRIS && <p>{dynamicQRIS}</p>}
    </div>
  )
}

How It Works

The library performs the following operations:

  1. Validates the input static QRIS format
  2. Removes the old CRC16 checksum
  3. Replaces the static identifier (010211) with dynamic identifier (010212)
  4. Inserts the amount tag (tag 54) with the specified value
  5. Adds optional fee tag (tag 55) if specified
  6. Recalculates the CRC16 checksum for the modified data
  7. Returns the complete dynamic QRIS string

Development

Setup

  1. Clone the repository:
git clone https://github.com/januarfonti/qris-dynamic-conversion.git
cd qris-dynamic-conversion
  1. Install dependencies:
npm install
  1. Run tests:
npm test
  1. Build the library:
npm run build

Testing with Real QRIS Data

To test with your actual QRIS data, replace the sample QRIS in the tests with your real static QRIS string. The QRIS must:

  • Contain the tag "010211" (static QRIS identifier)
  • Include "5802ID" (Indonesia country code)
  • End with a valid 4-character CRC16 checksum

Example test with your QRIS:

const yourStaticQRIS = 'YOUR_ACTUAL_STATIC_QRIS_HERE'
const dynamicQRIS = generateDynamicQRIS({
  qrisStatic: yourStaticQRIS,
  amount: 50000
})

Contributing

Contributions are welcome! Please feel free to submit a Pull Request. For major changes, please open an issue first to discuss what you would like to change.

  1. Fork the repository
  2. Create your feature branch (git checkout -b feature/amazing-feature)
  3. Commit your changes (git commit -m 'Add some amazing feature')
  4. Push to the branch (git push origin feature/amazing-feature)
  5. Open a Pull Request

Releasing

This project uses two methods for releasing:

Automatic Release (Changesets)

  1. Create a changeset for your changes: npx changeset
  2. Commit the changeset file
  3. When merged to main, the GitHub Action will create a release PR
  4. Merge the release PR to publish to NPM

Manual Release

  1. Go to Actions → Manual NPM Release
  2. Click "Run workflow"
  3. Select version type (patch, minor, major)
  4. The workflow will automatically:
    • Bump version
    • Publish to NPM
    • Create GitHub release
    • Push tags

License

This project is licensed under the MIT License - see the LICENSE file for details.

Author

Januar Fonti

Acknowledgments

  • Bank Indonesia for QRIS specifications
  • The Indonesian fintech community

Support

If you found this project helpful, please consider giving it a ⭐️ on GitHub!