Collecting Card Details on Android

    Learn how to build a Stripe integration for Android that uses Charges and tokenization.

    Accepting a card payment with Charges and the Android SDK is a two-step process, with server-side and client-side actions.

    1. Securely collect payment information
    2. Tokenize the card information

    Step 1: Securely collect payment information

    There are a few ways to collect payment details from a customer in your app:

    Using the card input widget

    Stripe’s Android SDK provides a set of standard user interface components for securely collecting card information from customers. The following example demonstrates how to use the CardMultilineWidget, a custom view which collects the customer’s card number, CVC, and expiration date.

    Android Card Input Widget

    You can include it in any view’s layout file. It has a minimum width of 320px.

    <com.stripe.android.view.CardMultilineWidget
        android:id="@+id/card_widget"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />
    

    If the customer’s input is valid, CardMultilineWidget#getCard() returns a Card instance; otherwise, it returns null.

    private void onCardSaved() {
        final Card cardToSave = cardWidget.getCard();
        if (cardToSave != null) {
            // tokenize card (see below)
            tokenizeCard(cardToSave);
        }
    }
    
    private fun onCardSaved() {
        val cardToSave = cardWidget.card
        if (cardToSave != null) {
            // tokenize card (see below)
            tokenizeCard(cardToSave)
        }
    }
    

    If you have any other data that you would like to associate with the card, such as name, address, or ZIP code, you can put additional input controls on your layout and add them directly to the Card object.

    cardToSave = cardToSave.toBuilder().name("Customer Name").build();
    cardToSave = cardToSave.toBuilder().addressZip("12345").build();
    

    Styling the card widget

    The CardInputWidget is a custom view which contains several customized Android EditText elements. If you set values for EditText attributes in your Theme, they will be picked up by the CardInputWidget.

    There are also two special parameters that you can set: the card tint and the error text color. To set these values, make sure to add the res/auto namespace in the layout file where you have created the CardInputWidget. You can use any legal value for the namespace, such as stripe.

    <LinearLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:stripe="http://schemas.android.com/apk/res-auto"
        ...
        >
    </LinearLayout>
    

    You can then apply your preferred values for the color of the empty card hint item (before a brand has been detected) and as a text error color. By default, the card tint is identical to the hint text color of your theme, and the Stripe library selects a text error color from two different shades of red, depending on how dark the background of your theme is.

    To apply your custom colors, simply add them to the CardInputWidget’s XML declaration.

    <com.stripe.android.view.CardInputWidget
        android:id="@+id/card_input_widget"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        stripe:cardTint="@android:color/holo_purple"
        stripe:cardTextErrorColor="@android:color/holo_orange_dark" />
    

    Changing the text and background colors

    To change the text colors, create a theme with the colors you would like and apply it to the CardInputWidget. The background color can be set using the android:background property, either directly on the widget, or as part of a theme. The following example sets both the background and text colors in the theme so that they can be easily applied wherever you use CardInputWidget in your app.

    <style name="CardWidgetStyle" parent="@android:style/Theme.DeviceDefault">
        <item name="android:background">#0000FF</item>
        <item name="editTextStyle">@style/EditTextOverride</item>
        <item name="android:editTextStyle">@style/EditTextOverride</item>
    </style>
    
    <style name="EditTextOverride" parent="@android:style/Widget.EditText">
        <item name="android:textColor">#FF0000</item>
        <item name="android:textColorHint">#00FF00</item>
    </style>
    

    Then, apply the style to the CardInputWidget to change its text, text hint, and background colors.

    <com.stripe.android.view.CardInputWidget
        android:id="@+id/card_input_widget"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:theme="@style/CardWidgetStyle" />
    

    The above example creates a CardInputWidget with a blue background, red text, and green text hints.

    Building your own form

    If you prefer to build your own custom form for collecting and validating card information, manually instantiate the Card class and pass in raw card information. Collect at least your customers’ card numbers and expiration dates. Stripe strongly recommends collecting the CVC. You can optionally collect the user’s name and billing address for additional fraud protection.

    Once you’ve collected a customer’s information, exchange the information for a Stripe token.

    Creating & validating cards from a custom form

    To create a Card object from data you’ve collected from other forms, you can create the object with its constructor.

    import com.stripe.android.model.Card;
    
    //...
    //...
    public void onAddCard(String cardNumber, String cardExpMonth,
                          String cardExpYear, String cardCVC) {
      final Card card = Card.create(
        cardNumber,
        cardExpMonth,
        cardExpYear,
        cardCVC
      );
    
      card.validateNumber();
      card.validateCVC();
    }
    
    

    The Card instance contains some helpers to validate that the card number passes the Luhn check, that the expiration date is the future, and that the CVC looks valid. You’ll probably want to validate these three things at once, so we’ve included a validateCard function that does so.

    final Card card = Card.create("4242424242424242", 12, 2020, "123");
    // Remember to validate the card object before you use it to save time.
    if (!card.validateCard()) {
      // Do not continue token creation.
    }
    

    Google Pay

    You also have the option of using Google Pay to collect payment information, allowing customers to use credit or debit cards that are already associated with their Google account.

    Step 2: Tokenize the card information

    First, get your Card object, which can be done with a custom form:

    final Card card = Card.create("4242424242424242", 12, 2020, "123");
    // Remember to validate the card object before you use it to save time.
    if (!card.validateCard()) {
      // Do not continue token creation.
    }
    

    You can also simply take the data from a CardInputWidget.

    // Remember that the card object will be null if the user inputs invalid data.
    Card card = mCardInputWidget.getCard();
    if (card == null) {
      // Do not continue token creation.
    }
    

    The next step is sending the customer’s payment information to Stripe and exchanging it for a token, which you can send to your server and use to create a charge. Tokenization ensures that no sensitive card data ever needs to touch your server, so that your integration remains PCI-compliant.

    See Using Payment Intents on Android for more information on integrating with the Payment Intents API.

    The following code shows how to use Stripe#createToken(). The method takes a Card instance as the first parameter. The second parameter is a ApiResultCallback<Token> instance that the client invokes on success or failure. When tokenization completes successfully, send the returned token ID to your server.

    private void tokenizeCard(@NonNull Card card) {
        stripe.createToken(
            card,
            new ApiResultCallback<Token>() {
                public void onSuccess(@NonNull Token token) {
                    // send token ID to your server, you'll create a charge next
                }
            }
        );
    }
    
    private fun tokenizeCard(card: Card) {
        stripe.createToken(
            card,
            object : ApiResultCallback<Token> {
                override fun onSuccess(token: Token) {
                    // send token ID to your server, you'll create a charge next
                }
            }
        )
    }
    

    Set up an endpoint on your server that can receive an HTTP POST call for the token. In the onActivityResult method (for Google Pay) or the onSuccess callback (when using your own form), you’ll need to POST the supplied token to your server. Make sure any communication with your server is SSL secured to prevent eavesdropping.

    Take a look at the full example application to see everything put together.

    Next steps

    Now that you can collect and tokenize card details in your Android app, try creating your first charge.

    Was this page helpful?

    Thank you for helping improve Stripe's documentation. If you need help or have any questions, please consider contacting support.

    On this page