Skip to content

Verification

Three levels of checking, from lightweight to thorough:

1. Structural checks — verify()

Checks the document's internal structure: required tags present, tag values match expected patterns, merchant info exists.

typescript
import { verify } from '@heigoly/qris/verify'

const issues = verify(doc)

if (issues.length === 0) {
  console.log('Structure is valid')
} else {
  for (const issue of issues) {
    console.log(`[${issue.code}] ${issue.message}`)
  }
}

Returns an array of VerifyIssue objects. Empty array = no problems.

2. CRC integrity — verifyCRC()

Checks whether the CRC16 checksum matches the payload. This detects accidental data corruption.

typescript
import { verifyCRC } from '@heigoly/qris/verify'

if (verifyCRC(doc)) {
  console.log('CRC is valid — data is intact')
}

3. Full security check — isSecure()

Runs both structural verification AND CRC check. Returns a single boolean.

typescript
import { isSecure } from '@heigoly/qris/verify'

if (!isSecure(doc)) {
  throw new Error('QRIS failed security check')
}

When to use each

SituationUse
User scans a QR codeisSecure() — full check
You just parsed a QRIS from a trusted sourceverify() — structure only
You upgraded a QRIS and want to check the outputisSecure() — full check
You're building a QRIS from scratchverifyCRC()verify()isSecure()

Low-level CRC

typescript
import { computeCRC } from '@heigoly/qris/crc'

computeCRC('000201010211...6304')  // → "C8C0"