Using PayPal's Adaptive Payments and Google App Engine to build an online market with Python

By Peter Georgeson

Overview

This multipart tutorial demonstrates how to build a complete online market application with Google App Engine (GAE), PayPal's Adaptive Payments and Python. This series covers:

The application implements a simple online market. Sellers can sign up and offer items for sale. Users can browse and purchase these items. The application uses the PayPal API to make payments to sellers, with the website owner collecting a commission.

The source code for the example application developed for this tutorial is hosted at GitHub.

The technology

Paypal Adaptive Payments

Paypal's API provides the mechanism for transferring money in a number of interesting ways, which gives developers quite a bit of flexibility in the payment process. The provided payment flows are:

PayPal's Adaptive Payments API

For further information, refer to PayPal's Introduction to Adaptive Payments.

This application demonstrates both the simple and chained payment options of the PayPal Adaptive Payments API.

Google App Engine

App Engine is a framework provided by Google for building scalable applications. Google provide and manage all the infrastructure. App Engine is free to use for low traffic applications.

Building an app engine application is significantly different from typical web application development because you are building on top of Google's framework, which forces you to implement in a scalable way. For instance, you must use Google's data store for persistence, rather than a typical SQL database like MySQL. This forces your data storage to be scalable.

Python

Python is an easy to learn and powerful programming language. Note that GAE runs on Python 2.5 - if you are used to a more recent version of Python there may be some slight differences in the Python libraries.

Setting Up

Google App Engine (GAE)

To build this project, you will need an App Engine application. First, sign up for App Engine (requires a Google account).

You need at least Python 2.5 installed on your machine. GAE is not compatible with Python 3. Then, download and install the App Engine SDK. Choose the Google App Engine SDK for your operating system.

This enables your application to be developed and run locally. The SDK also provides commands so you can upload your application to the App Engine servers.

PayPal

If you don’t already have one, create a PayPal developer account at https://developer.paypal.com/ for testing. After creating your main developer account, you will also need to create seller and buyer test accounts.

If you want to start accepting real money, you will also need to sign up for a live account at https://www.paypal.com/

Adaptive Payments also requires an application ID. While using the sandbox, you can use a test application ID, which is specified at https://www.x.com/community/ppx/testing. To get a live application ID, you need to login to https://www.x.com/ and follow the steps to create an application after clicking "My Apps". More details on this process are available at https://www.x.com/community/ppx/apps101/go-live.

Building the application

If you haven't already, now would be a good time to download the sample application from GitHub.

Settings

Before running the application, you must first configure your PayPal credentials in settings.py. Your PayPal API Credentials can be found on the sandbox by clicking on the API Credentials link in the left menu within PayPal:

Where to find your API credentials on the PayPal sandbox

To retrieve these values on a live application, you first need to request the API credentials from PayPal. After logging in, click on Profile->API Access and select Request API Signature. Your credentials will then be displayed. To obtain a live application ID, you must submit your application to PayPal for review.

Configuration

app.yaml is the main GAE configuration file for your application. This application uses a very simple configuration:


application: market
version: 1
runtime: python
api_version: 1

handlers:
- url: /static
  static_dir: static

- url: /.*
  script: main.py

This code:

A nifty thing you can do with GAE is easily maintain different versions of an application, by setting the version tag. GAE will keep track of the state of your application for each version tag used.

Application

The main application is defined in main.py. There are a number of Python based web frameworks available for GAE, such as Web2Py, Pylons and Django. This application uses the included web framework, called webapp.

Webapp provides a simple mechanism for defining a URL dispatcher, and a number of request handlers.

At the bottom of main.py is the main dispatcher. This defines the URL patterns that the application will accept and defines handlers for these patterns. As with Django, these URLs are regular expressions, and matches in brackets become parameters for the request handler.


application = webapp.WSGIApplication( [
    ('/', Home),
    ('/sell', Sell),
    ('/sell/(.*)/', Sell),
    ('/buy/(.*)/return/(.*)/(.*)/', BuyReturn),
    ('/buy/(.*)/cancel/(.*)/', BuyCancel),
    ('/buy/(.*)/', Buy),
    ('/image/(.*)/', Image),
  ],
  debug=True)

def main():
    run_wsgi_app(application)

if __name__ == "__main__":
    main()

Each request handler is a sub-class of webapp.RequestHandler and implements methods corresponding to the HTTP request type. For instance, the Home request handler looks like:


class Home(webapp.RequestHandler):
  def get(self):
    data = {
      'items': model.Item.recent(),
    }
    util.add_user( self.request.uri, data )
    path = os.path.join(os.path.dirname(__file__), 'templates/main.htm')
    self.response.out.write(template.render(path, data))

Model

GAE provides access to its datastore in a similar way to Django. For instance, the Item class is defined in model.py as:


class Item(db.Model):
  '''an item for sale'''
  owner = db.UserProperty()
  created = db.DateTimeProperty(auto_now_add=True)
  title = db.StringProperty()
  price = db.IntegerProperty() # cents
  image = db.BlobProperty()
  enabled = db.BooleanProperty()

  def price_dollars( self ):
    return self.price / 100.0

  @staticmethod
  def recent():
    return Item.all().filter( "enabled =", True ).order('-created').fetch(10)

Behind the scenes, GAE's datastore is schemaless, distributed and scalable. Rather than SQL, Google provide a similar but more limited language called GQL. GQL prevents certain non-scalable queries, such as joins and aggregate queries.

Templates

In the templates directory are the HTML templates. Google's webapp framework includes the Django template system.

Although this application uses Django's templating system, many others are available on GAE.

PayPal

paypal.py implements the interface between this application and PayPal's Adaptive Payments API.

The process of purchasing an item is reasonably simple:

Running the application

To run the application locally:

You should see something like:
Sample application home page

To run through the basic functionality of the application, first add an item to sell, then buy it.

Deploying the application

Before an application can be deployed, an application must first be created. Go to https://appengine.google.com/ and click "Create an application".
Create an application on GAE

Find an unused application ID. Once you have done this, edit app.yaml and change the application setting to the same name.

In the Google App Engine Launcher, your application should now show the correct application ID. Select this and click "Deploy". This process can take a few minutes - keep an eye on the GAE console log to see when the application has successfully deployed.

Once the deployment process is complete, go to http://your application id.appspot.com//, replacing your application id with your own ID.

Finally - Voilà! - your application is live!

In the next part...

This part of the tutorial introduced Google App Engine and PayPal Adaptive Payments with a simple online marketplace application.

Part 2 of this tutorial will extend the application by introducing chained payments, embedded payments and IPN.

Links and Further Information