Skip to main content

RFID / NFC Cards

Besides the dynamic QR code, users can identify themselves with a physical RFID card. The user registers the card once in the Cheers app; from then on, the card's serial number (UID) acts as their permanent Transaction Key at the till.

This page describes how the Cheers app reads the card during registration, so your POS or card reader can implement the same reading logic — both sides must derive the identical key from the same card.

How It Works​

The key derivation is identical on both sides. If your reader derives the same key the app derived during registration, the API resolves the card to the user.

Card Technology​

The Cheers app reads cards over the NFC-A (ISO/IEC 14443 Type A) interface, which covers the MIFARE family (Classic, Ultralight, DESFire, NTAG, ...). Only the UID (serial number) is read — the anti-collision identifier every ISO 14443-A card broadcasts. No sectors are authenticated, nothing is written to the card, and no NDEF payload is involved.

PropertyValue
InterfaceISO/IEC 14443 Type A (NFC-A / MIFARE)
What is readUID (serial number) only
UID lengths4, 7, or 10 bytes — all supported
Data written to the cardNone — the card is used purely as an identifier
info

Because only the UID is read, the card does not need to be issued by Cheers — any ISO 14443-A card with a fixed UID works. Cards or devices with a randomized UID (some bank cards, phones in card-emulation mode) will not work, since the UID changes on every read.

Deriving the Transaction Key​

The Transaction Key is the card UID, hex-encoded, lowercased, and left-padded with zeros to 32 characters:

  1. Read the UID in the byte order the card transmits it (UID byte 0 first).
  2. Hex-encode it and strip any separators (: or -) your reader inserts.
  3. Lowercase the result.
  4. Left-pad with 0 to exactly 32 characters.
const transactionKey = uidHex
.replace(/[^0-9a-fA-F]/g, "") // strip ":" / "-" separators
.toLowerCase()
.padStart(32, "0");

Examples​

UID as read from the cardLengthTransaction Key
04:1A:2B:3C:4D:5E:6F7 bytes000000000000000000041a2b3c4d5e6f
A1:B2:C3:D44 bytes000000000000000000000000a1b2c3d4

Use the result as the X-Transaction-Key header in the preview call. The rest of the payment flow is identical to the QR-code flow — see Integration Flow.

Reader Checklist​

Reader hardware (USB, keyboard-wedge, embedded modules) is often configurable, and the defaults vary. Verify all of these, otherwise the derived key will not match the one registered by the app:

RequirementDetail
Hex outputThe UID must be emitted as hexadecimal, not converted to a decimal number.
Byte orderUID byte 0 first — the order the card transmits it. Some readers emit the UID reversed (little-endian); disable that option.
Full UIDRead the complete UID. Some readers truncate 7-byte UIDs to 4 bytes or drop the leading 04 manufacturer byte common on NXP cards.
Leading zerosZero bytes inside the UID must be kept (04:00:2B:... → 04002b...). Only the overall left-padding to 32 characters is added afterwards.
LowercaseThe app registers the key in lowercase — lowercase your value before sending it.

Verification: scan a test card in the Cheers app (Profile → Settings → Physical cards → Add card → RFID). After the scan, the app displays the Card ID — the UID as uppercase hex without separators. Your reader must produce the same value; after lowercasing and left-padding it, you have the exact key the app registers.

QR Code vs. RFID Card​

The two Transaction Key sources behave differently:

QR codeRFID card
LifetimeOne-time use, short expiryPermanent until the user revokes the card
ReusableNoYes — the same key on every visit
ValueGenerated dynamically by the appDerived from the card UID
Prior registrationNot neededRequired — the user registers the card in the Cheers app first
Unregistered cards

Any card produces a syntactically valid key, but a card that was never registered in the Cheers app does not belong to any user — the preview request will be rejected. If a card is declined, ask the guest to register it in the Cheers app (Profile → Settings → Physical cards) and try again.

Reference Implementation​

This is how the Cheers app itself reads the card (React Native, using react-native-nfc-manager) — shown here as the reference for what your reader must reproduce:

import NfcManager, { NfcTech } from "react-native-nfc-manager";
import { Platform } from "react-native";

const readCard = async (): Promise<string | null> => {
try {
// MIFARE on iOS, NFC-A on Android — both expose the ISO 14443-A UID
await NfcManager.requestTechnology(
Platform.OS === "ios" ? NfcTech.MifareIOS : NfcTech.NfcA,
);

const tag = await NfcManager.getTag();
if (!tag?.id) return null;

// tag.id is the UID as hex, possibly colon-separated (e.g. "04:1A:2B:3C:4D:5E:6F")
const uidHex = tag.id.replace(/:/g, "");

// The registered Transaction Key: lowercase, left-padded to 32 chars
return uidHex.toLowerCase().padStart(32, "0");
} finally {
NfcManager.cancelTechnologyRequest().catch(() => {});
}
};