Using Payment Intents on Android

    Learn how to build an Android application that uses the Payment Intents API to accept card payments.

    There are two ways to accept card payments with the Payment Intents API depending on how you want to complete the payment: automatic confirmation and manual confirmation. See the Payments Intents API Overview for a detailed comparison.

    • The automatic confirmation flow confirms the payment on the client and uses webhooks to inform you when the payment is successful.
    • The manual confirmation flow confirms the payment on the server and lets you fulfill on your server immediately after the payment succeeds.

    Automatic confirmation

    Accepting a card payment with the Payment Intents API using automatic confirmation and the Android SDK is a four-step process, with server-side and client-side actions:

    1. Create a PaymentIntent and make its client secret accessible to your application
    2. Collect card information and create a PaymentMethodCreateParams object
    3. Confirm the PaymentIntent
    4. Authenticate the payment if necessary

    Step 1: Create a PaymentIntent and make its client secret accessible to your application

    When a customer begins the checkout process, create a PaymentIntent on your server. To use the PaymentIntent, you need to make its client secret accessible to your mobile application. Typically, the best approach is to serve it from an HTTP endpoint on your server and then retrieve it on the client side.

    public class PaymentActivity extends Activity {
        private Stripe mStripe;
    
        @Override
        protected void onCreate(@Nullable Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            PaymentConfiguration.init("pk_test_TYooMQauvdEDq54NiTphI7jx");
            mStripe = new Stripe(this,
                PaymentConfiguration.getInstance().getPublishableKey());
    
            // now retrieve the PaymentIntent that was created on your backend
        }
    }
    

    Step 2: Collect card information

    Collect Card details

    In your application, collect card details from the customer. There are a few ways to do this:

    • You can use CardInputWidget or the CardMultilineWidget, calling the getCard method to retrieve a Card object.
    • You can collect payment information through your own form and pass the collected information into a new Card instance.
    • You can use the token returned from Google Pay.

    Create a PaymentMethodCreateParams object

    Once you have the Card object, convert it to a PaymentMethodCreateParams.Card using Card#toPaymentMethodParamsCard and pass it to PaymentMethodCreateParams.create to create a new PaymentMethodCreateParams object. If you already have a PaymentMethod that you would like to associate with the PaymentIntent, you may skip this step. For more information on creating a PaymentMethod, see the Payment Methods API guide for Android.

    The following code demonstrates how to create the PaymentMethodCreateParams object from a Card:

    PaymentMethodCreateParams.Card paymentMethodParamsCard =
        mCardInputWidget.getCard().toPaymentMethodParamsCard();
    PaymentMethodCreateParams cardPaymentMethodCreateParams =
        PaymentMethodCreateParams.create(paymentMethodParamsCard, null);
    

    Step 3: Confirm the PaymentIntent

    To initiate payment collection, you must confirm that your customer intends to pay with the provided payment details.

    Create PaymentIntentParams with a PaymentMethod

    Create a PaymentIntentParams object from the desired PaymentMethod. If you are using a new PaymentMethod, you can accomplish this with the createConfirmPaymentIntentWithPaymentMethodCreateParams method. If you are attaching an existing PaymentMethod, use the createConfirmPaymentIntentWithPaymentMethodId method instead.

    The first parameter is the PaymentMethodCreateParams object created in the previous step. The second parameter is your client secret. The last parameter is the return URL, indicating where the PaymentIntent should return if it is redirected as part of the authentication process. You can associate the desired Activity with the return URL in your application’s AndroidManifest.xml.

    PaymentMethodCreateParams paymentMethodCreateParams =
        PaymentMethodCreateParams.create(card, null);
    PaymentIntentParams paymentIntentParams =
        PaymentIntentParams.createConfirmPaymentIntentWithPaymentMethodCreateParams(
            paymentMethodCreateParams, clientSecret,
            "yourapp://post-authentication-return-url");
    

    Confirm the PaymentIntent

    To finish confirming the payment, pass the PaymentIntentParams object to the confirmPaymentIntentSynchronous method:

    PaymentIntent paymentIntent =
        mStripe.confirmPaymentIntentSynchronous(paymentIntentParams);
    

    The parameter constructors are provided as convenience methods for the most common fields. If you’d like to send additional data, you can use PaymentIntentParams#setExtraParams. Any extra parameters that you add are included in the request to Stripe. To send an e-mail to the customer on payment confirmation, for example, you can use the receipt_email parameter:

    Map<String, Object> extraParams = new HashMap();
    extraParams.put("receipt_email", "{{YOUR_RECEIPT_EMAIL}}");
    paymentIntentParams.setExtraParams(extraParams);
    

    Step 4: Authenticate the payment if necessary

    Some payment methods may require additional authentication steps in order to complete a payment. To determine whether further action is required from your customer, check the status of the PaymentIntent object returned from the confirmation function in the previous step.

    If the PaymentIntent’s status property is requires_action, further action is required from your customer in order to complete the payment. The required next action is determined by inspecting the next_action property. If the required action is redirect_to_url, obtain the URL by calling PaymentIntent#getRedirectUrl. You can open the URL in a browser to accommodate the customer’s completion of the authentication step:

    if (PaymentIntent.Status.RequiresAction == paymentIntent.getStatus()) {
        Uri redirectUrl = paymentIntent.getRedirectUrl();
        if (redirectUrl != null) {
            startActivity(new Intent(Intent.ACTION_VIEW, redirectUrl));
        }
    } else {
      // Show success message
    }
    

    After the user has taken action, they are returned to the your application via the return URL specified in step 3. When declaring an activity that must be able to perform redirects, list an intent-filter item in your AndroidManifest.xml file. This allows you to accept links into your application. Your activity must include android:launchMode="singleTask" or else a new copy of it is opened when your customer comes back from the browser.

    <activity
        android:name=".activity.PollingActivity"
        android:launchMode="singleTask"
        android:theme="@style/SampleTheme">
        <intent-filter>
            <action android:name="android.intent.action.VIEW"/>
            <category android:name="android.intent.category.DEFAULT"/>
            <category android:name="android.intent.category.BROWSABLE"/>
            <data
                android:scheme="yourapp"
                android:host="post-authentication-return-url"/>
        </intent-filter>
    </activity>
    

    To receive information from this event, listen for your activity getting started back up with a new Intent using the onNewIntent lifecycle method. The redirect adds payment_intent and payment_intent_client_secret URL query parameters that your application can use to identify the PaymentIntent associated with the customer’s purchase. You can use PaymentIntentParams.createRetrievePaymentIntentParams to retrieve the status of the PaymentIntent to see if it has succeeded.

    public class PaymentActivity extends Activity {
        @Override
        protected void onNewIntent(Intent intent) {
            super.onNewIntent(intent);
            if (intent.getData() != null && intent.getData().getQuery() != null) {
                final String host = intent.getData().getHost();
                final String clientSecret = intent.getData().getQueryParameter(
                    "payment_intent_client_secret")
    
                final PaymentIntentParams retrievePaymentIntentParams =
                    PaymentIntentParams.createRetrievePaymentIntentParams(
                        clientSecret);
    
                AsyncTask.execute(new Runnable() {
                    @Override
                    public void run() {
                        // retrieve the PaymentIntent on a background thread
                        final PaymentIntent paymentIntent =
                            mStripe.retrievePaymentIntentSynchronous(
                                retrievePaymentIntentParams);
                    }
                });
    
                // If you had a dialog open when your user went elsewhere,
                // remember to close it here.
                mRedirectDialogController.dismissDialog();
            }
        }
    }
    

    Next, test your integration to make sure you’re correctly handling cards that require additional authentication.

    Manual confirmation

    Accepting a card payment with the Payment Intents API using manual confirmation and the Stripe Android SDK is a four-step process, with server-side and client-side actions:

    1. Collect card information and create a PaymentMethod
    2. Create and confirm a PaymentIntent on the server
    3. Redirect and authenticate the payment if necessary
    4. Confirm the PaymentIntent again on the server

    Step 1: Collect card information and create a PaymentMethod

    When a customer begins the checkout process, create a PaymentIntent on your server. To use the PaymentIntent, you need to make its client secret accessible to your mobile application. Typically, the best approach is to serve it from an HTTP endpoint on your server and then retrieve it on the client side.

    public class PaymentActivity extends Activity {
        private Stripe mStripe;
    
        @Override
        protected void onCreate(@Nullable Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            PaymentConfiguration.init("pk_test_TYooMQauvdEDq54NiTphI7jx");
            mStripe = new Stripe(this,
                PaymentConfiguration.getInstance().getPublishableKey());
    
            // now retrieve the PaymentIntent that was created on your backend
        }
    }
    

    Step 2: Create and confirm a PaymentIntent on the server

    Set up an endpoint on your server to receive the request. This endpoint will also be used in Step 4 to handle cards that require an extra step of authentication. It returns a PaymentIntent back to the client.

    Set your endpoint to additionally receive a return_url from the client.

    Step 3: Redirect and authenticate the payment if necessary

    Some payment methods may require additional authentication steps in order to complete a payment. To determine whether further action is required from your customer, check the status of the PaymentIntent object returned from confirmation in the previous step.

    If the PaymentIntent’s status property is requires_action, further action is required from your customer in order to complete the payment. The required next action is determined by inspecting the next_action property. If the required action is redirect_to_url, obtain the URL by calling PaymentIntent#getRedirectUrl. You can open the URL in a browser to accommodate the customer’s completion of the authentication step:

    if (PaymentIntent.Status.RequiresAction == paymentIntent.getStatus()) {
        Uri redirectUrl = paymentIntent.getRedirectUrl();
        if (redirectUrl != null) {
            startActivity(new Intent(Intent.ACTION_VIEW, redirectUrl));
        }
    } else {
      // Show success message
    }
    

    After the user has taken action, they are returned to the your application via the return URL. When declaring an activity that must be able to perform redirects, list an intent-filter item in your AndroidManifest.xml file. This allows you to accept links into your application. Your activity must include android:launchMode="singleTask" or else a new instance is launched when your customer comes back from the browser.

    <activity
        android:name=".activity.PollingActivity"
        android:launchMode="singleTask"
        android:theme="@style/SampleTheme">
        <intent-filter>
            <action android:name="android.intent.action.VIEW"/>
            <category android:name="android.intent.category.DEFAULT"/>
            <category android:name="android.intent.category.BROWSABLE"/>
            <data
                android:scheme="yourapp"
                android:host="post-authentication-return-url"/>
        </intent-filter>
    </activity>
    

    To receive information from this event, override Activity#onNewIntent(). The redirect adds payment_intent and payment_intent_client_secret URL query parameters that your application can use to identify the PaymentIntent associated with the customer’s purchase. Use PaymentIntentParams.createRetrievePaymentIntentParams() to retrieve the status of the PaymentIntent to see if it has succeeded.

    public class PaymentActivity extends Activity {
        @Override
        protected void onNewIntent(Intent intent) {
            super.onNewIntent(intent);
            if (intent.getData() != null && intent.getData().getQuery() != null) {
                final String host = intent.getData().getHost();
                final String clientSecret = intent.getData().getQueryParameter(
                    "payment_intent_client_secret")
    
                final PaymentIntentParams retrievePaymentIntentParams =
                    PaymentIntentParams.createRetrievePaymentIntentParams(
                        clientSecret);
    
                AsyncTask.execute(new Runnable() {
                    @Override
                    public void run() {
                        // retrieve the PaymentIntent on a background thread
                        final PaymentIntent paymentIntent =
                            mStripe.retrievePaymentIntentSynchronous(
                                retrievePaymentIntentParams);
                    }
                });
    
                // If you had a dialog open when your user went elsewhere,
                // remember to close it here.
                mRedirectDialogController.dismissDialog();
            }
        }
    }
    

    Step 4: Confirm the PaymentIntent again on the server

    Using the same endpoint you set up in Step 2, confirm the PaymentIntent again to finalize the payment and fulfill the order.

    Using Google Pay with the Payment Intents API

    To integrate with Google Pay, use the token returned by your Google Pay integration to confirm the PaymentIntent. Create a PaymentMethodCreateParams object with PaymentMethodCreateParams.create(), passing in the ID of the token to PaymentMethodCreateParams.Card#create(). After that, you can confirm the PaymentIntent as normal.

    private PaymentIntentParams confirmPaymentIntent(
            @NonNull String paymentIntentClientSecret,
            @NonNull PaymentMethod.BillingDetails billingDetails) {
        PaymentMethodCreateParams paymentMethodCreateParams =
                PaymentMethodCreateParams.create(
                        PaymentMethodCreateParams.Card.create("tok_visa")
                        billingDetails);
    
        // confirm PaymentIntent
    }
    

    Test the integration

    It’s important to thoroughly test your Payment Intents API integration to make sure you’re correctly handling cards that require additional authentication and cards that don’t to ensure the smoothest checkout experience for your users. Use the test cards in test mode to validate your integration when 3D Secure is: required, required and the payment is declined, and not required. Use these card numbers with any expiration date in the future and any three digit CVC code.

    Card Number 3D Secure usage Description
    4000000000003220 Required This test card requires 3D Secure 2 on all transactions and will trigger 3D Secure 2 in test mode.
    4000008400001629 Required This test card requires 3D Secure 2 but payments will be declined with a card_declined failure code after authentication.
    4000000000003055 Supported This test card supports but does not require 3D Secure 2 and will not require additional authentication steps in test mode.

    Use these cards in your application or the payments demo to see the different behavior.

    Next steps

    You now have an Android integration that can accept card payments with the Payment Intents API, prompting customers for authentication as needed.

    Questions?

    We're always happy to help with code or other questions you might have. Search our documentation, contact support, or connect with our sales team. You can also chat live with other developers in #stripe on freenode.

    Was this page helpful? Yes No

    Send

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

    On this page