Android Integration

Our Android libraries let you easily accept mobile payments inside any Android app. If you need help, check out our answers to common questions or chat live with other developers in #stripe on freenode.

Stripe has created a Java library for Android, allowing you to easily submit payments from an Android app. With our mobile library, we shoulder the burden of PCI compliance by eliminating the need to send card data directly to your server. Instead, our libraries send the card data directly to our servers, where we can convert them to tokens.

Your app will receive the token back, and can then send the token to an endpoint on your server, where it can be used to process a payment, establish recurring billing, or merely saved for later use.

We support Android back to version 4, and the library has no external dependencies.

Installation

Installing the Stripe Android library differs whether using Android Studio or Eclipse. For Android Studio, you don’t need to clone a repo or download any files, just add the following to your app’s build.gradle file, inside the dependencies section.

compile 'com.stripe:stripe-android:+'

To install the Stripe Android library for Eclipse:

  1. First download the stripe-android libraries.
  2. Be sure you’ve installed the Android SDK with a minimum of API Level 17 and android-support-v4.
  3. Import the stripe folder into Eclipse.
  4. In your project settings, add the stripe project under the “Libraries” section of the “Android” category.

Collecting credit card information

At some point in the flow of your app, you’ll want to obtain payment details from the user. There are a couple ways to do this:

Instructions for each route follows, although you may want to write your app to offer support for both.

Using Android Pay beta

Through Android Pay, you can access payment information stored in your customers’ Google accounts. You can start integrating Android Pay now to get your app ready for the Android Pay launch. Until the launch, you can use the Stripe test mode API with Android Pay but not the live mode API.

Setting up your app

You’ll first need to obtain credentials and a client ID for your app, as explained in the Android Pay API Tutorial. You will also need to set up Google Play Services, using version 7.3 or higher.

Collecting payment information through Android Pay

The first thing the application needs is a SupportWalletFragment in the activity’s layout. The fragment is the placeholder for the Android Pay purchase button.

The buy button will currently state “Buy with Google” until Android Pay is available.

<fragment
android:id="@+id/wallet_fragment"
android:name="com.google.android.gms.wallet.fragment.SupportWalletFragment"
android:layout_width="match_parent"
android:layout_height="wrap_content"
wallet:environment="sandbox"
wallet:fragmentMode="buyButton"/>

With the fragment in place, back in the activity, you need to:

  1. Grab a reference to that fragment.
  2. Create a MaskedWalletRequest.
  3. Initialize the fragment.

In the MaskedWalletRequest, you are able to specify the amount to charge and what additional information you’d like to collect (e.g., the shipping address). This is also where you specify you are using Stripe as the processor. Doing so will let the application request a Stripe token directly from the wallet.

public class PaymentActivity extends FragmentActivity implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener {

  // Change to your publishable key!!!
  public static final String PUBLISHABLE_KEY = "pk_test_6pRNASCoBOKtIshFeQd4XMUh";

  // Unique identifiers for asynchronous requests:
  private static final int LOAD_MASKED_WALLET_REQUEST_CODE = 1000;
  private static final int LOAD_FULL_WALLET_REQUEST_CODE = 1001;

  private SupportWalletFragment walletFragment;

  public void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.payment_activity);

      walletFragment =
        (SupportWalletFragment) getSupportFragmentManager().findFragmentById(R.id.wallet_fragment);

      MaskedWalletRequest maskedWalletRequest = MaskedWalletRequest.newBuilder()

          // Request credit card tokenization with Stripe by specifying tokenization parameters:
          .setPaymentMethodTokenizationParameters(PaymentMethodTokenizationParameters.newBuilder()
              .setPaymentMethodTokenizationType(PaymentMethodTokenizationType.PAYMENT_GATEWAY)
              .addParameter("gateway", "stripe")
              .addParameter("stripe:publishableKey", PUBLISHABLE_KEY)
              .addParameter("stripe:version", com.stripe.Stripe.VERSION)
              .build())

          // You want the shipping address:
          .setShippingAddressRequired(true)

          // Price set as a decimal:
          .setEstimatedTotalPrice("20.00")
          .setCurrencyCode("USD")
          .build();

      // Set the parameters:	
      WalletFragmentInitParams initParams = WalletFragmentInitParams.newBuilder()
              .setMaskedWalletRequest(maskedWalletRequest)
              .setMaskedWalletRequestCode(LOAD_MASKED_WALLET_REQUEST_CODE)
              .build();

      // Initialize the fragment:
      walletFragment.initialize(initParams);

      ...
  }

  public void onStart() {
      ...
  }

  public void onStop() {
      ...
  }

  @Override
  protected void onActivityResult(int requestCode, int resultCode, Intent data) {
      ...
  }

  @Override
  public void onConnectionFailed(ConnectionResult connectionResult) {}

  @Override
  public void onConnected(Bundle bundle) {}

  @Override
  public void onConnectionSuspended(int i) {}
}

Note that the price set within the Android app is written as a decimal. This is for the Android app only. The token received back will be sent to your server, and the charge request will be made of the Stripe API from there. The actual amount to be charged is requested at that point, and is set as an integer.

The last part of the setup process for the app is to connect to the Google Wallet API. You will need this connection in place for when the user presses the Android Pay purchase button just created.

public class PaymentActivity extends FragmentActivity {
  ...

  private GoogleApiClient googleApiClient;

  public void onCreate(Bundle savedInstanceState) {
      ...

      googleApiClient = new GoogleApiClient.Builder(this)
              .addConnectionCallbacks(this)
              .addOnConnectionFailedListener(this)
              .addApi(Wallet.API, new Wallet.WalletOptions.Builder()
                      .setEnvironment(WalletConstants.ENVIRONMENT_SANDBOX)
                      .setTheme(WalletConstants.THEME_HOLO_LIGHT)
                      .build())
              .build();
  }

  public void onStart() {
      super.onStart();
      googleApiClient.connect();
  }

  public void onStop() {
      super.onStop();
      googleApiClient.disconnect();
  }
}

When your customer confirms their purchase, the application then needs to create a FullWalletRequest. This will allow the application to request access to the customer’s FullWallet, which is where the payment information comes from. To do this, implement onActivityResult.

public class PaymentActivity extends FragmentActivity {
  ...

  @Override
  protected void onActivityResult(int requestCode, int resultCode, Intent data) {
      super.onActivityResult(requestCode, resultCode, data);

      if (requestCode == LOAD_MASKED_WALLET_REQUEST_CODE) { // Unique, identifying constant
          if (resultCode == Activity.RESULT_OK) {
              MaskedWallet maskedWallet = data.getParcelableExtra(WalletConstants.EXTRA_MASKED_WALLET);
              FullWalletRequest fullWalletRequest = FullWalletRequest.newBuilder()
                      .setCart(Cart.newBuilder()
                              .setCurrencyCode("USD")
                              .setTotalPrice("20.00")
                              .addLineItem(LineItem.newBuilder() // Identify item being purchased
                                      .setCurrencyCode("USD")
                                      .setQuantity("1")
                                      .setDescription("Premium Llama Food")
                                      .setTotalPrice("20.00")
                                      .setUnitPrice("20.00")
                                      .build())
                              .build())
                      .setGoogleTransactionId(maskedWallet.getGoogleTransactionId())
                      .build();
              Wallet.Payments.loadFullWallet(googleApiClient, fullWalletRequest, LOAD_FULL_WALLET_REQUEST_CODE);
          }
      } else if (requestCode == LOAD_FULL_WALLET_REQUEST_CODE) { // Unique, identifying constant
          ...
      }
   }
}

You can see from this example that you can add line items to the FullWalletRequest’s cart. The above only has one–Premium Llama Food, but if your customer is purchasing multiple items, you can add multiple line items by calling addLineItem additional times.

Creating tokens from Android Pay

Finally, when the customer allows access to their wallet for payment, the application will be given back a Stripe token. You will want to send this token to your server for use through the API.

public class PaymentActivity extends FragmentActivity {
  ...

  @Override
  protected void onActivityResult(int requestCode, int resultCode, Intent data) {
      if (requestCode == LOAD_MASKED_WALLET_REQUEST_CODE) {
          ...
      } else if (requestCode == LOAD_FULL_WALLET_REQUEST_CODE) {
          if (resultCode == Activity.RESULT_OK) {
              FullWallet fullWallet = data.getParcelableExtra(WalletConstants.EXTRA_FULL_WALLET);
              String tokenJSON = fullWallet.getPaymentMethodToken().getToken();

              com.stripe.model.Token token = com.stripe.model.Token.GSON.fromJson(tokenJSON, com.stripe.model.Token.class);

              // TODO: send token to your server
          }
      } else {
          super.onActivityResult(requestCode, resultCode, data);
      }
   }
}

Building your own form

If you build your own payment form, you’ll need to collect at least your customers’ card numbers and expiration dates. You should likely also collect the CVC to prevent fraud. You can optionally collect the user’s name and billing address for additional fraud protection.

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

Creating & validating cards from a custom form

You’ll need to import the Stripe classes before you can use them.

import com.stripe.android.*;

There are two main classes: Card and Stripe. The Card class contains a bunch of useful helpers for validating card input on the client-side, before you even try to create a charge.

Let’s construct a Card instance with your customers’ payment information, perhaps retrieved from a form.

Card card = new Card(
  cardNumber,
  cardExpMonth,
  cardExpYear,
  cardCVC
);

card.validateNumber();
card.validateCVC();

As you can see in the example above, 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.

Card card = new Card("4242-4242-4242-4242", 12, 2016, "123");

if ( !card.validateCard() ) {
  // Show errors
}

Creating tokens from a custom form

The next step is to pass off that sensitive payment information securely to Stripe, where you’ll exchange it for a token. You can create tokens using the Stripe instance method createToken, passing in a Card instance, and completion callbacks. An asynchronous network request will be executed, and the appropriate callback invoked when it completes.

Card card = new Card("4242424242424242", "12", "2014", "123");

Stripe stripe = new Stripe("pk_test_6pRNASCoBOKtIshFeQd4XMUh");
stripe.createToken(
  card,
  new TokenCallback() {
      public void onSuccess(Token token) {
          // Send token to your server
      }
      public void onError(Exception error) {
          // Show localized error message
          Toast.makeText(getContext(),
            error.getLocalizedString(getContext()),
            Toast.LENGTH_LONG
          ).show();
      }
  }
)

We’ve placed your test publishable API key as the first argument to Stripe. You’ll need to swap it out with your live publishable key in production. You can see all your keys in your dashboard.

Using tokens

Using the payment token, however it was obtained, requires an API call from your server using your secret API key. (For security purposes, you should never embed your secret API key in your app.)

Set up an endpoint on your server that can receive an HTTP POST call for the token. In the onActivityResult method (for Android 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 Up

Once you’ve retrieved a token from Stripe on your server, you’re going to want to do something with the payment details you just collected. This is usually one of two things: