Accepting Stripe Payments in Android

Stripe is one of the most widely used payment gateways currently. It is also one of the best for developers because it allows very easy and smooth integration of code in multiple languages. Here we are going to look at accepting stripe payments in an Android app.

It is assumed that there is already a stripe account available for integration. If not then you can sign up for a free Stripe account and use it in test mode.

CONCEPTS

Before we look at the code, a few concepts need to be understood .

API Keys

Stripe can run in two modes – Live and Test mode. Test mode is useful while testing integration or for any scenario which allows you to test payment integration without actually charging live credit cards.  When in test mode, Stripe has some predefined card numbers to use, as shown below. You can use these numbers with any CVC/CVV number and any expiry month/year set in the future.

testcard

 

 

 

 

 

 

 

 

 

 

For API integration, Stripe provides two keys – one Public and one Private. These can be found in your Stripe account settings. The Public key will have the prefix of pk and the Private Key will have the prefix of sk .  You will have different pairs of Public/Private keys for Test mode and Live Mode.

So if you are going to use the Stripe gateway in Test mode then use the Test keys , otherwise use the Live keys.

Customer

A Customer Entity in Stripe is the person who makes payments into the account.

Card

A Card entity contains the credit card details of a Customer. A Customer may have multiple Cards.

Charge

An actual payment made in Stripe is called a Charge. A Charge is always linked to a Card and a Customer.

There are more entities in Stripe like Subscription, Plans, Coupons etc. but here we are just dealing with a simple payment, so we will not look into the advanced concepts.

PROCESS

In the sample code, the following logic is in place.

1.Create a Card entity in Stripe

2.Create a Customer entity

3.Create a Charge entity and link it with the Card and Customer entity.

Each of these entities returns a unique id which has to be handled by your backend code. For instance, in your database you should store the Stripe customer id, so that the next time this customer does a payment you can retrieve the Customer Entity from Stripe and then do a Charge, instead of creating a duplicate Customer entity again.

You can do a similar thing for the Card. A Card entity returns a Card token which can be stored and reused in your code. The advantage of this is that the actual card details are stored securely in Stripe and you can use the card token to tell Stripe which card to use.

Note that amounts are to be sent in the lowest currency denomination. Eg. if you are using USD and the amount to be charged is $50.00 then the amount should not be sent to Stripe as 50.00 but 50*100 cents which is 5000 .


THE APPLICATION

For your app to use the Stripe Android library, you need to link

'com.stripe:stripe-android'

This is shown in the build.gradle listing below.

We have a single Activity screen which takes in the payment details, validates the data and then updates Stripe with the transaction details.

 

LISTINGS

 

build.gradle

apply plugin: 'com.android.application'

android {
    compileSdkVersion 23
    buildToolsVersion "23.0.3"

    defaultConfig {
        applicationId "stripe.test.com.stripetest"
        minSdkVersion 19
        targetSdkVersion 23
        versionCode 1
        versionName "1.0"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    testCompile 'junit:junit:4.12'
    compile 'com.android.support:appcompat-v7:23.4.0'
    compile 'com.android.support:design:23.4.0'
    compile 'com.stripe:stripe-android:+'
}

Android.Manifest

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="stripe.test.com.stripetest">

    <uses-sdk
        android:minSdkVersion="19"
        android:targetSdkVersion="23" />


    <uses-permission android:name="android.permission.INTERNET" />


    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity
            android:name=".MainActivity"
            android:label="@string/app_name"
            android:theme="@style/AppTheme.NoActionBar">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    app:layout_behavior="@string/appbar_scrolling_view_behavior"
    android:orientation="vertical"
    tools:context="stripe.test.com.stripetest.MainActivity"
    >



    <LinearLayout
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        android:layout_marginBottom="10dp">

        <TextView
            android:id="@+id/textStripeLabel"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:layout_gravity="center_horizontal"
            android:text="Transaction Details"
            android:textAllCaps="false"
            android:textAlignment="center"
            android:textSize="@dimen/font_size_medium"
            android:textStyle="bold"
            />


    </LinearLayout>

    <LinearLayout
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        android:background="@drawable/sharp_rectangle_border"
        android:layout_marginBottom="20dp">



        <EditText
            android:id="@+id/editStripeCardNumber1"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="0.20"
            android:padding="5dp"
            android:singleLine="true"
            android:hint="XXXX"
            android:inputType="number"
            android:maxLength="4"
            android:textColor="#000000"
            android:textCursorDrawable="@null"/>

        <EditText
            android:id="@+id/editStripeCardNumber2"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="0.20"
            android:padding="5dp"
            android:singleLine="true"
            android:hint="XXXX"
            android:inputType="number"
            android:maxLength="4"
            android:textColor="#000000"
            android:textCursorDrawable="@null"/>

        <EditText
            android:id="@+id/editStripeCardNumber3"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="0.20"
            android:padding="5dp"
            android:singleLine="true"
            android:hint="XXXX"
            android:inputType="number"
            android:maxLength="4"
            android:textColor="#000000"
            android:textCursorDrawable="@null"/>

        <EditText
            android:id="@+id/editStripeCardNumber4"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="0.20"
            android:padding="5dp"
            android:singleLine="true"
            android:hint="XXXX"
            android:inputType="number"
            android:maxLength="4"
            android:textColor="#000000"
            android:textCursorDrawable="@null"/>

    </LinearLayout>

    <LinearLayout
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        android:layout_marginBottom="20dp">


        <EditText
            android:id="@+id/editStripeCVV"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="0.15"
            android:padding="5dp"
            android:hint="CVC"
            android:maxLength="3"
            android:singleLine="true"
            android:inputType="number"
            android:background="@drawable/sharp_rectangle_border"
            android:textColor="#000000"
            android:layout_marginRight="10dp"
            android:textCursorDrawable="@null"/>

        <LinearLayout
            android:layout_width="0dp"
            android:layout_weight="0.80"
            android:layout_height="wrap_content"
            android:orientation="horizontal"
            android:padding="5dp"
            android:background="@drawable/sharp_rectangle_border"
            >

            <TextView
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="0.20"
                android:text="MM/YYYY"
                android:textAllCaps="true"
                android:textSize="@dimen/font_size_small"
                />

            <Spinner
                android:layout_width="0dp"
                android:padding="2dp"
                android:layout_height="wrap_content"
                android:layout_weight="0.25"
                android:id="@+id/spinnerStripeExpMonth"
                android:layout_marginRight="5dp"
                />

            <Spinner
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="0.25"
                android:padding="2dp"

                android:id="@+id/spinnerStripeExpYear"
                />
        </LinearLayout>

    </LinearLayout>


    <LinearLayout
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        android:layout_marginBottom="10dp">




    </LinearLayout>

    <LinearLayout
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        android:background="@drawable/sharp_rectangle_border"
        android:layout_marginBottom="10dp">

        <TextView
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="0.60"
            android:text="$"
            android:layout_gravity="end"
            android:textAlignment="textEnd"
            android:textSize="@dimen/font_size_medium"
            android:textAllCaps="true"

            />

        <EditText
            android:id="@+id/editStripeAmount"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="0.35"
            android:padding="2dp"
            android:editable="true"
            android:inputType="numberDecimal"
            android:singleLine="true"
            android:textAlignment="textEnd"
            android:textSize="@dimen/font_size_medium"
            android:textColor="#000000"
            android:textCursorDrawable="@null"/>
    </LinearLayout>



    <LinearLayout
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        android:layout_marginBottom="10dp">



        <EditText
            android:id="@+id/editCustName"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:editable="true"
            android:singleLine="true"
            android:hint="Customer Name"
            android:textSize="@dimen/font_size_small"
            android:textColor="#000000"
            android:textCursorDrawable="@null"/>
    </LinearLayout>


    <LinearLayout
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        android:layout_marginBottom="10dp">



        <EditText
            android:id="@+id/editCustEmail"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:editable="true"
            android:inputType="textEmailAddress"
            android:singleLine="true"
            android:hint="Customer Email"
            android:textSize="@dimen/font_size_small"
            android:textColor="#000000"
            android:textCursorDrawable="@null"/>
    </LinearLayout>


    <LinearLayout
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        android:layout_marginBottom="10dp">



        <EditText
            android:id="@+id/editCustAddress"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:editable="true"
            android:singleLine="true"
            android:hint="Customer Address"
            android:textSize="@dimen/font_size_small"
            android:textColor="#000000"
            android:textCursorDrawable="@null"/>
    </LinearLayout>

    <LinearLayout
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        android:layout_marginBottom="10dp">




    </LinearLayout>


    <LinearLayout
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        android:layout_marginTop="5dp">
        <Button
            style="?android:attr/buttonStyleSmall"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Cancel"
            android:id="@+id/btnStripeCancel"
            android:layout_weight="0.45"
            android:onClick="showInvoices"
            />



        <View
            android:layout_width="0dp"
            android:layout_height="0dp"
            android:layout_weight="0.10" />

        <Button
            style="?android:attr/buttonStyleSmall"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Save"
            android:id="@+id/btnStripeSave"
            android:layout_weight="0.45"
            android:onClick="doPayment"
            />


    </LinearLayout>

    <LinearLayout
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        android:layout_marginBottom="10dp">

        <TextView
            android:id="@+id/textStripeMode"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:layout_gravity="center_horizontal"
            android:text=""
            android:textAllCaps="true"
            android:textAlignment="center"
            android:textSize="@dimen/font_size_small"
            />


    </LinearLayout>

</LinearLayout>

drawable/sharp_rectangle_border.xml

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item>
        <shape android:shape="rectangle">
            <solid android:color="#d4d4d4"/>
            <corners android:radius="0dp" />
        </shape>
    </item>

    <item
        android:left="1dp"
        android:right="1dp"
        android:top="1dp"
        android:bottom="1dp">
        <shape android:shape="rectangle">
            <solid android:color="@android:color/white"/>
            <corners android:radius="0dp" />
        </shape>
    </item>
</layer-list>

values/dimens.xml

<resources>
    <!-- Default screen margins, per the Android Design guidelines. -->
    <dimen name="activity_horizontal_margin">16dp</dimen>
    <dimen name="activity_vertical_margin">16dp</dimen>

    <!-- Per the design guidelines, navigation drawers should be between 240dp and 320dp:
       https://developer.android.com/design/patterns/navigation-drawer.html -->
    <dimen name="navigation_drawer_width">240dp</dimen>

    <dimen name="font_size_verysmall">10sp</dimen>
    <dimen name="font_size_small">12sp</dimen>
    <dimen name="font_size_average">14sp</dimen>
    <dimen name="font_size_medium">20sp</dimen>
    <dimen name="font_size_large">30sp</dimen>
    <dimen name="font_size_verylarge">50sp</dimen>



</resources>

MainActivity.java

package stripe.test.com.stripetest;

import android.app.ProgressDialog;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.Snackbar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.View;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.ArrayAdapter;
import android.widget.EditText;
import android.widget.Spinner;
import android.widget.Toast;

import com.stripe.android.Stripe;
import com.stripe.android.TokenCallback;
import com.stripe.android.model.Card;
import com.stripe.android.model.Token;
import com.stripe.exception.AuthenticationException;
import com.stripe.exception.CardException;
import com.stripe.model.Charge;
import com.stripe.model.Customer;
import com.stripe.net.RequestOptions;

import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.HashMap;
import java.util.Map;

public class MainActivity extends AppCompatActivity {

    ProgressDialog mProgressBar;
    private String mStripeCardToken;
    private String mPublicKey = "";
    private String mPrivateKey = "";

    private Token mToken;
    private Stripe mStripe = null;
    private String mStripeCustId;
    private boolean mCustWasAdded = false;
    private String mCustomerName;
    private String mCustomerEmail;
    private String mCustomerAddress;
    private BigDecimal mAmount;
    private String mTxnRef;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mProgressBar = new ProgressDialog(this);

        // populate spinners
        String []months = new String[12];
        for (int i =1;  i <=12; i++) {
            String val = "";
            if (i < 10)
                val = "0";
            months[i-1] = val + String.valueOf(i);
        }
        Spinner s = (Spinner) findViewById(R.id.spinnerStripeExpMonth);
        ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
                android.R.layout.simple_spinner_item, months);
        s.setAdapter(adapter);

        String []years = new String[12];
        for (int i =1;  i <=12; i++) {
            years[i-1] = String.valueOf(i+2015);
        }
        Spinner s2 = (Spinner) findViewById(R.id.spinnerStripeExpYear);
        ArrayAdapter<String> adapter2 = new ArrayAdapter<String>(this,
                android.R.layout.simple_spinner_item, years);
        s2.setAdapter(adapter2);


        // set auto jump to next field for CC entry
        EditText card1 = (EditText)findViewById(R.id.editStripeCardNumber1);
        card1.addTextChangedListener(new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence s, int start, int count, int after) {

            }

            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) {

            }

            @Override
            public void afterTextChanged(Editable s) {
                EditText card1 = (EditText) findViewById(R.id.editStripeCardNumber1);
                if (card1.getText().toString().length() == 4) {
                    EditText card2 = (EditText) findViewById(R.id.editStripeCardNumber2);
                    card2.requestFocus();
                }

            }
        });

        EditText card2 = (EditText)findViewById(R.id.editStripeCardNumber2);
        card2.addTextChangedListener(new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence s, int start, int count, int after) {

            }

            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) {

            }

            @Override
            public void afterTextChanged(Editable s) {
                EditText card2 = (EditText)findViewById(R.id.editStripeCardNumber2);
                if (card2.getText().toString().length() == 4) {
                    EditText card3 = (EditText)findViewById(R.id.editStripeCardNumber3);
                    card3.requestFocus();
                }

            }
        });

        EditText card3 = (EditText)findViewById(R.id.editStripeCardNumber3);
        card3.addTextChangedListener(new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence s, int start, int count, int after) {

            }

            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) {

            }

            @Override
            public void afterTextChanged(Editable s) {
                EditText card3 = (EditText) findViewById(R.id.editStripeCardNumber3);
                if (card3.getText().toString().length() == 4) {
                    EditText card4 = (EditText) findViewById(R.id.editStripeCardNumber4);
                    card4.requestFocus();
                }

            }
        });

        // set stripe key values
        // this info would actually come from another place in the app or from the backend. I am just putting hardcoded values here
        mPublicKey = "pk_test_apikey_comes_here";
        mPrivateKey = "sk_test_apikey_comes_here";

        // if you already have the customer details and have his stripe customer id, then this is the time to retrieve and
        // assign it to mStripeCustId



    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();

        //noinspection SimplifiableIfStatement
        if (id == R.id.action_settings) {
            return true;
        }

        return super.onOptionsItemSelected(item);
    }

    public void doPayment(View view) {
        boolean isValid = true;


        Spinner s = (Spinner) findViewById(R.id.spinnerStripeExpMonth);
        Spinner s2 = (Spinner) findViewById(R.id.spinnerStripeExpYear);

        String cardNumber = "";
        EditText textCard1 = (EditText) findViewById(R.id.editStripeCardNumber1);
        EditText textCard2 = (EditText) findViewById(R.id.editStripeCardNumber2);
        EditText textCard3 = (EditText) findViewById(R.id.editStripeCardNumber3);
        EditText textCard4 = (EditText) findViewById(R.id.editStripeCardNumber4);
        cardNumber = textCard1.getText().toString();
        cardNumber += textCard2.getText().toString();
        cardNumber += textCard3.getText().toString();
        cardNumber += textCard4.getText().toString();


        EditText textAmount = (EditText) findViewById(R.id.editStripeAmount);
        EditText textName = (EditText) findViewById(R.id.editCustName);
        EditText textEmail = (EditText) findViewById(R.id.editCustEmail);
        EditText textAddress = (EditText) findViewById(R.id.editCustAddress);

        try {
            mAmount = new BigDecimal(Double.parseDouble(textAmount.getText().toString()));

        } catch (NumberFormatException nex) {
            Toast.makeText(getApplicationContext(), "Invalid amount entered", Toast.LENGTH_LONG).show();
            isValid = false;
            return;
        }

        if (cardNumber.length() < 16) {
            Toast.makeText(getApplicationContext(), "Card number looks invalid", Toast.LENGTH_LONG).show();
            isValid = false;
            return;
        }

        EditText textCVV = (EditText) findViewById(R.id.editStripeCVV);
        if (textCVV.getText().toString().length() < 3) {
            Toast.makeText(getApplicationContext(), "CVC looks invalid", Toast.LENGTH_LONG).show();
            isValid = false;
            return;
        }

        int month = Integer.parseInt(s.getSelectedItem().toString());
        int year = Integer.parseInt(s2.getSelectedItem().toString());

        Card card = new Card(cardNumber, month, year, textCVV.getText().toString());


        if ( !card.validateCard() ) {

            Toast.makeText(getApplicationContext(), "Credit card validation failed!", Toast.LENGTH_LONG).show();
            isValid = false;
            return;
        }

        mCustomerAddress = textAddress.getText().toString();
        mCustomerEmail = textEmail.getText().toString();
        mCustomerName = textName.getText().toString();



        mProgressBar.setCancelable(false);
        mProgressBar.setMessage("Validating payment..");
        mProgressBar.setProgressStyle(ProgressDialog.STYLE_SPINNER);
        mProgressBar.show();

        if (mStripeCardToken == null || mStripeCardToken.equals("")) {
            try {
                mStripe = new Stripe(mPublicKey);
                mStripe.createToken(
                        card,
                        new TokenCallback() {
                            public void onSuccess(Token token) {
                                mProgressBar.hide();
                                mToken = token;

                                mStripeCardToken = mToken.getId();
                                checkCustomerStatus();


                            }

                            public void onError(Exception error) {
                                mProgressBar.hide();
                                // Show localized error message
                                Toast.makeText(getApplicationContext(),
                                        error.getMessage(),
                                        Toast.LENGTH_LONG
                                ).show();
                                return;
                            }
                        }
                );

            } catch (AuthenticationException aex) {
                Toast.makeText(getApplicationContext(), aex.getMessage(), Toast.LENGTH_LONG).show();
            }
        } else {

            checkCustomerStatus();
        }


    }

    void checkCustomerStatus() {

        if (mStripeCustId == null || mStripeCustId.equals("")) {

            mProgressBar.setCancelable(false);
            mProgressBar.setMessage("Adding customer to stripe account..");
            mProgressBar.setProgressStyle(ProgressDialog.STYLE_SPINNER);
            mProgressBar.show();

            new CheckCustomerTask().execute(0);
        } else {

            chargeTransaction();
        }
    }

    private void chargeTransaction() {
        mProgressBar.setCancelable(false);
        mProgressBar.setMessage("Charging credit card..");
        mProgressBar.setProgressStyle(ProgressDialog.STYLE_SPINNER);
        mProgressBar.show();

        new MakeChargeTask().execute(0);

    }

    public void savePayment() {
        // this is where you update the payment to your backend servers or database
        // and then take the user to the next screen

        Toast.makeText(getApplicationContext(), "Payment has been updated.", Toast.LENGTH_LONG).show();
    }

    public void updateCustomer() {

        mProgressBar.setCancelable(false);
        mProgressBar.setMessage("Updating customer details..");
        mProgressBar.setProgressStyle(ProgressDialog.STYLE_SPINNER);
        mProgressBar.show();
        new UpdateCustomerTask().execute(0);


    }

    //////////////////////////////////////////////////////////////////////////////

    //
    // The params are dummy and not used
    //
    class UpdateCustomerTask extends AsyncTask<Integer, Integer, String> {
        String mError = null;

        @Override
        protected String doInBackground(Integer... params) {

            try {
                    // update the customer data in your backend or database

                Thread.sleep(200);

            } catch (InterruptedException iex) {}

            return "Task Completed.";
        }
        @Override
        protected void onPostExecute(String result) {
            mProgressBar.hide();
            if (mError != null && mError != "")
                Toast.makeText(getApplicationContext(), mError, Toast.LENGTH_LONG).show();
            else {
                chargeTransaction();
            }
        }
        @Override
        protected void onPreExecute() {
        }
        @Override
        protected void onProgressUpdate(Integer... values) {

        }
    }


    //////////////////////////////////////////////////////////////////////////////

    //
    // The params are dummy and not used
    //
    class CheckCustomerTask extends AsyncTask<Integer, Integer, String> {
        String mError = null;

        @Override
        protected String doInBackground(Integer... params) {
            String mError = "";

            try {
                if (mStripe == null)
                    mStripe = new Stripe(mPublicKey);
                RequestOptions requestOptions = (new RequestOptions.RequestOptionsBuilder()).setApiKey(mPrivateKey).build();

                Map<String, Object> customerParams = new HashMap<String, Object>();
                customerParams.put("description", mCustomerName);
                customerParams.put("email", mCustomerEmail);
                customerParams.put("source", mStripeCardToken); // obtained with Stripe

                Customer cust = Customer.create(customerParams, requestOptions);
                mCustWasAdded = true;

                mStripeCustId = cust.getId();


            } catch (Exception cx) {
                mError = cx.getMessage();

            }

            return "Task Completed.";
        }
        @Override
        protected void onPostExecute(String result) {
            mProgressBar.hide();
            if (mError != null && mError != "")
                Toast.makeText(getApplicationContext(), mError, Toast.LENGTH_LONG).show();
            else {
                if (mCustWasAdded)
                    updateCustomer();
                else
                    chargeTransaction();
            }
        }
        @Override
        protected void onPreExecute() {
        }
        @Override
        protected void onProgressUpdate(Integer... values) {

        }
    }

    //////////////////////////////////////////////////////////////////////////////

    //
    // The params are dummy and not used
    //
    class MakeChargeTask extends AsyncTask<Integer, Integer, String> {
        String mError = null;

        @Override
        protected String doInBackground(Integer... params) {

            DecimalFormat decimalFormat = new DecimalFormat("0.00");
            String sAmount = decimalFormat.format(mAmount);
            sAmount = sAmount.replace(".", "");


            // Create the charge on Stripe's servers - this will charge the user's card
            try {
                if (mStripe == null)
                    mStripe = new Stripe(mPublicKey);
                RequestOptions requestOptions = (new RequestOptions.RequestOptionsBuilder()).setApiKey(mPrivateKey).build();

                Map<String, Object> chargeParams = new HashMap<String, Object>();
                chargeParams.put("amount", Integer.parseInt(sAmount)); // amount in cents, again
                chargeParams.put("currency", "usd");
                chargeParams.put("customer", mStripeCustId);
                chargeParams.put("description", "Payment description will come here");


                Charge charge = Charge.create(chargeParams, requestOptions);
                mTxnRef = charge.getId();




            } catch (Exception e) {
                // The card has been declined
                mError = e.getMessage();
            }

            return "Task Completed.";
        }
        @Override
        protected void onPostExecute(String result) {
            mProgressBar.hide();
            if (mError != null && mError != "")
                Toast.makeText(getApplicationContext(), mError, Toast.LENGTH_LONG).show();
            else {
                savePayment();
            }
        }
        @Override
        protected void onPreExecute() {
        }
        @Override
        protected void onProgressUpdate(Integer... values) {

        }
    }

}

SCREENSHOTS

App Screen

Screenshot_2016-06-07-13-35-59

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Stripe Transaction Details

stripe1

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Stripe Customer Details

stripe2

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Save

1 Comment

Leave a Reply

Your email address will not be published.


*


This site uses Akismet to reduce spam. Learn how your comment data is processed.