Getting Started with Sources in the Android SDK

    Make use of Sources with the Android SDK.

    Creating a payment using Sources with the Android SDK is a multi-step process:

    1. Create a Source object that represents your customer’s payment method
    2. Check if further action is required from your customer

    If no further action is required:

    1. Confirm the source is ready to use
    2. Tell your backend to create a charge request using the source

    If further action is required:

    1. Present the user with any information they may need to authorize the charge
    2. In your backend, listen to Stripe webhooks to create a charge with the source
    3. In your app, display the appropriate confirmation to your customer based on the source’s status

    Create a Source object

    To create a Source object, use the appropriate creation method for your Source type.

    final Stripe stripe = new Stripe(getContext(),
        "pk_test_TYooMQauvdEDq54NiTphI7jx");
    Card card = mCardInputWidget.getCard();
    SourceParams cardSourceParams = SourceParams.createCardParams(card);
    // The asynchronous way to do it. Call this method on the main thread.
    stripe.createSource(
        cardSourceParams,
        new ApiResultCallback<Source>() {
            @Override
            public void onSuccess(@NonNull Source source) {
                // Store the source somewhere, use it, etc
            }
            @Override
            public void onError(@NonNull Exception error) {
                // Tell the user that something went wrong
            }
        });
    
    // The synchronous way to do it (DON'T DO BOTH)
    Source source = stripe.createSourceSynchronous(cardSourceParams);
    val stripe = Stripe(
        getContext(),
        "pk_test_TYooMQauvdEDq54NiTphI7jx"
    )
    val card = cardInputWidget.getCard()
    val cardSourceParams = SourceParams.createCardParams(card)
    // The asynchronous way to do it. Call this method on the main thread.
    stripe.createSource(
        cardSourceParams,
        object : ApiResultCallback<Source> {
            override fun onSuccess(source: Source) {
                // Store the source somewhere, use it, etc
            }
    
            override fun onError(error: Exception) {
                // Tell the user that something went wrong
            }
        })
    
    // The synchronous way to do it (DON'T DO BOTH)
    val source = stripe.createSourceSynchronous(cardSourceParams)

    Each method requires parameters unique to the payment type. Refer to the appropriate payment methods documentation to find out what these are.

    Once you have a SourceParams object, create a source with either the Stripe#createSource() or Stripe#createSourceSynchronous(), depending on whether you prefer to manage threading yourself.

    Check if further action is required from your customer

    Some payment methods require your customer to complete a certain action before the source can be used in a charge request. For instance, customers using Giropay must be redirected to their online banking service to authorize the payment.

    SourceParams giropayParams = SourceParams.createGiropayParams(
            100,
            "Customer Name",
            "yourapp://post-authentication-return-url",
            "a purchase description");
    // Note: this is a synchronous method -- you should not run it on the UI thread
    Source giropaySource = mStripe.createSourceSynchronous(giropayParams);
    if (Source.REDIRECT.equals(giropaySource.getFlow())) {
        String redirectUrl = giropaySource.getRedirect().getUrl();
        // then go to this URL, as shown below.
    }
    val giropayParams = SourceParams.createGiropayParams(
        100,
        "Customer Name",
        "yourapp://post-authentication-return-url",
        "a purchase description"
    )
    // Note: this is a synchronous method -- you should not run it on the UI thread
    val giropaySource = stripe.createSourceSynchronous(giropayParams)
    if (Source.REDIRECT.equals(giropaySource.getFlow())) {
        val redirectUrl = giropaySource.getRedirect().getUrl()
        // then go to this URL, as shown below.
    }

    For sources that require redirecting your customer, you must specify a return URL when creating the source. This redirect URL should be unique and used consistently for your application. Do not use the same redirect URL in other applications, as it can result in a payment attempt that opens the wrong application after the redirect.

    Redirecting your customer to authorize a source

    For sources that require your customer to complete an action (e.g., verify using 3D Secure), redirect the customer out of your application to complete this step.

    String externalUrl = mThreeDSource.getRedirect().getUrl();
    // We suggest popping up a dialog asking the user
    // to tap to go to their browser so they are not
    // surprised when they leave your application.
    Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(externalUrl));
    startActivity(browserIntent);
    val externalUrl = threeDsSource.getRedirect().getUrl()
    
    // We suggest popping up a dialog asking the user
    // to tap to go to their browser so they are not
    // surprised when they leave your application.
    val browserIntent = Intent(Intent.ACTION_VIEW, Uri.parse(externalUrl))
    startActivity(browserIntent)

    Once the customer has completed the required action, they are redirected to the URL that was provided when creating the source.

    When declaring your activity that creates redirect-based sources, 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.

    @Override
    protected void onNewIntent(Intent intent) {
        super.onNewIntent(intent);
        if (intent.getData() != null && intent.getData().getQuery() != null) {
            // The client secret and source ID found here is identical to
            // that of the source used to get the redirect URL.
    
            String host = intent.getData().getHost();
            // Note: you don't have to get the client secret
            // and source ID here. They are the same as the
            // values already in your source.
            String clientSecret = intent.getData().getQueryParameter(QUERY_CLIENT_SECRET);
            String sourceId = intent.getData().getQueryParameter(QUERY_SOURCE_ID);
            if (clientSecret != null
                    && sourceId != null
                    && clientSecret.equals(redirectSource.getClientSecret())
                    && sourceId.equals(redirectSource.getId())) {
                // Then this is a redirect back for the original source.
                // You should poll your own backend to update based on
                // source status change webhook events it may receive, and display the results
                // of that here.
            }
            // If you had a dialog open when your user went elsewhere, remember to close it here.
            mRedirectDialogController.dismissDialog();
        }
    }
    override fun onNewIntent(intent: Intent) {
        super.onNewIntent(intent)
        if (intent.data != null && intent.data!!.query != null) {
            // The client secret and source ID found here is identical to
            // that of the source used to get the redirect URL.
    
            val host = intent.data!!.host
            // Note: you don't have to get the client secret
            // and source ID here. They are the same as the
            // values already in your source.
            val clientSecret = intent.data!!.getQueryParameter(QUERY_CLIENT_SECRET)
            val sourceId = intent.data!!.getQueryParameter(QUERY_SOURCE_ID)
            if (clientSecret != null
                && sourceId != null
                && clientSecret == mRedirectSource.getClientSecret()
                && sourceId == mRedirectSource.getId()
            ) {
                // Then this is a redirect back for the original source.
                // You should poll your own backend to update based on
                // source status change webhook events it may receive, and display the results
                // of that here.
            }
            // If you had a dialog open when your user went elsewhere, remember to close it here.
            redirectDialogController.dismissDialog()
        }
    }

    More information

    If you’d like more help, check out our example app on Github that demonstrates creating a payment using several different payment methods. In addition, here’s some documentation you might want to read next:

    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