O'Reilly logo

PayPal APIs: Up and Running, 2nd Edition by Matthew A. Russell

Stay ahead with the world's most comprehensive technology and business learning platform.

With Safari, you learn the way you learn best. Get unlimited access to videos, live online training, learning paths, books, tutorials, and more.

Start Free Trial

No credit card required

Chapter 1. PayPal API Overview

This chapter provides a very brief overview of PayPal’s Name-Value Pair (NVP) APIs, the primary way that you’ll interact with PayPal products throughout the remainder of this book. Since using the NVP APIs is as simple as making some HTTP requests and parsing the responses, we’ll get a Python project up and running with Google App Engine (GAE) as part of this initial overview. Future chapters all use Python-based GAE projects, so unless you’re definitely planning to port the code without running it, you should make the most of this opportunity to learn the basics. After reading this chapter, it is highly recommended that you check out and run the sample code for Tweet Relevance as introduced in Appendix A.

Overview of PayPal API Requests

PayPal’s NVP API makes it simple to integrate payments into your application. As the merchant, your web application constructs an NVP string and transmit it via HTTPS (HTTP Secure) to the PayPal authorization server, and PayPal sends back an NVP-formatted response that your web application parses for the information relevant to the payment. Figure 1-1 shows this basic request and response workflow, which is typical of just about any web application.

Typical NVP request and response

Figure 1-1. Typical NVP request and response

The request identifies:

  • The name or method of the API operation to be performed and its version

  • PayPal API credentials

  • Operation-specific parameters formatted as name/value pairs

Note

Various PayPal products may require additional specific request parameters as indicated by PayPal’s official documentation. For example, Adaptive Payments APIs also require an APP ID field to be specified.

The PayPal API server executes the operation and returns a response containing:

  • Acknowledgment of success or failure (including any warnings returned in case of failure)

  • PayPal tracking information specific to the API operation

  • Response-specific information required to fulfill the request

Some PayPal products such as Express Checkout require calls to multiple API operations, while others such as Direct Pay (part of Website Payments Pro) only require one call. We’ll review Express Checkout in the next chapter, but Figure 1-2 is included to illustrate its typical flow, which should look pretty familiar and intuitive if you’ve ever used PayPal. Either way, interacting with PayPal products is just a series of API calls that allow you to accomplish a wide variety of tasks. A few examples of the possible transactions PayPal products support include:

  • Accepting PayPal as part of a streamlined checkout process

  • Charging a credit card

  • Capturing previously authorized payments

  • Reauthorizing or voiding previous authorizations

  • Paying single or multiple recipients

  • Issuing full or partial refunds

  • Searching transactions histories

  • Retrieving details of specific transactions

  • Processing payments involving more than one party

  • Setting up recurring subscription charges

  • Accepting Donations

A typical Express Checkout in which a merchant site establishes a session with PayPal and then redirects the buyer to PayPal for specification of shipping and payment information. Once the buyer confirms transaction details, PayPal redirects the buyer back to the merchant site where it regains control of the checkout and can issue additional requests to PayPal for final payment processing.

Figure 1-2. A typical Express Checkout in which a merchant site establishes a session with PayPal and then redirects the buyer to PayPal for specification of shipping and payment information. Once the buyer confirms transaction details, PayPal redirects the buyer back to the merchant site where it regains control of the checkout and can issue additional requests to PayPal for final payment processing.

With a broad understanding of how payment transactions are implemented, let’s briefly segue into an overview of GAE and how to implement HTTP requests, the essential skill required to interact with PayPal APIs.

Google App Engine Primer

GAE is a terrific platform, and this book takes advantage of its simplicity and uses it as the standard for communicating how to build web applications that interact with PayPal APIs. It’s very easy to get an application up and running locally for test purposes, yet the same applications that you’ve implemented can be run and scaled out on the very same infrastructure that Google uses for its own applications with virtually no additional work! A vast amount of documentation about GAE is available online, so let’s assume that you’ll take a little time to familiarize yourself by reviewing the App Engine Python Overview, which includes a “getting started” guide that walks you through installation of the Python Software Development Kit (SDK).

Building and Deploying Your First App

Assuming you’ve installed the Python SDK[1] and done little more than use Google App Engine Launcher to create a new sample project, you’ve essentially already implemented a traditional “Hello, world” program that you can run on your local machine. Launch the program by clicking the Run button, and then click the Browse button to launch and navigate your browser so that you successfully see “Hello world!” to make sure that everything is up and running. Then, take a peek at the contents of app.yaml and main.py, which are reproduced in Examples 1-1 and 1-2 for convenience. At a high level, the salient points are that the name of the application is helloworld; that MainHandler is assigned to the root context of the web application, as indicated by the presence of ('/', MainHandler) in the list that’s supplied to the WSGIApplication class constructor; and a get method is defined for MainHandler, which allows the web application to respond to your browser’s GET request when you click the Browse button from the Google App Engine Launcher.

Example 1-1. app.yaml from a stock GAE project

application: helloworld
version: 1
runtime: python
api_version: 1

handlers:
- url: /favicon\.ico
  static_files: favicon.ico
  upload: favicon\.ico

- url: .*
  script: main.py

Example 1-2. main.py from a stock GAE project

from google.appengine.ext import webapp
from google.appengine.ext.webapp import util

class MainHandler(webapp.RequestHandler):
    def get(self):
        self.response.out.write('Hello world!')


def main():
    application = webapp.WSGIApplication([('/', MainHandler)],
                                         debug=True)
    util.run_wsgi_app(application)


if __name__ == '__main__':
main()

At this point, if you naively click the Deploy button to try to deploy the application to the Web, you’ll get an unfortunate error in the logging console to the effect of, “You do not have permission to modify this app (app_id=u'helloworld').” In other words, it’s telling you that the application id of helloworld that’s specified in app.yaml is already registered by someone else and that you’ll need to try another one. It’s unfortunate that the error message doesn’t give you a bit more information, because what you really need to do at this point is click the Dashboard button to log into your GAE account and register a web application with a unique identifier, which in turn corresponds to a unique appspot.com subdomain. For example, a GAE web application with an application identifier of helloworld would correspond to http://helloworld.appspot.com. You can only register a limited number of application identifiers for free, so it’s recommended that you create a generic identifier that you can reuse for multiple test applications. The identifier that’ll be used throughout this book is ppapis2e, which somewhat corresponds to this book’s title, PayPal APIs: Up and Running (Second Edition). You can use whatever identifier you’d like.

You should verify that you can register an application identifier and deploy it to appspot.com before reading further. The steps you should take simply involve:

  • Clicking the Dashboard button in the Google App Engine Launcher

  • Authenticating into the dashboard with your Google account

  • Creating an application in the dashboard

  • Changing the top line of your local app.yaml file to reflect your web application’s name you’ve chosen

  • Clicking the Deploy button in the Google App Engine Launcher

  • Navigating your web browser to the corresponding URL on http://appspot.com that corresponds to the subdomain that you’ve chosen, i.e., a URL such as http://ppapis2e.appspot.com

There’s lots more that could be said about GAE, but we should review at least one more important skill that you’ll need before leaving you to the online documentation: implementing HTTP requests. In GAE parlance, this skill is filed under the URL Fetch Python API.

Fetching URLs

One thing that should be mentioned about GAE is that there are some modules from the standard library that are not accessible because of the sensitive nature of running applications in a shared environment. Unfortunately, urllib, urllib2, and httplib are some common modules that you may have used for implementing HTTP requests that are off limits to your GAE application; however, GAE naturally provides ways to make both synchronous and asynchronous requests in a familiar enough manner. Example 1-3 is an updated version of Example 1-2 that makes use of the urlfetch function to perform a synchronous HTTP request. (Asynchronous requests are made in a very similar manner except that a callback function defines what should happen once the request completes.) Note the use of the keyword parameter validate_certificate, which is employed to ensure that the request is securely completed so as to avoid potential man-in-the-middle attacks. You should be able to deploy the application and verify that it can indeed securely fetch the URL https://paypal.com/ before continuing.

Tip

When implementing an online commerce application, always be a bit paranoid and routinely double-check security assumptions.

Example 1-3. An updated main.py that illustrates how to use the urlfetch function to perform a secure HTTP request

from google.appengine.ext import webapp
from google.appengine.ext.webapp import util
from google.appengine.api import urlfetch

class MainHandler(webapp.RequestHandler):
    def get(self):
        url = "https://www.paypal.com/"
        result = urlfetch.fetch(
                      url,  
                      validate_certificate=True # Avoid man-in-the-middle attacks
                 )   
        if result.status_code == 200:
            self.response.out.write('Successfully fetched ' + url)
        else:
            self.response.out.write('Could note fetch %s (%i)' % (url, result.status_code,))


def main():
    application = webapp.WSGIApplication([('/', MainHandler)],
                                         debug=True)
    util.run_wsgi_app(application)

if __name__ == '__main__':
    main()

Hopefully, you are now comfortable enough with GAE that you can find your way around and use the online documentation to fill in basic knowledge gaps. Generally speaking, the overall flow for each application is discussed to some degree when sample code is introduced, and inline source code comments are provided wherever helpful, but a basic working knowledge of GAE is assumed moving forward.

Making PayPal API Requests with App Engine

Note

Although PayPal offers a number of SDKs for a number of common programming languages including Java, ASP.NET, Ruby, PHP, and Cold Fusion, the applications in this book use the NVP APIs directly. Visit the SDKs and Downloads section of PayPal’s Integration Center for more details about the various SDKs that are available.

In order to make PayPal API requests, you’ll first need to register a merchant account and obtain API credentials. Since it wouldn’t be a very good idea to implement a commerce application in a live production environment that involves real accounts and real money, PayPal offers a wonderful sandbox environment to use while developing your application. Using the sandbox environment, you can set up faux buyer and seller accounts to fully test the payment flows and track the flow of funds before flipping the switch on your application code and going live. The faux buyer account acts like someone buying a product from a marketplace, and the faux seller account acts like the marketplace that’s selling the products. For the most part, switching between the two is as simple as changing the target server URL and the API credentials from sandbox values to production values. The rest of your application will remain unchanged, so it’s a fairly painless experience to go live. The remainder of this chapter steps through the process of obtaining API credentials for the sandbox environment, and shows you how to use them to make a PayPal API request.

Obtaining API Credentials for the Sandbox Environment

Developing your application only requires access to the PayPal API sandbox. You can sign up for access to the sandbox environment at https://developer.paypal.com. Once your account is established, you can create test accounts for buyers and sellers as well as obtain API credentials. Sandbox accounts and live accounts require different processes to obtain credentials.

Note

This book doesn’t cover some of the nuances of transitioning to a live environment, but you’ll essentially just sign up for a merchant account, substitute the production API credentials that come with your merchant account into your web application, and update the API endpoints that your web application uses for making requests. There’s also a handy Go Live Checklist that’s maintained in PayPal’s official documentation that summarizes the key steps.

Use the following steps for a sandbox account:

  1. Go to https://developer.paypal.com and click Sign Up Now.

  2. Enter the requested information and click Agree and Submit.

  3. PayPal will send you an email to complete the signup process.

  4. After confirming your email address, you can create test accounts and access API credentials by logging into https://developer.paypal.com/ with the email/password combination you provided during the signup process.

  5. Click the Test Accounts link.

  6. Click the Create Test Account link.

  7. Choose Seller for the account type and select the other appropriate options. Going with the defaults is highly recommended and results in API credentials being created automatically.

  8. Click the API credentials link to access your API credentials.

  9. Click the Enter Sandbox Test Site button to log in to faux buyer and seller accounts. Note that after the initial login to https://developer.paypal.com/, you can log in to individual sandbox accounts by accessing https://www.sandbox.paypal.com directly.

Warning

You cannot use the same email/password combination to log in to your sandbox account at https://developer.paypal.com/ that you use to log in to your ordinary PayPal account (unless, of course, you intentionally used the very same email/password combination for both accounts, which is not recommended).

If this is your first encounter with the PayPal Sandbox Test Environment, these steps can seem slightly confusing at first since you end up with so many accounts. The key takeaways are that you can create a developer account and log in to the sandbox environment. From within the sandbox environment, you can create faux buyer and seller accounts, and the creation of a faux seller account provides you with API credentials for the faux merchant account. Note, however, that in order to log in to these faux accounts, you’ll need to establish a session by first logging in through https://www.sandbox.paypal.com and using the faux account credentials for each individual account; you cannot log in to http://paypal.com with the faux credentials. Figures 1-3 through 1-7 show the overall login flow.

Log in to the sandbox environment with your developer account (which is separate from your ordinary PayPal account).

Figure 1-3. Log in to the sandbox environment with your developer account (which is separate from your ordinary PayPal account).

Once logged into the sandbox environment, you can create and manage test accounts from the Test Accounts menu item.

Figure 1-4. Once logged into the sandbox environment, you can create and manage test accounts from the Test Accounts menu item.

Create faux buyer and seller accounts.

Figure 1-5. Create faux buyer and seller accounts.

Select an account and click Enter Sandbox Test Site to launch a login. (Notice the message in the upper-right corner of the screen that alerts you that you have already established a developer session.)

Figure 1-6. Select an account and click Enter Sandbox Test Site to launch a login. (Notice the message in the upper-right corner of the screen that alerts you that you have already established a developer session.)

Use the faux account credentials to log in to the account—it provides the same view as if it were a real merchant account!

Figure 1-7. Use the faux account credentials to log in to the account—it provides the same view as if it were a real merchant account!

Once you’ve successfully worked your way through the developer sandbox fundamentals, you’re ready to use your faux merchant account’s API credentials to programatically make a request.

Making API Requests with 3-Token Credentials

PayPal offers two methods for authenticating requests: certificates and “3-token credentials,” which are comprised of a username, password, and signature. You are already familiar with the concept of securing an account by using a username and a password, but perhaps you’re not familiar with the additional signature. Essentially, the signature is an additional password that is intrinsically virtually impossible to guess or crack, and the addition of it to the authentication process results in a scheme known as multi-factor authentication since the signature is an additional factor that is used in addition to the password. By default, faux accounts are set up with 3-token credentials, and we’ll use the API Signature method of specifying credentials throughout this book. Figure 1-8 illustrates the 3-token credentials in a developer sandbox account.

PayPal API credentials are available through the developer sandbox environment

Figure 1-8. PayPal API credentials are available through the developer sandbox environment

The remainder of this section works through a few implementation details and culminates with the equivalent of a working “Hello, world!” example to illustrate how to make a PayPal API request and parse the response. Specifically, we’ll call the SetExpressCheckout API, which is the first step involved in using the Express Checkout product. Express Checkout is featured in depth in the next chapter, so for now, don’t worry about the details of what it does. At this point, just think of it as an opaque API operation, and focus on the details of making the request and parsing the response. The key steps your application must accomplish to post to the NVP API include URL encoding, constructing the request in a format the NVP API can interpret, and posting the request via HTTPS to the server. The remainder of this section works through these details.

URL encoding and decoding

Both the request to the PayPal server and the response from the server are URL encoded. This method ensures that you can transmit special characters, characters not typically allowed in a URL, and characters that have reserved meanings in a URL. For example:

NAME=John Doe&COMPANY=Acme Goods & Services

is URL encoded as follows:

NAME=John+Doe&Company=Acme+Goods+%26+Services

Each application language typically has a specific built-in URL encode method. Refer to the list in Table 1-1 for some specific functions in common programming languages.

Table 1-1. URL encoding and decoding methods for common programming languages

Application languageEncoding Function NameDecoding Function Name
ASP.NETSystem.Web.HttpUtility.UrlEncodeSystem.Web.HttpUtility.UrlDecode
Classic ASPServer.URLEncodeNo built-in function
Javajava.net.URLEncoder.encodejava.net.URLEncoder.decode
PHPurlencodeurldecode
ColdFusionURLEncodeURLDecode
Pythonurllib.urlencodeurlparse.parse_qs

Since Python is used as the primary programming language in this book, Example 1-4 illustrates a Python interpreter session showing you how to decode and encode URL query string parameters. The very same logic holds for your GAE app, except that the parse_qs function may need be imported from the cgi module instead of the urlparse module because of changes to Python packages between versions 2.6 and 2.7.

Warning

At the time of this writing, Python 2.5 was still the default version to run on GAE, but Python 2.7 seemed imminently releasable and was in an experimental state. Note that as of Python 2.6, parse_qs was moved into the urlparse module, so attempting to import it from cgi will fail if and when GAE defaults to Python version 2.7.

Example 1-4. Encoding and decoding a URL with Python version 2.7

>>> import urllib
>>> encoded_qs = urllib.urlencode({'NAME' : 'John Doe', 'COMPANY' : 'Acme Goods & Services'})
>>> print encoded_qs
'COMPANY=Acme+Goods+%26+Services&NAME=John+Doe'

>>> import urlparse
>>> decoded_qs = urlparse.parse_qs(encoded_qs) # use cgi.parse_qs for Python 2.5 and older
>>> print decoded_qs
{'COMPANY': ['Acme Goods & Services'], 'NAME': ['John Doe']}

One very minor nuance to observe is that parse_qs returns lists of values for each field in the dictionary result. The reason is that it is legal for URL query string items to be keyed by duplicate field names. For example, foo=1&foo=2&foo=3 is a valid query string, so parse_qs needs to be able to return all of these values back to you uniformly.

Request and response format

Each NVP API request is composed of required and optional parameters and their corresponding values. Parameters are not case-sensitive, but certain values such as the API Password, (PWD), are case-sensitive. The required parameters for all NVP API transactions are USER, PWD, METHOD, and VERSION. The METHOD, or type of transaction you are calling the NVP API to process, has an associated VERSION. Together the METHOD and VERSION define the exact behavior of the API operation you want performed. This will be followed by the information posted from your application, including things such as Item, Quantity, and Cost.

Tip

API operations can change between versions, so when you change a version number, be sure to test your application code again before going live.

Each NVP API response is composed of an acknowledgment (or ACK), a timestamp, a CorrelationID unique to the transaction, and a build number stating the API version used to process the transaction. This basic response is then followed by a series of name/value pairs holding the transaction data, which you can parse and handle accordingly in your application. The acknowledgment will be one of the responses outlined in Table 1-2.

Tip

PayPal maintains a fairly detailed list of error codes that is very handy to bookmark and consult during debugging situations.

Table 1-2. ACK parameter values

Type of responseValue
Successful responseSuccess, SuccessWithWarning
Partially successful response (relevant only for parallel payments; some of the payments were successful and others were not)PartialSuccess
Error response codeFailure, FailureWithWarning, Warning

Making a PayPal Request with GAE

Now that we have established some of the fundamentals, let’s make a PayPal API request using GAE. Example 1-5 ties together the common concepts from this chapter and shows you how do it.

Example 1-5. An updated main.py that illustrates how to make a PayPal API request and parse the response

from google.appengine.ext import webapp
from google.appengine.ext.webapp import util
from google.appengine.api import urlfetch

import urllib
import cgi

class MainHandler(webapp.RequestHandler):
    def get(self):

        # Sandbox NVP API endpoint

        sandbox_api_url = 'https://api-3t.sandbox.paypal.com/nvp'

        nvp_params = { 
            # 3 Token Credentials - Replace XXX with your own values

            'USER' : 'XXX',
            'PWD' : 'XXX',
            'SIGNATURE' : 'XXX',

            # API Version and Operation
            'METHOD' : 'SetExpressCheckout',            
            'VERSION' : '82.0',

            # API specifics for SetExpressCheckout            
            'PAYMENTREQUEST_0_AMT' : '1.00',
            'RETURNURL' : 'http://ppapis2e.appspot.com/xxx_returnurl_xxx',
            'CANCELURL' : 'http://ppapis2e.appspot.com/xxx_cancelurl_xxx'
        }   

        # Make a secure request and pass in nvp_params as a POST payload

        result = urlfetch.fetch(
                    sandbox_api_url,  
                    payload = urllib.urlencode(nvp_params),
                    method=urlfetch.POST,
                    validate_certificate=True
                 )   

        if result.status_code == 200: # OK

            decoded_url = cgi.parse_qs(result.content)    

            for (k,v) in decoded_url.items():
                self.response.out.write('<pre>%s=%s</pre>' % (k,v[0],))
        else:

            self.response.out.write('Could note fetch %s (%i)' % 
                    (url, result.status_code,))

def main():
    application = webapp.WSGIApplication([('/', MainHandler)],
                                         debug=True)
    util.run_wsgi_app(application)

if __name__ == '__main__':
    main()

Hopefully, the code is pretty self-explanatory. GAE’s urlfetch.fetch function is used to make a secure request to the sandbox API endpoint, which includes the standard USER, PWD, and SIGNATURE parameters from under the “API Credentials” tab of the sandbox environment, along with an API operation and version as defined by METHOD and VERSION, respectively. The SetExpressCheckout API requires a minimum of a request amount and redirect URL.

Tip

Keeping up with updates to PayPal’s API isn’t quite as simple as one would imagine. The simplest way to keep up with developments is to consult About Previous Versions of the API.

The important thing to take away from this particular example is just that you can substitute in your own 3-token credentials and successfully execute the code. It should run on your local development machine, but also take the opportunity to deploy it as a live application and see it run out on the Web as well.

Example 1-6. Sample results from executing Example 1-5, which calls SetExpressCheckout and displays the results

ACK=Success
TIMESTAMP=2011-11-16T15:38:28Z
TOKEN=EC-7JK870639U925801V
VERSION=82.0
BUILD=2256005
CORRELATIONID=f7f4dbb891723

Once you’ve successfully run the code and get back a sample response as shown in Example 1-6, you should be ready to move on to the next chapter, where we’ll explore the Express Checkout product in more detail and build a (hopefully) fun and realistic sample app that incorporates it to implement the payment flow. However, before turning to the next chapter, you should definitely check out, review, and run the sample code for Tweet Relevance, the foundational sample project that’s used throughout this book and introduced in Appendix A.

Recommended Exercises

  • Complete the (official) Python tutorial.

  • Review and execute the examples in the Getting Started with Python documentation for GAE.

  • Check out, review, and run the sample code for Tweet Relevance, as introduced in Appendix A.

  • Bookmark and spend a few minutes browsing PayPal’s official documentation.

  • Take some time to explore the GAE development console. It provides extensive options for interacting with objects persisted in the data store, an interactive console, and much more. Familiarity with it is essential to efficient GAE software development.

Note

All sample code for this book is available online at GitHub and is conveniently organized by chapter. Although much of the code is included in the text of this book so that it’s as instructional as possible, always reference the latest bug-fixed code on GitHub as the definitive reference for sample code. Bug tickets and patches are welcome!



[1] As of this writing, version 1.6.0 is the latest SDK, which supports the Python 2.5 runtime by default. The Python 2.7 runtime is a stable—but still considered experimental—feature.

With Safari, you learn the way you learn best. Get unlimited access to videos, live online training, learning paths, books, interactive tutorials, and more.

Start Free Trial

No credit card required