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 🙏

© 2025 – Pkg Stats / Ryan Hefner

emvco-qr-sdk

v1.0.0

Published

A robust TypeScript SDK for decoding, validating, and processing EMVCo-compliant QR codes used in digital payment systems.

Downloads

306

Readme

EMVCo QR SDK Banner

emvco-qr-sdk

TypeScript Node.js Jest License Platform

A robust, zero-dependency TypeScript SDK to decode, validate, and map EMVCo-compliant QR codes for digital payment systems.

emvco-qr-sdk provides a full-featured, extensible parser for QR codes that follow the EMVCo Merchant Presented Mode format.
It is cross-platform, with support for Node.js and browser environments, and does not rely on any external dependencies.


✨ Features

  • 🧠 EMVCo TLV Parsing Engine
    Decode raw QR strings using the official Tag-Length-Value format defined by the EMVCo specification.

  • 🔀 Nested Tag Support
    Automatically parses and reconstructs deeply nested TLV structures, commonly found in interoperable payment systems.

  • 🌍 Regional Mapping Strategies
    Supports both standard global mappings and region-specific mappings like Colombia (EASPBV), returning human-readable field names for better integration.

  • 🏷️ Multiple Output Modes
    Choose from:

    • TLV: Raw parsed tag entities (TlvEntity[])
    • RAW_OBJECT: Raw key/value object by tag
    • GLOBAL or CO: Named object output with optional subtag resolution
  • CRC-16/CCITT-FALSE Checksum Validation
    Built-in cyclic redundancy check to ensure QR string integrity, following EMVCo guidelines.

  • 🔍 Validation Utilities
    Validate QR format, structure, and checksum before processing. Ensures reliable QR handling in secure applications.

  • 📦 Zero Dependencies & Tree-shakeable
    No external libraries required. Fully optimized for bundlers like Webpack, Vite, or Rollup.

  • 🌐 Cross-platform Compatibility
    Runs seamlessly in:

    • Web Browsers
    • Node.js
    • React Native
    • Serverless environments
  • 🧪 100% TypeScript & Fully Tested
    Strong typings for auto-completion and refactoring. Built with modern TypeScript and tested with Jest.


📦 Installation

npm install emvco-qr-sdk
# or
yarn add emvco-qr-sdk

🚀 Usage Examples

✅ 1. TLV Mode – Return Raw TLV Entities

import { parseQR, QRParseMode } from 'emvco-qr-sdk';

const tlvs = parseQR(rawQR, { parseMode: QRParseMode.TLV });

console.log(tlvs);

Returns:

[
  { "tag": "00", "value": "01", "length": 2 },
  { "tag": "53", "value": "170", "length": 3 },
  { "tag": "54", "value": "100.53", "length": 6 },
  { "tag": "59", "value": "Fulano de Tal", "length": 13 },
  { "tag": "60", "value": "BOGOTA", "length": 6 },
  { "tag": "63", "value": "CADC", "length": 4 }
]

📦 2. RAW_OBJECT Mode – Flat Raw Tags with Optional Nested Subtags

const raw = parseQR(rawQR, { parseMode: QRParseMode.RAW_OBJECT });

console.log(raw);

Returns:

{
  "00": "01",
  "53": "170",
  "54": "100.53",
  "59": "Fulano de Tal",
  "60": "BOGOTA",
  "63": "CADC",
  "80": {
    "00": "CO.COM.CRB.CANAL",
    "01": "POS"
  },
  "90": {
    "00": "CO.COM.CRB.TRXID",
    "01": "a1777581-6d1a-4b60-b3a9-b695f3562c55"
  }
}

🌍 3. GLOBAL Mode – Named Fields Based on EMVCo Standards

const global = parseQR(rawQR, { parseMode: QRParseMode.GLOBAL });

console.log(global);

Returns:

{
  "payloadFormatIndicator": "01",
  "transactionCurrency": "170",
  "transactionAmount": "100.53",
  "merchantName": "Fulano de Tal",
  "merchantCity": "BOGOTA",
  "crc": "CADC",
  "channel": {
    "00": "CO.COM.CRB.CANAL",
    "01": "POS"
  },
  "transactionId": {
    "00": "CO.COM.CRB.TRXID",
    "01": "a1777581-6d1a-4b60-b3a9-b695f3562c55"
  }
}

🇨🇴 4. CO Mode – Colombian EASPBV Enhanced Mapping

import { parseQR, QRParseMode } from 'emvco-qr-sdk';

const parsed = parseQR(rawQR, { parseMode: QRParseMode.CO });

console.log(parsed);

Returns:

{
  payloadFormatIndicator: "01",
  pointOfInitiationMethod: "12",
  merchantAccountInfo: {
    gui: "CO.COM.CRB.LLA",
    rawType: "02",
    type: "MOBILE_NUMBER",
    value: "3191231234"
  },
  transactionCurrency: "170",
  transactionAmount: "100.53",
  merchantName: "Fulano de Tal",
  merchantCity: "BOGOTA",
  channel: {
    gui: "CO.COM.CRB.CANAL",
    channel: "POS"
  },
  transactionId: {
    gui: "CO.COM.CRB.TRXID",
    transactionId: "a1777581-6d1a-4b60-b3a9-b695f3562c55"
  },
  securityField: {
    gui: "CO.COM.CRB.SEC",
    securityHash: "caf0f93160949f2c96d7f0ed4473eab8ba53fadf9cd29bc518507fe879266145"
  },
  vatValue: {
    gui: "CO.COM.CRB.IVA",
    vatValueOrPercentage: "10.00"
  },
  vatBase: {
    gui: "CO.COM.CRB.BASE",
    vatBaseValue: "1000.00"
  },
  incCondition: {
    gui: "CO.COM.CRB.CINC",
    incCondition: "02"
  },
  incValue: {
    gui: "CO.COM.CRB.INC",
    incValueOrPercentage: "50.00"
  },
  discountField: {
    gui: "CO.COM.CRB.DESC",
    discountIndicator: "01",
    discountConsultation: "00"
  },
  crc: "CADC"
}

🧩 This mode uses Colombia's extended EMVCo specification (EASPBV) to map structured information such as:

  • 🔑 merchantAccountInfo: the interoperable key used (cell phone, email, NIT, etc.)
  • 🧾 vatValue, vatCondition, vatBase
  • 📌 channel, transactionId, securityField
  • 💸 discountField with breakdowns
  • 🏷️ Each field includes internal identifiers like gui and type to help systems interpret the format

🧠 This is ideal for any payment app, merchant system, or validator working with the Colombian QR regulation EASPBV.


🧹5. Full Parsing with parseFullQR

This method returns a full structured object including:

  • named: A mapped object with field names (standard or Colombian).
  • raw: The raw object preserving tag codes.
  • tlvs: The full array of parsed TLV entities.
  • crc: Validates the checksum.
  • meta: Metadata about format, version, and region.
import { parseFullQR, QRParseMode } from 'emvco-qr-sdk';

const rawQR = '00020101021226360014CO.COM.CRB.LLA0210319123123453021705406100.535902Fulano de Tal6006BOGOTA800016CO.COM.CRB.CANAL0103POS900016CO.COM.CRB.TRXID0136a1777581-6d1a-4b60-b3a9-b695f3562c556304CADC';

const result = parseFullQR(rawQR, { parseMode: QRParseMode.CO });

console.log(result);

Returns:

{
  named: {
    payloadFormatIndicator: "01",
    pointOfInitiationMethod: "12",
    merchantAccountInfo: {
      gui: "CO.COM.CRB.LLA",
      rawType: "02",
      type: "MOBILE_NUMBER",
      value: "3191231234"
    },
    transactionCurrency: "170",
    transactionAmount: "100.53",
    merchantName: "Fulano de Tal",
    merchantCity: "BOGOTA",
    channel: {
      gui: "CO.COM.CRB.CANAL",
      channel: "POS"
    },
    transactionId: {
      gui: "CO.COM.CRB.TRXID",
      transactionId: "a1777581-6d1a-4b60-b3a9-b695f3562c55"
    },
    crc: "CADC"
  },
  raw: {
    "00": "01",
    "01": "12",
    "26": {
      "00": "CO.COM.CRB.LLA",
      "02": "3191231234"
    },
    "53": "170",
    "54": "100.53",
    "59": "Fulano de Tal",
    "60": "BOGOTA",
    "80": {
      "00": "CO.COM.CRB.CANAL",
      "01": "POS"
    },
    "90": {
      "00": "CO.COM.CRB.TRXID",
      "01": "a1777581-6d1a-4b60-b3a9-b695f3562c55"
    },
    "63": "CADC"
  },
  tlvs: [
    // Array of parsed TlvEntity instances
  ],
  crc: {
    value: "CADC",
    isValid: true
  },
  meta: {
    format: "EMVCO",
    version: "01",
    region: "CO"
  }
}

🧾 Change Log

You can find the changelog in the Releases section.
We follow Semantic Versioning.


📘 References


📄 License

Licensed under the ISC License.