In the previous part Android Integrating PayPal using PHP, MySQL – Part 1, we have covered building the PayPal server side part i.e creating mysql database and writing the PHP services those interacts with android app and PayPal REST API.

In this part we are going to cover the remaining things like building the android app and integrating the PayPal payment gateway. Finally we conclude this by doing few tests in local environment.

android paypal integration php mysql

9. Downloading PayPal Android SDK

Just like PayPal PHP REST API SDK, PayPal provides SDK for mobile platforms too. Download the PayPal Android SDK and extract it. It comes with a Sample App, docs and libs. We would be interested in using the libs folder. If you want to try Future Payments and Profile Sharing, you can find example code in the sample app.

10. Creating the Android Project

Now let’s start building the android app.

1. Create a new project in Eclipse by going to File ⇒ New ⇒ Android Application Project and fill the required information.

I gave my project name as PayPalClient and package name as info.androidhive.paypalclient

2. Now quickly create two packages named app and helper.

3. Paste all the contents of PayPal Android SDK’s libs folder into our project’s libs folder.

Below is the final project structure that we’re going to create. You should have all the PayPal lib files and the packages placed as shown below.

android paypal project structure

4. Open colors.xml under res ⇒ value and add below color resources.

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <color name="btn_bg_checkout">#428bca</color>
    <color name="list_divider">#dedede</color>
    <color name="white">#ffffff</color>
    <color name="lbl_product_name">#333333</color>
    <color name="lbl_product_description">#444444</color>
    <color name="bg_msg_you">#5eb964</color>
    <color name="bg_msg_from">#e5e7eb</color>
    <color name="msg_border_color">#a1a1a1</color>
    <color name="bg_btn_join">#1e6258</color>
    <color name="bg_msg_input">#e8e8e8</color>
    <color name="text_msg_input">#626262</color>
    <color name="lblFromName">#777777</color>
</resources>

5. Open strings.xml under res ⇒ values and add below string values.

<?xml version="1.0" encoding="utf-8"?>
<resources>

    <string name="app_name">PalPal Client</string>
    <string name="checkout">Checkout</string>
    <string name="add_to_cart">Add to Cart</string>

</resources>

6. I am using volley to make network calls. Download the volley.jar and paste it in libs folder. (If you are new to volley, this tutorial will give you a good overview about volley library).

7. Create class named LruBitmapCache.java under helper package. The purpose of this class to cache the downloaded images.

package info.androidhive.palpalclient.helper;

import com.android.volley.toolbox.ImageLoader.ImageCache;

import android.graphics.Bitmap;
import android.support.v4.util.LruCache;

public class LruBitmapCache extends LruCache<String, Bitmap> implements
		ImageCache {
	public static int getDefaultLruCacheSize() {
		final int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024);
		final int cacheSize = maxMemory / 8;

		return cacheSize;
	}

	public LruBitmapCache() {
		this(getDefaultLruCacheSize());
	}

	public LruBitmapCache(int sizeInKiloBytes) {
		super(sizeInKiloBytes);
	}

	@Override
	protected int sizeOf(String key, Bitmap value) {
		return value.getRowBytes() * value.getHeight() / 1024;
	}

	@Override
	public Bitmap getBitmap(String url) {
		return get(url);
	}

	@Override
	public void putBitmap(String url, Bitmap bitmap) {
		put(url, bitmap);
	}
}

8. Crete a class named AppController.java under app package. This is a singleton class that extends from Application which will be executed on app launch. All the initialization of volley objects will be done here.

package info.androidhive.palpalclient.app;

import info.androidhive.palpalclient.helper.LruBitmapCache;
import android.app.Application;
import android.text.TextUtils;

import com.android.volley.Request;
import com.android.volley.RequestQueue;
import com.android.volley.toolbox.ImageLoader;
import com.android.volley.toolbox.Volley;

public class AppController extends Application {

	public static final String TAG = AppController.class.getSimpleName();

	private RequestQueue mRequestQueue;
	private ImageLoader mImageLoader;

	private static AppController mInstance;

	@Override
	public void onCreate() {
		super.onCreate();
		mInstance = this;
	}

	public static synchronized AppController getInstance() {
		return mInstance;
	}

	public RequestQueue getRequestQueue() {
		if (mRequestQueue == null) {
			mRequestQueue = Volley.newRequestQueue(getApplicationContext());
		}

		return mRequestQueue;
	}

	public ImageLoader getImageLoader() {
		getRequestQueue();
		if (mImageLoader == null) {
			mImageLoader = new ImageLoader(this.mRequestQueue,
					new LruBitmapCache());
		}
		return this.mImageLoader;
	}

	public <T> void addToRequestQueue(Request<T> req, String tag) {
		// set the default tag if tag is empty
		req.setTag(TextUtils.isEmpty(tag) ? TAG : tag);
		getRequestQueue().add(req);
	}

	public <T> void addToRequestQueue(Request<T> req) {
		req.setTag(TAG);
		getRequestQueue().add(req);
	}

	public void cancelPendingRequests(Object tag) {
		if (mRequestQueue != null) {
			mRequestQueue.cancelAll(tag);
		}
	}
}

9. Now edit the AndroidManifest.xml and do below changes.

> Add the AppController class to <application> tag using android:name property.

> Add CAMERA, VIBRATE, ACCESS_NETWORK_STATE and INTERNET permissions.

> Add the camera feature. This should be added when user wants to pay using card.io feature.

> Add the PayPalService

> Add the PayPal SDK activities (PaymentActivity, LoginActivity, PaymentMethodActivity, PaymentConfirmActivity and CardIOActivity). These are necessary activities to make paypal payment.

Finally the AndroidManifest.xml should look like below.

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="info.androidhive.palpalclient"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="21" />

    <!-- for card.io card scanning -->
    <uses-permission android:name="android.permission.CAMERA" />
    <uses-permission android:name="android.permission.VIBRATE" />

    <uses-feature
        android:name="android.hardware.camera"
        android:required="false" />
    <uses-feature
        android:name="android.hardware.camera.autofocus"
        android:required="false" />

    <!-- for most things, including card.io & paypal -->
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.INTERNET" />

    <application
        android:name="info.androidhive.palpalclient.app.AppController"
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name" >
        <activity
            android:name="info.androidhive.palpalclient.MainActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

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

        <service
            android:name="com.paypal.android.sdk.payments.PayPalService"
            android:exported="false" /> 

        <activity android:name="com.paypal.android.sdk.payments.PaymentActivity" />
        <activity android:name="com.paypal.android.sdk.payments.LoginActivity" />
        <activity android:name="com.paypal.android.sdk.payments.PaymentMethodActivity" />
        <activity android:name="com.paypal.android.sdk.payments.PaymentConfirmActivity" />
        <activity
            android:name="io.card.payment.CardIOActivity"
            android:configChanges="keyboardHidden|orientation" />
        <activity android:name="io.card.payment.DataEntryActivity" />
    </application>

</manifest>

10. Crete a class named Config.java under app package. This class contains all the configuration variables like PayPal client id & secret, paypal environment and url endpoints to our server which we built in the first part of this series.

package info.androidhive.palpalclient.app;

import com.paypal.android.sdk.payments.PayPalConfiguration;
import com.paypal.android.sdk.payments.PayPalPayment;

public class Config {

	// PayPal app configuration
	public static final String PAYPAL_CLIENT_ID = "AbLgy0hRsq0PmoGK-ws2-jlBIeBVKUUU0xRjbfW1-GAckylz_TDNsh1cMrIiSksc2wpqYC2PisTrKhko";
	public static final String PAYPAL_CLIENT_SECRET = "";

	public static final String PAYPAL_ENVIRONMENT = PayPalConfiguration.ENVIRONMENT_SANDBOX;
	public static final String PAYMENT_INTENT = PayPalPayment.PAYMENT_INTENT_SALE;
	public static final String DEFAULT_CURRENCY = "USD";

	// PayPal server urls
	public static final String URL_PRODUCTS = "http://192.168.0.103/PayPalServer/v1/products";
	public static final String URL_VERIFY_PAYMENT = "http://192.168.0.103/PayPalServer/v1/verifyPayment";

}

11. Create a model class named Product.java under helper package. This class will be used while parsing the products json.

package info.androidhive.palpalclient.helper;

import java.math.BigDecimal;

public class Product {
	private String id, name, description, image, sku;
	private BigDecimal price;

	public Product() {

	}

	public Product(String id, String name, String description, String image,
			BigDecimal price, String sku) {
		this.id = id;
		this.name = name;
		this.description = description;
		this.image = image;
		this.price = price;
		this.sku = sku;
	}

	public String getId() {
		return id;
	}

	public void setId(String id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getDescription() {
		return description;
	}

	public void setDescription(String description) {
		this.description = description;
	}

	public String getImage() {
		return image;
	}

	public void setImage(String image) {
		this.image = image;
	}

	public BigDecimal getPrice() {
		return price;
	}

	public void setPrice(BigDecimal price) {
		this.price = price;
	}

	public String getSku() {
		return sku;
	}

	public void setSku(String sku) {
		this.sku = sku;
	}

}

12. Under res ⇒ layout, create a file named list_item_product.xml. This layout file renders a single list item in products list view. This layout contains the product image on the left and other details like product name, description, price on the right.

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/white"
    android:paddingBottom="10dp" >

    <com.android.volley.toolbox.NetworkImageView
        android:id="@+id/productImage"
        android:layout_width="100dp"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_margin="8dp"
        android:scaleType="fitCenter" >
    </com.android.volley.toolbox.NetworkImageView>

    <TextView
        android:id="@+id/productName"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_toRightOf="@id/productImage"
        android:padding="5dp"
        android:textColor="@color/lbl_product_name"
        android:textSize="16dp"
        android:textStyle="bold" />

    <TextView
        android:id="@+id/productDescription"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@id/productName"
        android:layout_toRightOf="@id/productImage"
        android:padding="5dp"
        android:textColor="@color/lbl_product_description" />

    <TextView
        android:id="@+id/productPrice"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@id/productDescription"
        android:layout_toRightOf="@id/productImage"
        android:padding="5dp"
        android:textColor="@color/lbl_product_description" />

    <Button
        android:id="@+id/btnAddToCart"
        android:layout_width="wrap_content"
        android:layout_height="30dp"
        android:layout_below="@id/productPrice"
        android:layout_margin="5dp"
        android:layout_toRightOf="@id/productImage"
        android:background="#64d048"
        android:paddingLeft="5dp"
        android:paddingRight="5dp"
        android:text="@string/add_to_cart"
        android:textColor="@color/white" />

</RelativeLayout>

13. As the product list view is customized, we need to write the custom list adapter class. Create a class named ProductListAdapter.java under helper package. This adapter class renders list_item_product.xml by filling appropriate product data in a single list row.

package info.androidhive.palpalclient.helper;

import info.androidhive.palpalclient.R;
import info.androidhive.palpalclient.app.AppController;

import java.util.List;

import android.app.Activity;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.TextView;

import com.android.volley.toolbox.ImageLoader;
import com.android.volley.toolbox.NetworkImageView;

public class ProductListAdapter extends BaseAdapter {
	private Activity activity;
	private LayoutInflater inflater;
	private List<Product> products;
	private ProductListAdapterListener listener;
	ImageLoader imageLoader = AppController.getInstance().getImageLoader();

	public ProductListAdapter(Activity activity, List<Product> feedItems,
			ProductListAdapterListener listener) {
		this.activity = activity;
		this.products = feedItems;
		this.listener = listener;
	}

	@Override
	public int getCount() {
		return products.size();
	}

	@Override
	public Object getItem(int location) {
		return products.get(location);
	}

	@Override
	public long getItemId(int position) {
		return position;
	}

	@Override
	public View getView(int position, View convertView, ViewGroup parent) {

		if (inflater == null)
			inflater = (LayoutInflater) activity
					.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
		if (convertView == null)
			convertView = inflater.inflate(R.layout.list_item_product, null);

		if (imageLoader == null)
			imageLoader = AppController.getInstance().getImageLoader();

		TextView name = (TextView) convertView.findViewById(R.id.productName);
		TextView description = (TextView) convertView
				.findViewById(R.id.productDescription);
		TextView price = (TextView) convertView.findViewById(R.id.productPrice);

		NetworkImageView image = (NetworkImageView) convertView
				.findViewById(R.id.productImage);

		Button btnAddToCart = (Button) convertView
				.findViewById(R.id.btnAddToCart);

		final Product product = products.get(position);

		name.setText(product.getName());

		description.setText(product.getDescription());

		price.setText("Price: $" + product.getPrice());

		// user profile pic
		image.setImageUrl(product.getImage(), imageLoader);

		btnAddToCart.setOnClickListener(new View.OnClickListener() {

			@Override
			public void onClick(View v) {
				listener.onAddToCartPressed(product);
			}
		});

		return convertView;
	}

	public interface ProductListAdapterListener {
		public void onAddToCartPressed(Product product);
	}

}

14. Now we have all the helpers classes ready. Let’s move to main activity and start adding the PayPal code. Create a layout file under res layout named activity_main.xml and add below code. This layout contains a ListView to display the product list and a button to do the ckeckout.

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/white" >

    <ListView
        android:id="@+id/list"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content" 
        android:paddingBottom="20dp"
        android:divider="@color/list_divider"
        android:dividerHeight="1dp">
    </ListView>

    <Button
        android:id="@+id/btnCheckout"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:text="@string/checkout" 
        android:background="@color/btn_bg_checkout"/>

</RelativeLayout>

15. Open your MainActivity.java and do below changes. Basically to add PayPal support, we need to take below simple steps.

> Create a PayPalConfiguration object by setting necessary configuration like environment and client id.

> Start the PayPalService in onCreate()

> When user presses the checkout button, start the PaymentActivity by passing necessary information like final items, price, description etc.

> Once the payment is done, receive the PaymentConfirmation in onActivityResult(). This is where you will receives paypal response like payment id and other important information.

> Finally send the payment id and response json to our server for server side verification.

In the below code

fetchProducts() – Fetches the products json from our server.

verifyPaymentOnServer() – Verifies the mobile payment on the server.

prepareFinalCart() – Prepare the final cart information like total amount, items that needs to be submitted to paypal payment activity.

launchPayPalPayment() – Launches the PayPal payment activity

onAddToCartPressed() – Adds the item to cart when add to cart button is pressed.

package info.androidhive.palpalclient;

import info.androidhive.palpalclient.app.AppController;
import info.androidhive.palpalclient.app.Config;
import info.androidhive.palpalclient.helper.Product;
import info.androidhive.palpalclient.helper.ProductListAdapter;
import info.androidhive.palpalclient.helper.ProductListAdapter.ProductListAdapterListener;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.ListView;
import android.widget.Toast;

import com.android.volley.DefaultRetryPolicy;
import com.android.volley.Request.Method;
import com.android.volley.Response;
import com.android.volley.RetryPolicy;
import com.android.volley.VolleyError;
import com.android.volley.VolleyLog;
import com.android.volley.toolbox.JsonObjectRequest;
import com.android.volley.toolbox.StringRequest;
import com.paypal.android.sdk.payments.PayPalConfiguration;
import com.paypal.android.sdk.payments.PayPalItem;
import com.paypal.android.sdk.payments.PayPalPayment;
import com.paypal.android.sdk.payments.PayPalPaymentDetails;
import com.paypal.android.sdk.payments.PayPalService;
import com.paypal.android.sdk.payments.PaymentActivity;
import com.paypal.android.sdk.payments.PaymentConfirmation;

public class MainActivity extends Activity implements
		ProductListAdapterListener {
	private static final String TAG = MainActivity.class.getSimpleName();

	private ListView listView;
	private Button btnCheckout;

	// To store all the products
	private List<Product> productsList;

	// To store the products those are added to cart
	private List<PayPalItem> productsInCart = new ArrayList<PayPalItem>();

	private ProductListAdapter adapter;

	// Progress dialog
	private ProgressDialog pDialog;

	private static final int REQUEST_CODE_PAYMENT = 1;

	// PayPal configuration
	private static PayPalConfiguration paypalConfig = new PayPalConfiguration()
			.environment(Config.PAYPAL_ENVIRONMENT).clientId(
					Config.PAYPAL_CLIENT_ID);

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

		listView = (ListView) findViewById(R.id.list);
		btnCheckout = (Button) findViewById(R.id.btnCheckout);

		productsList = new ArrayList<Product>();
		adapter = new ProductListAdapter(this, productsList, this);

		listView.setAdapter(adapter);

		pDialog = new ProgressDialog(this);
		pDialog.setCancelable(false);

		// Starting PayPal service
		Intent intent = new Intent(this, PayPalService.class);
		intent.putExtra(PayPalService.EXTRA_PAYPAL_CONFIGURATION, paypalConfig);
		startService(intent);

		// Checkout button click listener
		btnCheckout.setOnClickListener(new View.OnClickListener() {

			@Override
			public void onClick(View v) {

				// Check for empty cart
				if (productsInCart.size() > 0) {
					launchPayPalPayment();
				} else {
					Toast.makeText(getApplicationContext(), "Cart is empty! Please add few products to cart.",
							Toast.LENGTH_SHORT).show();
				}

			}
		});

		// Fetching products from server
		fetchProducts();
	}

	/**
	 * Fetching the products from our server
	 * */
	private void fetchProducts() {
		// Showing progress dialog before making request

		pDialog.setMessage("Fetching products...");

		showpDialog();

		// Making json object request
		JsonObjectRequest jsonObjReq = new JsonObjectRequest(Method.GET,
				Config.URL_PRODUCTS, null, new Response.Listener<JSONObject>() {

					@Override
					public void onResponse(JSONObject response) {
						Log.d(TAG, response.toString());

						try {
							JSONArray products = response
									.getJSONArray("products");

							// looping through all product nodes and storing
							// them in array list
							for (int i = 0; i < products.length(); i++) {

								JSONObject product = (JSONObject) products
										.get(i);

								String id = product.getString("id");
								String name = product.getString("name");
								String description = product
										.getString("description");
								String image = product.getString("image");
								BigDecimal price = new BigDecimal(product
										.getString("price"));
								String sku = product.getString("sku");

								Product p = new Product(id, name, description,
										image, price, sku);

								productsList.add(p);
							}

							// notifying adapter about data changes, so that the
							// list renders with new data
							adapter.notifyDataSetChanged();

						} catch (JSONException e) {
							e.printStackTrace();
							Toast.makeText(getApplicationContext(),
									"Error: " + e.getMessage(),
									Toast.LENGTH_LONG).show();
						}

						// hiding the progress dialog
						hidepDialog();
					}
				}, new Response.ErrorListener() {

					@Override
					public void onErrorResponse(VolleyError error) {
						VolleyLog.d(TAG, "Error: " + error.getMessage());
						Toast.makeText(getApplicationContext(),
								error.getMessage(), Toast.LENGTH_SHORT).show();
						// hide the progress dialog
						hidepDialog();
					}
				});

		// Adding request to request queue
		AppController.getInstance().addToRequestQueue(jsonObjReq);
	}

	/**
	 * Verifying the mobile payment on the server to avoid fraudulent payment
	 * */
	private void verifyPaymentOnServer(final String paymentId,
			final String payment_client) {
		// Showing progress dialog before making request
		pDialog.setMessage("Verifying payment...");
		showpDialog();

		StringRequest verifyReq = new StringRequest(Method.POST,
				Config.URL_VERIFY_PAYMENT, new Response.Listener<String>() {

					@Override
					public void onResponse(String response) {
						Log.d(TAG, "verify payment: " + response.toString());

						try {
							JSONObject res = new JSONObject(response);
							boolean error = res.getBoolean("error");
							String message = res.getString("message");

							// user error boolean flag to check for errors

							Toast.makeText(getApplicationContext(), message,
									Toast.LENGTH_SHORT).show();

							if (!error) {
								// empty the cart
								productsInCart.clear();
							}

						} catch (JSONException e) {
							e.printStackTrace();
						}

						// hiding the progress dialog
						hidepDialog();

					}
				}, new Response.ErrorListener() {

					@Override
					public void onErrorResponse(VolleyError error) {
						Log.e(TAG, "Verify Error: " + error.getMessage());
						Toast.makeText(getApplicationContext(),
								error.getMessage(), Toast.LENGTH_SHORT).show();
						// hiding the progress dialog
						hidepDialog();
					}
				}) {

			@Override
			protected Map<String, String> getParams() {

				Map<String, String> params = new HashMap<String, String>();
				params.put("paymentId", paymentId);
				params.put("paymentClientJson", payment_client);

				return params;
			}
		};

		// Setting timeout to volley request as verification request takes sometime
		int socketTimeout = 60000;
		RetryPolicy policy = new DefaultRetryPolicy(socketTimeout,
				DefaultRetryPolicy.DEFAULT_MAX_RETRIES,
				DefaultRetryPolicy.DEFAULT_BACKOFF_MULT);
		verifyReq.setRetryPolicy(policy);

		// Adding request to request queue
		AppController.getInstance().addToRequestQueue(verifyReq);
	}

	/**
	 * Preparing final cart amount that needs to be sent to PayPal for payment
	 * */
	private PayPalPayment prepareFinalCart() {

		PayPalItem[] items = new PayPalItem[productsInCart.size()];
		items = productsInCart.toArray(items);

		// Total amount
		BigDecimal subtotal = PayPalItem.getItemTotal(items);

		// If you have shipping cost, add it here
		BigDecimal shipping = new BigDecimal("0.0");

		// If you have tax, add it here
		BigDecimal tax = new BigDecimal("0.0");

		PayPalPaymentDetails paymentDetails = new PayPalPaymentDetails(
				shipping, subtotal, tax);

		BigDecimal amount = subtotal.add(shipping).add(tax);

		PayPalPayment payment = new PayPalPayment(
				amount,
				Config.DEFAULT_CURRENCY,
				"Description about transaction. This will be displayed to the user.",
				Config.PAYMENT_INTENT);

		payment.items(items).paymentDetails(paymentDetails);

		// Custom field like invoice_number etc.,
		payment.custom("This is text that will be associated with the payment that the app can use.");

		return payment;
	}

	/**
	 * Launching PalPay payment activity to complete the payment
	 * */
	private void launchPayPalPayment() {

		PayPalPayment thingsToBuy = prepareFinalCart();

		Intent intent = new Intent(MainActivity.this, PaymentActivity.class);

		intent.putExtra(PayPalService.EXTRA_PAYPAL_CONFIGURATION, paypalConfig);

		intent.putExtra(PaymentActivity.EXTRA_PAYMENT, thingsToBuy);

		startActivityForResult(intent, REQUEST_CODE_PAYMENT);
	}

	/**
	 * Receiving the PalPay payment response
	 * */
	@Override
	protected void onActivityResult(int requestCode, int resultCode, Intent data) {
		if (requestCode == REQUEST_CODE_PAYMENT) {
			if (resultCode == Activity.RESULT_OK) {
				PaymentConfirmation confirm = data
						.getParcelableExtra(PaymentActivity.EXTRA_RESULT_CONFIRMATION);
				if (confirm != null) {
					try {
						Log.e(TAG, confirm.toJSONObject().toString(4));
						Log.e(TAG, confirm.getPayment().toJSONObject()
								.toString(4));

						String paymentId = confirm.toJSONObject()
								.getJSONObject("response").getString("id");

						String payment_client = confirm.getPayment()
								.toJSONObject().toString();

						Log.e(TAG, "paymentId: " + paymentId
								+ ", payment_json: " + payment_client);

						// Now verify the payment on the server side
						verifyPaymentOnServer(paymentId, payment_client);

					} catch (JSONException e) {
						Log.e(TAG, "an extremely unlikely failure occurred: ",
								e);
					}
				}
			} else if (resultCode == Activity.RESULT_CANCELED) {
				Log.e(TAG, "The user canceled.");
			} else if (resultCode == PaymentActivity.RESULT_EXTRAS_INVALID) {
				Log.e(TAG,
						"An invalid Payment or PayPalConfiguration was submitted.");
			}
		}
	}

	private void showpDialog() {
		if (!pDialog.isShowing())
			pDialog.show();
	}

	private void hidepDialog() {
		if (pDialog.isShowing())
			pDialog.dismiss();
	}

	@Override
	public void onAddToCartPressed(Product product) {

		PayPalItem item = new PayPalItem(product.getName(), 1,
				product.getPrice(), Config.DEFAULT_CURRENCY, product.getSku());

		productsInCart.add(item);

		Toast.makeText(getApplicationContext(),
				item.getName() + " added to cart!", Toast.LENGTH_SHORT).show();

	}

}


Here we completed android part too. In order to test both the server and mobile apps in the local environment, follow below steps.

11. Testing the App

> Make sure that both devices (the device running the php project and the android device) are connected to same wifi network.

> Replace the PAYPAL_CLIENT_ID & PAYPAL_SECRET in Config.php with your paypal keys in your php project.

> Replace the PAYPAL_CLIENT_ID in Config.java with your paypal client id

> Run the WAMP server and get the ip address of the machine by executing ipconfig in cmd. (On mac, use ifconfig to get the ip address). We need to use this ip address in the url instead of localhost.

> Replace the ip address of URL_PRODUCTS and URL_VERIFY_PAYMENT with your ip address in Config.java.

> Deploy and run the android app on device. If you get the products list displayed, your app successfully connecting with the php server.

> Try selecting the products you want to buy and proceed with the checkout. You should able to see PayPal payment screens and do the payment. When it ask for paypal credentials, use the sandbox credentials.

android paypal listing the shopping cart
android paypal integrating verifying mobile payment

12. Final Thoughts

⇒ Making Your App Live
When you are making your app live, read the guidelines ‘Going Live with Your Application‘ provided by PayPal to move your app to production environment.

In our app, change the environment from PayPalConfiguration.ENVIRONMENT_SANDBOX to PayPalConfiguration.ENVIRONMENT_PRODUCTION in Config.java

⇒ Supported Currencies
PayPal is not supporting all the currencies as of now. Here is the list of currencies PayPal is supporting. Unfortunately, for indian users INR is not in the list. But you can use google currency calculator to get realtime INR to USD currency convert rate.

References:
> Goto through PayPal REST API doc for detailed explanation of each REST API call.

> PayPal Android Mobile SDK

> PayPal PHP REST API SDK

> Server image used in the illustration.

Subscribe
Notify of
guest
142 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
Ajay
Ajay
6 years ago

thanks ravi, you made my day….

Ravi Tamada
6 years ago
Reply to  Ajay

You are welcome.

Virender Dall
Virender Dall
6 years ago
Reply to  Ravi Tamada

Hello Ravi sir
so far i am working with Eclipse only & now i wish to start work with Android studio but i am not very much aware about it. I am facing below problems with
1. how to use a lib project / jar in android studio
2. how to use eclipse project inside android studio or vice versa
3. not very much aware about gradle etc.

Can you please provide a tutorial on this (I know sounds like silly to ask you provide tutorial on Android studio but may be there are many more likes me)

Thanks!

Ajay Serona
Ajay Serona
6 years ago
Reply to  Ravi Tamada

Hi Ravi….is the paypal work in INDIA???

Alexis Troncoso
Alexis Troncoso
6 years ago

Very illustrative tutorial. Help me a lot. Thanks.

Ravi Tamada
6 years ago

You are welcome 🙂

ak
ak
6 years ago

Haillll Ravi.

simple gats
simple gats
6 years ago

Thanks a lot Ravi.

Kaustav Ghosh
Kaustav Ghosh
6 years ago

Just wow

Nitesh
Nitesh
6 years ago

Hi Ravi.. Its showing cart is empty.. I am testing it in emulator and have also changed the ip .. what should be the issue.?

Nitesh
Nitesh
6 years ago
Reply to  Nitesh

Sorry i didnt add app secret thats why it was not working.. Now all good… Thanks for this wonderful tutorial..

Franco Gutierrez
6 years ago
Reply to  Nitesh

Great tuto. But i get the same problem . My result is this [2627] BasicNetwork.performRequest: Unexpected response code 500 for http://myipfromipconfig/PayPalServer/v1/products . Any help ?

Ravi Tamada
6 years ago

You have a problem at apache server. Check php, apache logs for errors.

Ng Ik Mei
Ng Ik Mei
6 years ago
Reply to  Ravi Tamada

@:disqus hi great tutorial, but currently im working this one with my own server that is where i faced the problem. the cart come out empty and prompt
org.json.JSONException: End of input at character 1, i changed the url at the index.php, but it just wont bring out the link. do you know what seems to be the problem ?

sgshim09
sgshim09
6 years ago

In my case, rewrite_module unloaded;; check it below url.
http://forum.wampserver.com/read.php?2,82053,130076

Ng Ik Mei
Ng Ik Mei
6 years ago
Reply to  Nitesh

Hi, I’m facing the same problem now. May i know how did you solve it? It shows nothing (not even the picture) in the shopping cart.

Linus
Linus
6 years ago

Sir you are awesome………Thanks a lot….

Ravi Tamada
6 years ago
Reply to  Linus

You are welcome 🙂

Virender Dall
Virender Dall
6 years ago

Hello Ravi sir
so far i am working with Eclipse only & now i wish to start work with Android studio but i am not very much aware about it. I am facing below problems with
1. how to use a lib project / jar in android studio
2. how to use eclipse project inside android studio or vice versa
3. not very much aware about gradle etc.

Can you please provide a tutorial on this (I know sounds like silly to ask you provide tutorial on Android studio but may be there are many more likes me)

Thanks!

Ravi Tamada
6 years ago
Reply to  Virender Dall

Yeah, I’ll write the article soon.

Sithu
Sithu
6 years ago

Thanks a lot Ravi. Your tutorial is very great .

Ravi Tamada
6 years ago
Reply to  Sithu

You are welcome 🙂

Trey Rosius
Trey Rosius
6 years ago

Superb Tutorial Chief Ravi….Very Helpful.
But i have a problem, ip address changes whenever computer restarts, meaning i have to keep changing the ip address in the app.Is there a fix for this?I’ve already thought of static IP.

Raj
Raj
6 years ago

Hi i copied paypal server folder to wamp www directory but i cant able to run the server can you please help

Ravi Tamada
6 years ago
Reply to  Raj

Can you give me the steps you followed in running the project?

RAJ
RAJ
6 years ago
Reply to  Ravi Tamada

i followed all the steps created database using wamp and i copied, pasted the paypal server source code into the www directory inside wamp folder and imported paypal client into my eclipse. when i run paypal server into the projects of wamp i cant run the php pages in my chrome, it says webpage not available.

Ravi Tamada
6 years ago
Reply to  RAJ

Is WAMP started running ? If yes, please give me the url you are testing.

RAJ
RAJ
6 years ago
Reply to  Ravi Tamada

ya wamp is online i meant how to check the paypal server whether it is online or not cos when i run the app in my phone it doesnt populate any products like pendrive and other things.

Sanjay
Sanjay
6 years ago
Reply to  RAJ

hey dear
Parse error: syntax error, unexpected ‘[‘ in C:xampphtdocsPayPalServerv1index.php on line 113

pls give me sol..

Ibrahem Betar
Ibrahem Betar
6 years ago
Reply to  Sanjay

Hi Sanjay,
i faced same this problem and this is the solve :

Find the httpd.conf file (usually you will find it in a folder called conf, config or something along those lines)
Inside the httpd.conf file uncomment the line LoadModule rewrite_module modules/mod_rewrite.so (remove the pound ‘#’ sign from in front of the line).

Maor Hadad
Maor Hadad
6 years ago
Reply to  Raj

it happen to me too.

i solved it by enabling apachi modules.

left click on wamp tray icon -> apache->apache modules ->rewrite module

then restart all services

badname
badname
6 years ago

wow nice ! tank you Ravi !!! can use paypal for in app purches ? markets allow this?
tanks

jay
jay
6 years ago
Reply to  badname

I also wish to know if i can upload this at playstore without problems

badname
badname
6 years ago
Reply to  jay

we in Boycott , cant use in-app billing play store …. i need use it for Anti-boycott and sale my app from this tut (some like paypal in-app billing) 🙂

Celmar Galindez
Celmar Galindez
6 years ago

Hi, Ravi. This is a very helpful tutorial. Is this also possible in XAMPP? Thanks!

Ravi Tamada
6 years ago

Yes, it is.

Celmar Galindez
Celmar Galindez
6 years ago
Reply to  Ravi Tamada

Could you please show how to? Thanks!

I tried it and a lot of errors came out in my eclipse. Please help me to resolve these. Regards.

Arjun
Arjun
6 years ago

Hello Everyone, Could you please help me how to build a SPELLATHON android application or atlease provide few referral links for the same. Thank you

Arjun
Arjun
6 years ago

Hi Ravi, could you please build a application like this ? or else atleast suggest how to build this and what concepts we actullay require to build such apps

Suppose a user is playing with a canvas and has knowledge of drawing alphabets (Capital Letters) in digital format. Recognize which alphabet the user has drawn on the canvas.

Input:
User should be able to draw an alphabet.

Output:
Display the character what user draws on the canvas.

pushpa
pushpa
6 years ago

I am using android studio and i have followed all the steps but still i am getting errors. is there anything i have to add while working on android studio?
Thanks!

Naren Thapa magar
Naren Thapa magar
6 years ago

Hi Ravi I download you codes for better testing using eclipse but I got classNotFound error. As I used you code I ha

Naren Thapa magar
Naren Thapa magar
6 years ago

Hi,I used your code in eclipse but got classNotFound error and now I have no idea where is the error. It would be helpful if it could be fixed.

Cristian
Cristian
6 years ago

please help me

org.JSONException: Value <!DOCTYPE of type java.lang.String cannot be converted to JSONObject

Cristian
Cristian
6 years ago
Reply to  Cristian

Value <!DOCTYPE of type
java.lang.String cannot be converted
to JSONObject

Guest
Guest
6 years ago

org.JSONException: Value <!DOCTYPE of type java.lang.String cannot be converted to JSONObject help me

Maor Hadad
Maor Hadad
6 years ago

awesome tutorial. ty very much

PJ
PJ
6 years ago

Hey Ravi! Its awesome..!! I need your help. In my app, I need only Cash On Delivery..so how can I eliminate paypal payment gateway from the code. Plzz reply.. Thnxx

Sanjay
Sanjay
6 years ago

HEy Ravi,,,
Parse error: syntax error, unexpected ‘[‘ in C:xampphtdocsPayPalServerv1index.php on line 113

Sanjay
Sanjay
6 years ago

pls give me solution

Sanjay
Sanjay
6 years ago

org.json.jsonexception value br of type java.lang.string cannot be converted to jsonobject

pls give me sol….

Ishmael Chibvuri
Ishmael Chibvuri
5 years ago
Reply to  Sanjay

Hi. Did you manage to get a solution to this error. Having same error?

sudhir kumar
sudhir kumar
6 years ago

java.lang.NoClassDefFoundError: Failed resolution of: Lcom/paypal/android/sdk/payments/PayPalConfiguration;

sudhir kumar
sudhir kumar
6 years ago

java.lang.NoClassDefFoundError: Failed resolution of: Lcom/paypal/android/sdk/payments/PayPalConfiguration;

I get this type of exception while run this project…..

Pavan
Pavan
6 years ago

Hey, I am glad I found your post. Very helpful.

Just a question, can we include discounts in the paypal item list. i.e. the way you added items, can we also add the overall discounts given with them, which will be shown there.

Charly
Charly
6 years ago

Good tutorial, but I keep getting Error code 404 payment not found ,,can you please help with that??

Vonnie Franx
Vonnie Franx
6 years ago

Parse error: syntax error, unexpected ‘[‘ in /data/multiserv/users/1279600/projects/2715122/www/PayPalServer/v1/index.php on line 110 which points to this: $transaction = $payment->getTransactions()[0];

Trevor
6 years ago

I’m getting an error message, org.json.JSONException: Value <br to type java.lang.String cannot be coverted to JSONObject, were is this error coming from?

sajeeb
sajeeb
6 years ago

I am facing a problem. App runs fine but not loading the product list and makes a toast null. Can anyone help me on this?

Stylesmylez Io
Stylesmylez Io
6 years ago

Helppppppppp: BasicNetwork.performRequest: Unexpected response code 404

Ravi Tamada
6 years ago
Reply to  Stylesmylez Io

The url you are trying to hit is wrong.

Stylesmylez Io
Stylesmylez Io
6 years ago

ssl=0x6c185780 cert_verify_callback calling verifyCertificateChain authMethod=RSA

Erum Malik
Erum Malik
6 years ago

it does recieve response onActivityResult 🙁

Selva Ganesh
Selva Ganesh
6 years ago

hai bro,

i am getting this error while run the app
“jsonexception value br of type java.lang.string cannot be converted to jsonobject”
plz tell me solution to resolve this pbm

Pawan Sharma
Pawan Sharma
6 years ago

Hi ravi is there any way to take only 1 rupee from customer(In India) without spending any amount from developer side.

Munisekhar
Munisekhar
6 years ago

Hi Ravi, I got “An invalid Payment or PayPalConfiguration was submitted.” response in OnActivityRestult method can you please help on this.

Cholly Cholly
Cholly Cholly
6 years ago

Thanks Ravi.

My question is how to do it for the future subscription payments? it would be good to do an article about it, I’d appreciate it greatly. Thank you for this article.

† Captain Africa †
† Captain Africa †
6 years ago

Hi Ravi the product are not displaying can you hlep ?

Anand Patel
Anand Patel
5 years ago

i face same problem bro.
product item not displaying

† Captain Africa †
† Captain Africa †
6 years ago
Ravi Tamada
6 years ago

Understanding this article needs little effort. If you are not getting it, you need to read below tutorial first.

http://www.androidhive.info/2014/01/how-to-create-rest-api-for-android-app-using-php-slim-and-mysql-day-12-2/

Geraldo K Fillipus
Geraldo K Fillipus
5 years ago
Reply to  Ravi Tamada

HI, i am getting unfortunately your app has stopped working, i did follow all the steps but i didn’t change the ip address and the secret key including the id for paypal, could that be the problem?

Ravi Tamada
5 years ago

What is the error you are seeing in LogCat?

Geraldo K Fillipus
Geraldo K Fillipus
5 years ago
Reply to  Ravi Tamada

I also i appreciate your help! you are amazing bro! i don,t know how to thank you, but i wish you a good health and keep up with this awesome work you are doing for the world!

Ravi Tamada
5 years ago

Thanks bro. I wish you the same 🙂

Geraldo K Fillipus
Geraldo K Fillipus
5 years ago
Reply to  Ravi Tamada

I am using the same version you used in the project 2.8.5

Geraldo K Fillipus
Geraldo K Fillipus
5 years ago
Reply to  Ravi Tamada

if possible i can send you the whole project for for you to test it

Ravi Tamada
5 years ago

What is the play services version you are using in build.gradle

Geraldo K Fillipus
Geraldo K Fillipus
5 years ago
Reply to  Ravi Tamada

Here is the dependenency: dependencies {

compile ‘com.android.support:multidex:1.0.1’

compile ‘com.android.support:appcompat-v7:23.0.1’

compile ‘com.nineoldandroids:library:2.4.0’

compile ‘com.android.support:design:23.0.1’

compile ‘com.google.android.gms:play-services:8.1.0’

compile ‘com.android.support:support-v4:23.0.1’

compile ‘com.google.android.gms:play-services-identity:8.1.0’

compile ‘com.google.android.gms:play-services-gcm:8.1.0’

compile ‘com.jakewharton:butterknife:7.0.1’

compile ‘com.google.maps.android:android-maps-utils:0.4’

compile ‘org.jbundle.util.osgi.wrapped:org.jbundle.util.osgi.wrapped.org.apache.http.client:4.1.2’

compile ‘de.hdodenhof:circleimageview:2.0.0’

compile ‘com.joooonho:selectableroundedimageview:1.0.1’

compile ‘com.mcxiaoke.volley:library-aar:1.0.0’

compile ‘com.android.support:recyclerview-v7:23.0.1’

compile ‘com.android.support:cardview-v7:23.0.1’

compile ‘com.squareup.picasso:picasso:2.5.2’

compile(‘com.paypal.sdk:paypal-android-sdk:2.13.3’)

compile ‘com.google.android.gms:play-services-wallet:8.1.0’

† Captain Africa †
† Captain Africa †
6 years ago

i have used my Ip address still no luck the app runs but the product are not displaying i need help thanks in advance

† Captain Africa †
† Captain Africa †
6 years ago

Everything work perfectly Thanks Ravie now im just trying to do it in a fragment

relex
relex
6 years ago

Im having the same situation (products are not displayed). Anyway, what did you do to fix yours?

† Captain Africa †
† Captain Africa †
6 years ago
Reply to  relex

Left click on wamp tray icon -> apache->apache modules ->rewrite module

† Captain Africa †
† Captain Africa †
6 years ago
Reply to  relex

did it work ?

Pathak Harshal
Pathak Harshal
6 years ago

java.lang.NoClassDefFoundError: Failed resolution of: Lcom/paypal/android/sdk/payments/PayPalConfiguration;
at info.androidhive.palpalclient.MainActivity.(MainActivity.java:66)

PayPal Client giving me this error, please help me out

Supriya Sakore
Supriya Sakore
5 years ago

show null pointer in ProductListAdapter appController instance image loader

ahmad efendi
ahmad efendi
5 years ago

hay mr. Ravi
how can i get data from
List productsInCart = new ArrayList();
after btnAddToCart is clicked ?
Thanks..

Eudes
Eudes
5 years ago

Hi. The application does not display the products. can someone send me a link to download the code. I can not download the code on the site link.

Michał Pankowski
Michał Pankowski
5 years ago

Hello there, I have a problem with “index.php” file.

The problem is: org.json.JSONException: Value br of type java.lang.String cannot be converted to JSONObject

Michał Pankowski
Michał Pankowski
5 years ago

Fatal error: Call to a member function getAmount() on a non-object in /michal/www/android_login_api/v1/index.php on line 115

Abhinay Sharma
Abhinay Sharma
5 years ago

sir one tutorial for javamail api in android please.

142
0
Would love your thoughts, please comment.x
()
x