Web.py Application – Paypal Transaction

Visit the Github repository for the full code example


Paypal is one of the most prominent online transaction platform. And there is a lot that you can do with paypal. This tutorial will bring you through using the paypal rest API with web.py to create an application that is capable of handling paypal transaction.

In this tutorial, we will be using the paypalrestsdk to access the API which we will be using to create and execute our transactions.

Before starting

Before we start, a little about how the PayPal SDK works. You will first have to create a payment with a unique payment id. The payment will have two main stages, the authorization stage and the execution stage.

In the authorization stage, the user will review the details of the transaction and if they are happy with all the details, they will authorize it, which brings us to the next stage, execution.

In the execution stage, the transaction of the specified payment id will be carried out and only then will the transaction amount be actually transferred between the accounts.

We will be doing all the testing in the sandbox PayPal (don’t need real money), which you will need a Paypal Developer account to access.

Setting up your account

Head to Paypal Developer and create a new REST app, check that you have the client id and the client secret. Then head over to Sandbox Accounts and make sure you have 2 accounts, one for the buyer, one for the seller.

Also, make sure you have the python package installed. To get it up and running, simply run pip install paypalrestsdk

Initialization stage

The good thing about using the python package is that they handle almost everything for you. To initialize your paypal application, you have to give it your client id and client secret. As for the urls, they point to the locations where your application actually handles the execution of the transaction (more on that later).

import paypalrestsdk

PP_CLIENT_ID = '<client id>'
PP_CLIENT_SECRET = '<client secret>'

PP_URL_RETURN = 'http://localhost:8080/pay'
PP_URL_CANCEL = 'http://localhost:8080/'

    "mode": "sandbox",
    "client_id": PP_CLIENT_ID,
    "client_secret": PP_CLIENT_SECRET

For the web application, here is the basic structure of the application. In /create, the application will create the transaction where details such as the transaction amount and details will be used for the payment, and /pay will then be used for the execution of the transaction, which actually transfer the money to your seller account.

import web

urls = [
    '/create', 'PaymentCreate',
    '/pay', 'PaymentExecute'
app = web.application(urls, globals())

Creating the payment transaction

First, we will create a function createPayment that handles the API part of the code. The function will create a Payment object with the basic details, including the amount to be transferred and the description of the payment, etc…

For now, the transaction method is set to paypal account, which means that the user must have a paypal account in order to complete the transaction. You can add in the option to complete the transaction via credit cards, but you will have to add in a bit more details (information available at REST API documentation).

def createPayment(amt, description='', currency='SGD'):
    payment = paypalrestsdk.Payment({
        'intent': 'sale',
        'payer': {
            'payment_method': 'paypal'
        'transactions': [{
            'amount': {
                'total': '%.2f'%float(amt),
                'currency': currency
            'description': description

    if payment.create():
        href = [str(l.href) for l in payment.links if l.method == 'REDIRECT'][0]
        return str(href)
        return payment.error

For the web application, this web.py class will take in the values for amt and des, then calling the createPayment function and redirecting the users to the authorization page (which is on the paypal site).

class PaymentCreate:
    def GET(self):
        i = web.input()

        if not i.get('amt') or not i.get('des'):
            return web.badrequest()
        amt = i.amt
        des = i.des

        res = createPayment(amt, des)
        if type(res) == str:
            return web.seeother(res)
            return web.notfound()

Executing the payment transaction

Assuming that the users have authorized the transaction all you have to do next is to execute the transaction and BAMM, you will have your money.

So for the executePayment function, the payment_id and the payer_id (id of the user) will be required for the execution to take place.

def executePayment(pid, uid):
    payment = paypalrestsdk.Payment.find(pid)

    if payment.execute({"payer_id": uid}):
        return str(payment.id)
        return payment.error

Some of you may have notice the variable, PP_URL_RETURN in the initialization stage. This link points to the server’s payment execution handler (the web.py class that handles the execution), which in this case, is /pay

In this web.py class, the payment is executed using the executePayment function using the values paymentId and PayerID (all part of PayPal’s SDK redirect request).

class PaymentExecute:
    def GET(self):
        i = web.input()
        if not i.get('paymentId') or not i.get('PayerID'):
            return web.badrequest()
        id_payment = i.get('paymentId')
        id_payer = i.get('PayerID')

        res = executePayment(id_payment, id_payer)
        if type(res) is str:
            return { 'success': True }
            return { 'error': res }

How to tell that it worked

Head to SandBox PayPal, and login with your buyer account(-buyer@.com). Under the recent activity section, view the details of the transaction to ensure that the correct amount is transferred, and that the corresponding description you have entered is returned.

Things to note:

  • There are alot more details you can add to your application, visit the Paypal REST API to review all the possible details that can be included.
  • Official documentation for the python package
  • When using it for real, switch the mode in the initialization stage to live

Visit the Github repository for the full code examples.

Feel free to email me if you have any questions.