---
id: how-it-works
title: How ripper checkout works
summary: The pieces, what happens when a shopper pays, and the words for each outcome.
faces: ["public", "agent"]
section: shared
group: Get started
order: 5
next: ["quickstart"]
---
# How ripper checkout works

Read this once and the rest of the docs will be shorter.

## The pieces

**The loader** is one script tag, `r.js`, served from `https://js.ripper.dev`. It reads your publishable key
from its own tag, fetches a small manifest, and inserts the runtime. `window.ripper` works from the first
line of your page: calls made before the runtime has loaded are queued and replayed in order, so you never
have to wait for it.

**The runtime** is the checkout itself — the card fields, the panels, the payment. The loader brings it in;
you never reference it directly.

**The npm package** is `ripperpay`. `loadRipper()` gives you the same runtime through an import instead of a
script tag, for pages that build their JavaScript.

**The React component** is `RipperCheckout`, from `ripperpay/react`. It is the runtime with props.

**The Stripe compatibility layer** is for pages already written against Stripe.js. It accepts what those
pages already send, so an existing integration can move with fewer changes. It is reached by its own loader
path, and the native SDK is what to write against for anything new.

## What happens when a shopper pays

You call `collect()` with an amount. The checkout needs a session, and gets one in whichever way you set up:
created in the browser from your publishable key, or created on your server and handed over. It renders the
card fields, runs 3-D Secure where the card asks for it, confirms the payment, and shows the shopper the
outcome.

`collect()` resolves rather than rejecting for any payment outcome, including a decline: a refusal is a
result, not an exception. The one exception is the runtime failing to load at all.

## The words for an outcome

A payment that was taken has status `captured`. Prose in these docs may say "paid"; the wire word is
`captured`.

A payment that was **held** rather than taken has status `held` and a capture state of `authorised`, and
`collect()` reports it to your page as `authorised`. The money is reserved and not yet taken. Shopper-facing
copy says "reserved"; the merchant verbs are capture and void.

A payment still being confirmed is `pending`. One that was refused is `declined`, and one that failed on our
side is `failed`.

## Where the outcome is decided

On your server, not in the browser. The browser tells your page what happened so it can show the shopper
something useful, but the decision your business acts on — fulfil, ship, email — should come from reading
the session or the payment from your server, or from the webhook that tells you without being asked.

That is not distrust of the shopper. It is that a browser can be closed, refreshed or driven by someone
else, and your server cannot.

## Three ways in

Most integrations use more than one, and they are not alternatives so much as layers.

- **The checkout on your page** — the loader, the runtime, React or Next.js. Start at the
  [Quickstart](/quickstart).
- **The API from your server** — create sessions, read payments, receive webhooks. Start at the
  [API reference](/api/reference).
- **The hosted payment page** — no code at all, a link you send. See [The hosted page](/js/hosted-page).

If you are using an AI coding assistant, point it at `/llms.txt` and it will find the rest.
