@fraudcheck/capture-flow
v0.2.2
Published
Embeddable document capture + liveness flow (CaptureFlow) for mounting inside your own React app.
Downloads
306
Readme
@fraudcheck/capture-flow
Document capture + liveness verification component for React --- mount <CaptureFlow>
directly in your own app against a transaction id your backend already created.
Install
npm install @fraudcheck/capture-flowUsage
import { CaptureFlow } from '@fraudcheck/capture-flow'
import '@fraudcheck/capture-flow/style.css'
function VerifyPage() {
return (
<CaptureFlow
transactionId={myTransactionId}
showCompletionScreen={false} // render your own "done" UI instead of ours
onComplete={({ transactionId, results }) => {
// session finished --- the meaningful part is that this fired at all; the
// backend already has the authoritative data (status flipped to PROCESSING
// server-side by now). results is just supporting detail, not something to
// build UI around.
}}
onError={(err) => {
// session bootstrap failed, or the final PROCESSING PATCH failed after retries
}}
onStepChange={({ step, index, total }) => {
// 'welcome' | 'fields' | 'document' | 'liveness'
}}
/>
)
}transactionId is required --- created however your backend already creates one today.
The SDK never mints a transaction id and never reads one from the URL. All callbacks are
optional and fire alongside CaptureFlow's own UI, never instead of it.
showCompletionScreen (default true) is the one exception --- set it false to
suppress just the final "All done" screen and show your own instead, driven by
onComplete. Every other screen in the flow is unaffected.
Branding
CaptureFlow automatically fetches per-transaction white-label branding (logo, colors,
company name, a "powered by" toggle, font) and applies it --- nothing to configure, it's
keyed off the transactionId you already pass in. Applies to: the logo everywhere it
appears, the primary button/accent colors, the "powered by" footer text, and font family
on the main welcome/completion shells. Not applied: page background or text color ---
deliberately excluded after theming those broke readability for at least one real brand
(white text over a fixed light background once the background override was removed).
Failure-safe by design --- no transaction id yet, the brand lookup fails, times out, or returns nothing usable, all collapse to the same default Fraudcheck look. Branding can only ever be added on top of a working default, never break it.
The brand API is rate-limited (5 requests/minute). Every call still attempts a live fetch first (so a page reload gets current data, not something stale), but a successful result is cached per transaction id and used as the fallback specifically when a live fetch fails --- most importantly on a 429 from the cap itself. Concurrent calls for the same transaction (e.g. React StrictMode's double-invoked effects in dev) are deduped to one request.
Known gap: CORS isn't configured on the brand API host, unlike the other backends this package calls. Same-origin (a page hosted by Fraudcheck) is unaffected; a cross-origin fetch from this package running on your own domain will be blocked by the browser. Falls back to the default theme the same safe way as any other failure --- not broken, just unbranded until that gets a CORS allowlist entry backend-side.
Desktop / QR handoff
On a detected desktop/laptop browser, CaptureFlow opens on a QR code screen instead of
the normal welcome screen --- camera/liveness capture is a much better experience on a
phone. Scanning it continues the same transaction there; there's also a "Continue here
instead" button to skip it and proceed on the current device. While the QR screen is
showing, it polls the transaction in the background and automatically advances --- the
moment it detects the transaction was completed elsewhere, onComplete fires exactly as
it would finishing normally on one device.
The QR code always points at Fraudcheck's own hosted capture link for that transaction
(https://capture.apps.fraudcheck.co.za/{transactionId}) — a working page regardless of
whether this is running as the hosted app or embedded via the SDK in your own page.
This is an early prototype, with known gaps worth knowing about:
- Device detection is UA-sniffing --- not spoof-proof, but the failure mode is just an unnecessary or missed QR offer, nothing worse.
- "Continue here instead" doesn't persist --- a page reload brings the QR screen back.
Requirements
Your app / build setup
- React 18 or 19 (peer dependency --- bring your own copy, this package doesn't bundle one).
- A bundler that understands
import.meta.url-relative asset resolution: Vite, Webpack 5+, or Rollup. Not Create React App without ejecting --- its webpack 4 config doesn't handle this pattern. - Add the CSS import yourself (
import '@fraudcheck/capture-flow/style.css') --- it's not auto-injected. Skip it and CaptureFlow renders unstyled.
One-time step before your production build
cp -r node_modules/@fraudcheck/capture-flow/dist-lib/{mediapipe,onnx-wasm,models,zxing} public/Required. The on-device ML libraries (mediapipe, onnxruntime-web, zxing) pick exact WASM
filenames at runtime via feature detection, which no bundler's static analysis can trace
through --- so they can't be auto-discovered and copied for you. Copy them into wherever
your bundler serves static files from (shown here as public/, the Vite/CRA convention)
before building.
If you use Vite for your own dev server
// vite.config.js
export default defineConfig({
optimizeDeps: { exclude: ['@fraudcheck/capture-flow'] },
})Without this, Vite's dev-time dependency pre-bundling relocates the package and breaks the same asset-path resolution the copy step above depends on. Not verified whether Webpack/Next.js dev servers need an equivalent --- only tested against Vite.
Deployment environment
- HTTPS in production (or
localhostin dev) ---getUserMedia(camera access) is blocked outright by the browser on insecure origins, not something this package controls. - If you run a Content-Security-Policy header, it needs
connect-srcallowances for*.fraudcheck.co.zaand*.fraudcheckonline.co.za, and likely ascript-src/worker-srcallowance for WASM ('wasm-unsafe-eval'or equivalent for your CSP version).
Backend prerequisite
- A valid
transactionIdthat already exists server-side before you mountCaptureFlow. This doubles as the access control for the flow --- the backend APIs are gated only by possession of an unguessable 32-char-hex transaction id, not a separate API key.
Known unverified spot
- CORS is confirmed open (checked directly) for the
consumer-serviceandliveness-apibackends. Not confirmed for thecrop/extract/classifybackends, which only fire during document capture. A CORS error (not a 404) specifically during document capture means those need a CORS allowlist update on the backend --- not fixable from this package.
Size
Install is ~69MB, almost entirely the bundled ONNX/mediapipe/WASM models. Your
node_modules and deploy artifact both grow by that much --- expected, not a bug.
