Managing Customer Information in the Android SDK

Allow customers to securely store and update payment information.

This guide assumes you've already followed the Getting Started section of our main tutorial to install and configure our SDK.

This guide demonstrates how to build your app's customer payment management flow using PaymentSession, a class designed to make building your app's checkout flow as easy as possible. It handles collecting, saving, and reusing your user's payment details.

Prepare your API

Our prebuilt UI elements operate on the assumption that you have a single Customer object for each of your users. We strongly recommend you create this Customer at the same time you create your user on your own backend, so that every user is guaranteed to have an associated Customer. (This is fine even if you don't collect your user's payment information when they sign up—it's totally OK to have a Customer without any attached cards.)

Our prebuilt UI elements require an ephemeral key, a short-lived API key with restricted API access. You can think of an ephemeral key as a session, authorizing the SDK to retrieve and update a specific Customer object for the duration of the session. To provide an ephemeral key to the SDK, you'll need to expose a new API endpoint on your backend. This endpoint should create an ephemeral key for the current Stripe customer, and return the key's unmodified response as JSON.

When the SDK requests an ephemeral key, it specifies the version of the Stripe API that it expects the response to come from. Your endpoint should accept an api_version parameter, and use the specified API version when creating the ephemeral key. This ensures that the SDK always receives the correct ephemeral key response from your backend. You can consult our Example Backend to see this in practice.

After you've added an ephemeral key endpoint to your backend, you'll need a way for your Android app to communicate with this endpoint. In your app, you should make your API client class implement the EphemeralKeyProvider interface, which defines a single method, createEphemeralKey. When implementing this method, be sure to pass the apiVersion parameter along to your ephemeral keys endpoint. You can consult our Example App to see this in practice.

After creating an EphemeralKeyProvider, initialize a CustomerSession. Think of CustomerSession as a Stripe communication manager for a single logged-in session of a customer. A CustomerSession talks to your backend to retrieve an ephemeral key (via its key provider), and uses that key to manage retrieving and updating its Stripe customer on your behalf.

ExampleEphemeralKeyProvider.java

CustomerSession.initCustomerSession(
new ExampleEphemeralKeyProvider(
new ExampleEphemeralKeyProvider.ProgressListener() {
@Override
public void onStringResponse(String string) {
if (string.startsWith("Error: ")) {
// Show the error to the user.
}
}
}));

CustomerSession automatically prefetches its customer once its key provider has been set. If you'd like to take advantage of preloading your customer's information, initialize your CustomerSession instance earlier, before your user enters your payment flow. If your current user logs out of the app, you should clear the current CustomerSession singleton using the clearInstance method. When a new user logs in, you can re-initialize the instance. On your backend, be sure to create and return a new ephemeral key for the customer object associated with the new user.

Implement your app's payment flow using PaymentSession

Our SDK provides a class called PaymentSession, which is designed to make building your app's checkout flow as easy as possible. It handles collecting, saving, and reusing your user's payment details, and can also be used to collect shipping info. Think of it as the data source for your checkout activity—it handles asynchronously retrieving the data you need, and notifies its listener when its UI should change.

Setting the listener, configuration, and host activity

To work with PaymentSession, you'll need to write a class that conforms to PaymentSessionListener, and pass a PaymentSessionConfig object to the init method. (Note, the code samples in this section are simply examples – your own implementation may differ depending on the structure of your app).

The PaymentSessionConfig object is created using a Builder pattern, and has the following fields, all of which are optional.

setShippingInfoRequired(boolean required)

This method sets whether or not the PaymentSession requires the user
to have a valid shipping address. The default value is true.

setShippingMethodsRequired(boolean required)

This method sets whether or not the PaymentSession requires the user
to select a shipping method (Overnight, Standard Shipping, etc). The default value is true. You must set these values later.

setPrepopulatedShippingInfo(ShippingInformation shippingInfo)

Sets a default shipping address for your customer, which you can get from your CustomerSession or your own records. The Shipping information screen will start with this information already filled out.

setHiddenShippingInfoFields(List hiddenFields)

Sets which address fields should be hidden in the shipping information screen. Values must be from among the labels listed in ShippingInfoWidget.. All fields will be shown if this list is empty. Note that not all fields can be hidden, such as country or name.

setOptionalShippingInfoFields(List hiddenFields)

Sets which address fields should be listed as optional in the shipping information screen. Values must be from among the labels listed in ShippingInfoWidget.. All fields will be required if this list is empty. Note that not all fields can be optional, such as country or name.

Having created the PaymentSessionConfig, you'll need to create your PaymentSessionListener, which has 3 required methods:

void onPaymentSessionDataChanged(@NonNull PaymentSessionData data)

This method is called whenever the PaymentSession's data changes, e.g., when the user selects a new payment method or enters shipping info. This is a good place to update your UI:

This method should also check for whether or not the payment data is complete, according to the PaymentSessionConfig specified. If you receive an update for which PaymentSessionData#isPaymentReadyToCharge() returns true, you can immediately send message to your server to complete the charge.

void onCommunicatingStateChanged(boolean isCommunicating)

This method is called whenever the network communication state has changed. We recommend showing a spinner or infinite progress bar when it is set to true

Note that the init function returns a boolean value to let you know whether or not the initialization was successful. The only reason for failure is if you have not already set up a CustomerSession, which must come first.

Once the PaymentSession has been initialized, you can use it to make the following calls.

void presentPaymentMethodSelection()

This method presents the PaymentMethodsActivity to allow the user to choose a stored form of payment or to add more forms of payment and select from among those. It will automatically be pre-populated with values from your CustomerSession, so previously existing payment sources will appear without any extra work.

void presentShippingFlow()

This method presents the PaymentFlowActivity to allow the user to enter shipping information, if such information is required according to your PaymentSessionConfig. Note that in order to validate the input shipping address, you'll need to register a local BroadcastReceiver.

When you broadcast your response to the shipping validation request, you can then send down your (potentially) dynamically created shipping methods. This allows you to validate whether or not a customer is eligible for expedited shipping, for instance, based on the input shipping address. This is also the place to filter out locations that you cannot ship to, for instance if you are restricted to domestic customers.

Completing the purchase

When you have detected that the PaymentSession#isPaymentReadyToCharge() has come back true, you are free to charge the payment method immediately with the data in the PaymentSessionData object using a call to your server. To make full use of the PaymentSession and guard against duplicate payment requests, we recommend making use of the completePayment method.

void completePayment(@NonNull PaymentCompletionProvider provider)

This method will call the complete payment method on the provider, talking to your server to make the purchase, and recording the result data in the PaymentSessionData To use this method, you must provide a PaymentCompletionProvider, which requires the implementation of just one method:

This method will be invoked with the current PaymentSessionData object, and the results will be returned to the PaymentResultListener (which you do not need to create). Any errors will be returned to your original PaymentSessionListener, and a successful update will result in a call to the same onPaymentSessionDataChanged method used to update the listener about any other change in the PaymentSessionData. To verify results, call PaymentSessionData#getPaymentResult(), which returns a PaymentResult.

Managing PaymentSession in a host Activity

In order to get updates for the PaymentSessionData object and to handle state during Activity lifecycle, you'll need to hook up your PaymentSession instance to a few key parts of your host Activity lifecycle. The first is in onActivityResult

This is all you need to do to get updates from the various activities launched by PaymentSession. Any updates to the data will be reported to the listener attached during the initialization of the PaymentSession. To handle lifecycle events in your activity that require the saving and restoring of state, the session can be attached and re-initialized as follows:

Finally, don't forget to destroy the PaymentSession when your activity is destroyed. This clears out any listeners and references that you may have given the PaymentSession object that could have been put in different threads.