@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
Maintainers
Readme
QRIS Dynamic Conversion
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-conversionOr using yarn:
yarn add @januarfonti/qris-dynamic-conversionOr using pnpm:
pnpm add @januarfonti/qris-dynamic-conversionUsage
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 convertamount(string | number): Transaction amount in IDRtaxType(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 validerrors(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 zerostoCRC16(data): Calculate CRC16 checksumisValidQRIS(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:
- Validates the input static QRIS format
- Removes the old CRC16 checksum
- Replaces the static identifier (010211) with dynamic identifier (010212)
- Inserts the amount tag (tag 54) with the specified value
- Adds optional fee tag (tag 55) if specified
- Recalculates the CRC16 checksum for the modified data
- Returns the complete dynamic QRIS string
Development
Setup
- Clone the repository:
git clone https://github.com/januarfonti/qris-dynamic-conversion.git
cd qris-dynamic-conversion- Install dependencies:
npm install- Run tests:
npm test- Build the library:
npm run buildTesting 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.
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add some amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
Releasing
This project uses two methods for releasing:
Automatic Release (Changesets)
- Create a changeset for your changes:
npx changeset - Commit the changeset file
- When merged to main, the GitHub Action will create a release PR
- Merge the release PR to publish to NPM
Manual Release
- Go to Actions → Manual NPM Release
- Click "Run workflow"
- Select version type (patch, minor, major)
- 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
- GitHub: @januarfonti
Acknowledgments
- Bank Indonesia for QRIS specifications
- The Indonesian fintech community
Support
If you found this project helpful, please consider giving it a ⭐️ on GitHub!
