f
 

Building a POS System with Android, QR Codes, and PayPal

July 18, 2011
By Peter Georgeson

Overview

In this article, I describe how to build and extend an Android-based point-of-sale (POS) application.

The article uses an existing Android application: Yard Sale. Yard Sale uses QR codes to identify an item for sale. The application uses Android's barcode-scanning capability to get the item's unique ID based on the QR code, which is then used to get price and other details associated with the item from a server. PayPal's Android SDK is used to make payment.

I first demonstrate how to build the existing Android application. Then I'll extend the solution with a Google App Engine project that implements:

  • An inventory management system; and
  • IPN (Instant Payment Notification)

Building Android Applications

Briefly, to build an Android application, install the following:

  • Android SDK — Google provide extensive instructions for installing their Android SDK.
  • Eclipse — although the Eclipse IDE is not technically required to build Android applications, Yard Sale is an Eclipse project. Note that the latest Android SDK requires Eclipse 3.5 or later.
  • Android Developer Toolkit Eclipse Plugin — this plugin links the Eclipse IDE to the Android SDK.

With these three components in place, you're ready to build Android applications.

Building the Yard Sale Application

To build the Yard Sale application, first download the Yard Sale project from GitHub, then import it into Eclipse.

Yard Sale has the following dependencies:

  • PayPal SDK — this handles all communication with PayPal.
  • Google GSON — converts JSON into Java objects.

These are included with the project in the lib directory; however, it may be worth checking occasionally for updates to these libraries.

Running the Application

In its current form, the application requires a physical device so that the barcode scanner can run.   If you have an Android device, start up the application and the application will ask you to scan a barcode.

Given a valid barcode, the application attempts to connect to a URL based on the scanned barcode. It expects to retrieve JSON data containing product details. An example of a valid JSON snippet:


{"price" : 35.00, "id" : "1234", "description" : "An autographed copy of Mining the Social Web by the author", "name" : "Mining the Social Web", "seller" : "seller@domain.com"}

After successfully retrieving this data from the web server, it is then displayed to the buyer, along with a "Buy Now" button. If the buyer chooses to continue, the PayPal SDK is initiated to allow the item to be purchased.

Inventory Management

The basic Yard Sale application doesn't include the server side of this process — i.e., the ability to build an inventory, generate QR codes, or retrieve product data.    A simple Google App Engine (GAE) application has been built to demonstrate this.

The GAE application is included in the source code, under the server directory.

Deploying a GAE application is not covered in detail here; however, the basic steps are:

  • Download and install the App Engine SDK;
  • Import the GAE project (in the server directory) using the provided App Engine tool;
  • Run the project locally if desired;
  • Create an application at Google and edit app.yaml to match the name of the created application; and
  • Deploy!

Once you have the server running, you need to modify the Android client to have all data requests go to your web server. Look for the definition of INVENTORY_SERVER in ItemDetails.java:

private static final String INVENTORY_SERVER = "http://superniftytest.appspot.com/get/";

Change the URL to match your own application server.  The text that is extracted from the QR code will be appended to this string to form the URL from which to retrieve the JSON code. For example, if the QR code is 1234, then the Android application will connect to http://superniftytest.appspot.com/get/1234.

Managing Your Inventory

The application contains a simple database model consisting of Item objects, defined in model.py, which are simply displayed as a list on the home page:

Click on "Add" to add a new item.

Now click on the added item to see details and the QR code.

You can easily see what JSON data will be provided to the Android client for this item by changing the URL in your browser. Change /edit/ to /get/ to see what the Android client will receive.

Now that an item has been added, the idea is to print out this QR code and attach it to the item you wish to sell.

A buyer scans the barcode using the YardSale application and can check the item price and other details of the item for sale, with the option to proceed to payment with PayPal.

If you start up the Android client, you can test the process by scanning the QR code straight off the website. The next screen displays the item details along with a "Pay with PayPal" button.

The inventory server that has been implemented here is a simple demonstration and intended as a starting point — there are many avenues for expanding on this basic implementation. For instance, it would be trivial to add a page that allows all QR codes to be printed in a single batch, instead of having to print each code individually.

IPN (Instant Payment Notification)

IPN is a notification mechanism offered by PayPal that enables automation of particular actions based on the status of an order.   In this simple demonstration, we use IPN to keep track of the store's inventory.

To configure the Android application to use IPN, set the IPN_SERVER property, specified in ItemDetails.java, to the correct server.    Note that the application by default is set to PayPal.ENV_NONE, which does not support IPN.

To send IPN notifications through the client application, the application must be configured to use either PayPal.ENV_SANDBOX or PayPal.ENV_LIVE

Alternatively, a useful tool for testing IPN is PayPal's IPN Simulator. This tool can be accessed by logging in to https://developer.paypal.com/ and selecting Test Tools.

The IPN handler for the demonstration server is very simple. If the IPN request is determined to be valid, the available stock of the item is reduced by one.    If the IPN request is determined to be invalid, an error is logged:


class IPN (webapp.RequestHandler):
  def post(self, key):
    '''incoming post from paypal'''
    logging.debug( "IPN received for %s" % key )
    ipn = paypal.IPN( self.request )
    if ipn.success():
      # request is paypal's
      item = model.Item.get( key )
      # confirm amount
      if item.price_decimal() != ipn.amount:
        logging.info( "IPN amounts didn't match. Item price %f. Payment made %f" % ( item.price_dollars(), ipn.amount ) )
      else:
        item.available -= 1 # success
        item.save()
        logging.info( "Item %s was purchased" % item.name )
    else:
      logging.info( "PayPal IPN verify failed: %s" % ipn.error )
      logging.debug( "Request was: %s" % self.request.body )

 

The actual IPN verification is implemented by the call to paypal.IPN:


    verify_response = url_request( "%s?cmd=_notify-validate" % PAYPAL_PAYMENT_HOST, data=urllib.urlencode( request.POST.copy() ) )
    # check code
    if verify_response.code() != 200:
      self.error = 'PayPal response code was %i' % verify_response.code()
      return
    # check response
    raw_response = verify_response.content()
    if raw_response != 'VERIFIED':
      self.error = 'PayPal response was "%s"' % raw_response
      return
    # check payment status
    if request.get('payment_status') != 'Completed':
      self.error = 'PayPal status was "%s"' % request.get('payment_status')
      return

    amount = request.get( "mc_gross" )
    self.amount = decimal.Decimal(amount)

 

IPN verification consists of the entire request being sent back to PayPal. PayPal will respond with VERIFIED if the request originated from them. 

The application considers the transaction to be successful if:

  • PayPal confirm the request as VERIFIED; and  
  • the payment status is COMPLETED

Using the Application

The use case of the Yard Sale application is that a vendor with an inventory of items for sale wishes to be able to take payment over a mobile device, for instance, at a Yard Sale.    Although Yard Sales may not be considered a hotspot for payment innovation, this paradigm can be expanded to any situation where a mobile payment option could be useful.

This particular solution has the advantage of using commonly available consumer hardware, along with a highly recognized payment provider.

Here's the process for preparing for the Yard Sale with this application:

Generate an Inventory

The GAE application provides a method of adding individual items to the inventory.

This simple implementation could benefit from expansion, for instance, with a method for bulk adding items.   Another possibility for populating an inventory is to use Amazon's Product Advertising API to automatically populate an inventory based on descriptions and/or existing product barcodes.

Print QR Codes

The application provides a method for viewing the QR code for each item. These codes can be printed and attached to the items for sale. A simple enhancement to the web application would be the option to print all QR codes.

Take Payment

With the inventory and QR codes in place, simply use the Android application to scan items and take payment. Voilà! A mobile POS system based on Android, PayPal, and QR codes.

Summary

The Yard Sale application provides a system for implementing a point-of-sale solution using QR codes, barcode scanning, and PayPal's Android SDK.

This article expanded on the provided client-side application by implementing a simple GAE-based server providing inventory management and IPN handling.

The intention of this article was to demonstrate the potential for this solution and provide some ideas for further expansion into a production-ready implementation.

Further Details