Prerequisites
- An active Payrails session (see Quick Start)
- A session init payload that includes a PayPal payment option (
paymentMethodCode: "payPal")
- Kotlin + Jetpack Compose for rendering the button
New PayPal Payment
1. Initialize a session
redirectSessionLifecycle.onSessionExpired is optional here — PayrailsPayPalButtonDelegate.onPaymentSessionExpired is the primary hook for PayPal session refresh. Configure onSessionExpired if you also use 3DS or generic redirect payment methods in the same session.
3. Set the delegate
onPaymentSessionExpired is required. After a PayPal cancellation or timeout the session cannot be reused — you must reinitialize before the user can attempt payment again.
The button renders in PayPal’s branded gold (#ffc439) with the PayPal wordmark. No additional styling configuration is required.
5. Handle the payment result
When the user taps the button, the SDK opens the PayPal authorization page in a Chrome Custom Tab. After the user approves or cancels, the Activity resumes and the SDK polls for the final execution status. Your delegate receives onAuthorizeSuccess, onAuthorizeFailed, or onCancelled + onPaymentSessionExpired accordingly.
Storing a PayPal Account for Future Use
To request that the PayPal account is saved for future payments, set saveInstrument = true before the user taps:
After a successful payment with saveInstrument = true, the account appears in session.getStoredInstruments(forType = PaymentMethod.payPal).
Charging a Stored PayPal Account
Stored PayPal accounts are charged directly without opening a browser. No user interaction in the browser is required.
1. Retrieve stored instruments
Each StoredInstrument exposes:
id — the instrument identifier
email — the PayPal account email
displayName — server-provided display name (typically the email)
isDefault — whether this is the holder’s default instrument
2. Build your instrument picker
The SDK does not provide a pre-built instrument picker UI. Build your own and let the user select an account.
3. Trigger payment with the stored instrument
The result is delivered through the same delegate: onAuthorizeSuccess or onAuthorizeFailed. onCancelled and onPaymentSessionExpired do not fire for stored instrument payments — there is no browser session to cancel.
Troubleshooting
Button taps do nothing after a cancelled payment
The Payrails session is expired after a PayPal cancellation. Make sure your onPaymentSessionExpired implementation fetches fresh init data and calls Payrails.createSession() before the user retries.
onAuthorizeFailed fires immediately after the Custom Tab closes
If the user closes the Custom Tab before completing the PayPal flow (without pressing the PayPal cancel button), the SDK’s grace reconciliation window applies. The polling resolves as authorizeFailed after a brief delay. This is expected — the session is still valid in this case and the user can retry without refreshing.
IllegalStateException: session not initialized on createPayPalButton()
Payrails.createPayPalButton() must be called after Payrails.createSession() completes successfully.
See Also
Last modified on September 30, 2026