Skip to main content
Drive checkout from your own UI — a custom layout, a ViewModel-driven flow, your own “Pay” button — instead of rendering a prebuilt SDK button component. The single public payment trigger is PayrailsPaymentLauncher: you draw the controls, the SDK owns the post-tap work (Google Pay sheet, 3DS / PayPal / redirect Custom Tab, polling).
There is no public Session.authorize(...). Payment execution is launcher-only, so a single authorize(...) call handles both frictionless and 3DS outcomes — you never branch on whether a charge will need a step-up. See Custom UI: the launcher and the internal client.

Prerequisites

  • An active Payrails session (see Quick Start) — hold the Session returned by Payrails.createSession(...).
  • A ComponentActivity host. The launcher is lifecycle-bound; it cannot live in a bare ViewModel (it registers a Google Pay Activity Result contract), but your ViewModel can drive when it fires.
  • For stored-instrument payments: at least one saved instrument (see How to Tokenize a Card).

Steps

1. Create the launcher early

Construct it in onCreate (or a Compose remember) so its Activity Result contract registers before the host is STARTED:

2. Charge a stored instrument from your own UI

The most common headless case — no SDK button, your own list:
A frictionless charge completes with no UI; if the instrument requires 3DS, the launcher opens the Custom Tab and still resolves to one terminal result — you write the same code either way.

3. Charge a fresh card you encrypted yourself

If you collect and encrypt card data with the client-side encryption library, pass the already-encrypted string. The SDK exposes no encryption API, and raw card fields never cross this call:

4. Trigger other methods by type

5. Handle the result

Every authorize(...) resolves to exactly one ActionResult, delivered to the callback from step 1:

Full example — stored-instrument checkout driven from a ViewModel

The ViewModel owns selection and state; the activity owns the launcher and fires it:

Troubleshooting

Problem: The launcher throws when created Solution: Payrails.createPaymentLauncher(...) must be called from Activity.onCreate (or rememberPayrailsPaymentLauncher during composition). Registering the Google Pay Activity Result contract after the activity is STARTED is not allowed by the Android Activity Result API. Problem: ActionResult.Failed with code == UNKNOWN_ERROR (rawError sdkNotInitialized) Solution: The session was destroyed or replaced (for example a newer createSession() superseded it). Obtain a fresh Session from Payrails.createSession(). Problem: ActionResult.Failed with code == UNKNOWN_ERROR (rawError unsupportedPayment) Solution: The payment method is not configured on the session. Call session.getPaymentMethodConfig() to confirm what is available before triggering.

See also

Last modified on September 30, 2026