Skip to main content

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.

2. Create the PayPal button

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.

4. Render the button

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