Validation Examples
Each example is a check you can run on the decoder. The payload cookbook has full strings; this page is the expected verdict.
Pass: static INR sticker shape
POI 11, Tag 53 = 356, no Tag 54, CRC valid, name ≤ 25. Verdict: structurally OK. Still not payable unless GUID is live.
Fail: Tag 53 letters
5303INR. Verdict: non-compliant currency even if CRC was computed after the letters.
Fail: CRC last digit flipped
Verdict: integrity fail. Do not pay.
Fail: 11 with Tag 54
Verdict: POI/amount conflict. Fix before print.
Pass: dynamic billed QR
POI 12, Tag 54 present, Tag 53 numeric, CRC valid. Decoder should show a locked amount equal to Tag 54. If the amount on the pay screen differs, the wallet is rounding or ignoring decimals — file that as an app issue, not a CRC issue.
Include Tag 62 bill number when your recon process needs it. Validation still passes if 62 is omitted; operations may fail later.
Fail: length overrun after MAI
If the outer MAI length is larger than the inner TLV, the next root tag is eaten as residual account data. Symptom: merchant name looks like a fragment of a GUID. Fix the outer length; do not rename the merchant.
Fail: Tag 63 not last
Any object after CRC is unspecified for MPM. Treat as malformed even if a naive CRC over a prefix still matches. Regenerators should always append 63 as the final root tag.
How to record a validation run
Save the raw string, decoder screenshot of the tag table, wallet name and version, and pass/fail. Academy cookbook strings must be labelled illustrative so nobody pastes them onto a door.
Official pass criteria for a scheme still come from that scheme’s cert kit, not from this page.
Pass: static INR sticker without amount
Expect Tag 00=01, Tag 01=11, one MAI, Tag 52 four digits, Tag 53=356, Tag 58=IN, Tag 59 and 60 within length caps, Tag 63 last with a CRC that Decode marks valid, and no Tag 54. If your generator emits 54 on this shape, fail the build even if CRC matches. Static means the customer types the amount in the wallet.
Label every Academy sample illustrative. The EMVQRHUB / DELHI strings are for layout drills. A reviewer or a wallet risk engine that sees those names on a live counter should treat them as placeholders, not as a merchant file.
Fail: alphabetic currency and why CRC can still match
Tag 53=INR with length 03 is a well-formed TLV object and will checksum if you compute CRC after the mistake. Validation must include a semantic check: Tag 53 is three digits, not three letters. Decode on this site flags that class of error because many wallets refuse to charge. Do not “fix” it by padding INR to 356 in a support script without regenerating CRC and retesting wallets.
Pair this with the ISO 4217 article. Numeric 356, 764, 702, 840 are the usual examples; the rule is the numeric code, not the alphabetic code you type in accounting software.
Fail: POI 11 with Tag 54, and the opposite
A static method with a locked amount is undefined behaviour across wallets: some hide the keypad, some ignore 54, some refuse. Treat 11+54 as a fail in your own validator even if a particular app is lenient. The inverse (12 without 54) is also a fail for billed QR: the customer should not be typing the ticket total.
Record both as named fixtures. After every generator release, run them. See Point of Initiation for why Tag 01 is a method bit, not a marketing label, and Static vs Dynamic for the operations choice.
Fail: CRC nibble flip versus length overrun
Flipping the last hex character of Tag 63 should yield CRC invalid with a still-readable tag table. That is an integrity fail. A length overrun after MAI often yields a garbage tree and a CRC that may or may not match depending on how far you compared. Do not lump both under “QR broken.” Ticket them as checksum versus framing so the right engineer looks.
Tag 63 not last is its own fail: extra objects after CRC are unspecified for MPM. A naive CRC over a prefix can still match. Regenerators must append 63 as the final root tag every time.
How to archive a run so it is reproducible
Save the raw payload, the Decode tag table (or a screenshot plus the string), wallet name and version, pass/fail, and the date. If you only keep the pretty QR image, JPEG compression and crop make the ticket useless. If you only keep “failed in PhonePe,” you cannot tell CRC from GUID from camera glare.
Official scheme pass criteria still come from that scheme’s certification kit and from EMVCo’s QR documents on emvco.com. This page is a cookbook of shapes we use when teaching the decoder — not a cert lab.
Teaching order for new hires
Start with pass static, then fail alphabetic Tag 53, then fail CRC nibble, then fail 11+54. Only then show dynamic pass. That order mirrors how often each defect appears in Decode tickets. End with “record the string.”
Automating verdicts
Script pass/fail against the cookbook strings: assert Tag 53.isdigit(), assert not (poi==11 and has54), assert crc_valid, assert tag63_is_last. Human-readable pages and machine fixtures can share the same strings. Keep them in git beside the generator.
Fixture hygiene
Refresh CRC when sample bytes change; never commit a pass fixture with EMVQRHUB on a production branch tag.
