Prerequisites
- An active Payrails session (see Quick Start)
- A session init payload with
vaultConfigurationand asaveInstrumentlink (provided by the Payrails backend — contact Payrails to enable vault configuration for your merchant account) - Kotlin + Jetpack Compose for rendering the card form
Steps
1. Initialize a session
2. Create a card form (no payment button required)
CardPaymentButton is not needed for tokenization. The card form collects and validates card fields independently.
3. Render the card form and a save button
session.tokenize(...) is the primary tokenization API (mirroring the iOS SDK). TokenizationRequest.Card(cardForm) selects the card currently entered in the form.
Callback variant (without coroutines)
If you are not calling from a coroutine, use the callback overload. Exactly one of the three callbacks fires once, on the main thread:onCancelled fires only on cancellation (coroutine/session-scope) — card validation and network failures are delivered to onFailed.
4. Choose a FutureUsage value
5. Use the returned instrument ID
Theresponse.id is the instrument identifier. Pass it to setStoredInstrument for future payments, or use it with the instrument management API:
Tokenize with Google Pay
Google Pay tokenization uses the samesession.tokenize(...) API with a TokenizationRequest.GooglePay case. Because a Google Pay token can only be obtained through an Activity-result launcher that Android requires to be registered up front, you create a presenter in your Composable and pass it to tokenize:
SaveInstrumentResponse. User dismissal cancels (the callback overload’s onCancelled, or a CancellationException from the suspend variant).
For a compliant, Google-branded button with no wiring, use GooglePayTokenizeButton instead — it renders only when Google Pay is available for the session:
Google’s brand guidelines require the official Google Pay button to launch the Google Pay flow. Prefer
GooglePayTokenizeButton (or a Google Pay–branded button) over a fully custom button.Verify it worked
Check that the response contains a valid ID and"active" status:
Troubleshooting
Problem:PayrailsError.invalidCardData is thrown
Solution: Card form validation failed. The form automatically shows inline field errors — the user needs to correct the highlighted fields before retrying. No manual error display is needed.
Problem: PayrailsError.missingData("Vault configuration with providerConfigId is required...")
Solution: The session init payload does not include vaultConfiguration. Contact Payrails to enable vault configuration for your merchant account.
Problem: PayrailsError.missingData("holderReference is required...")
Solution: The session init payload does not include holderReference. Ensure your client-init request includes a holder reference.
Alternative: pay directly with the saved instrument
Once a card is tokenized, you can charge it through the button flow shown above (payButton.setStoredInstrument(...) + payButton.Render()), or skip the button entirely
and charge it from your own UI with PayrailsPaymentLauncher:
launcher.authorize(storedInstrument = ...) is the way to charge an existing stored
instrument from a custom layout or ViewModel-driven flow — and, because the launcher holds
a presenter, it transparently handles a 3DS step-up if the issuer requires one. See
How to Run a Payment Without an SDK Button.
See also
- Understanding Card Tokenization — why tokenization and payment are separate flows, and what
storeInstrumentandFutureUsagemean - Card Tokenization API Reference — complete reference for
TokenizeOptions,FutureUsage, andSaveInstrumentResponse - Stored Instruments — how to retrieve and pay with saved instruments
PayrailsPaymentLauncher— the public payment-execution API