QR Scan Check

Shows where a scanned QR code really goes before anything opens, so a fake sticker over a real code doesn't send you somewhere else.

StopsHelps catch a fake QR sticker before it opens

Installation

pnpm dlx shadcn@latest add https://bollard-ui.vercel.app/r/qr-scan-check.json

The files land in your project. They're yours to edit.

Usage

qr-scan-check-usage.tsx
import { QrScanCheck } from "@/components/ui/qr-scan-check"

<QrScanCheck
  key={scan.id}
  payload={scan.payload}
  printed={scan.printed}
  resolveRedirect={resolveRedirect}
  onOpen={(target) => setResult(`Opening ${target}`)}
  onCancel={() => setResult("Not opened. Good call.")}
/>

What it catches

  • Destination that differs from the printed site (sticker over a real code)
  • Lookalike and brand-borrowing domains
  • Short links, followed through your resolver
  • App downloads
  • UPI codes: payee, pre-filled amount and "scan to receive a refund" scams

Props

QrScanCheck props
PropTypeDefault
payload* (required)

The decoded text of the scanned code.

string—
printed

What is printed or shown beside the code: a domain ("paybyphone.com") or a merchant name.

string""
trusted

Brands to test for lookalikes.

string[]QR_TRUSTED_DOMAINS
shorteners

Hosts treated as link shorteners.

string[]URL_SHORTENERS
resolveRedirect

Follows a short link and resolves to its final URL (on your server; redirects can't be read from the browser).

(url: string) => Promise<string>—
onOpen

Called with what to open: the URL, the `upi://` link, or the tel/sms/mailto text.

(target: string) => void—
onCancel

Called when the user decides not to open it.

() => void—
locale

Locale for amounts.

string"en-IN"
messages

Any visible string; `types`, `verdict` and `issues` may be partial.

Partial<Omit<QrScanMessages, "types" | "verdict" | "issues">> & { types?: Partial<QrScanMessages["types"]> verdict?: Partial<QrScanMessag…—

* required. Also accepts the native props of <div> (className, aria-*, data-*…), passed through to it.

Accessibility

  • Result is a group labelled by its heading
  • Verdict is in a polite live region with text, icons aria-hidden
  • Open and cancel are buttons

Only what the source does. Test with your own screen reader and content before shipping.

Limitations

This is a UX guard rail. Enforce on the server: Check URLs against a safe-browsing service and verify UPI payees on the server before payment.

  • Doesn't scan the code itself; pass the decoded payload
  • Brand and shortener lists are defaults; pass trusted and shorteners
  • Can't tell whether a site you trust has been compromised

What it stops

Helps catch a fake QR sticker before it opens

Also known as

qr scanner · scan qr · quishing · upi qr · phishing · short link · parking meter · payment qr

Field type

Dependencies

Pairs well with