PayPal REST API Payment System (PHP)

Everyone’s been really excited about PayPal REST API since its launch, so I decided to try and explore PayPal’s new RESTful web service. And after playing a bit with it, I was able to create my own simple online cell phone store successfully. Here’s how!

Before we continue, make sure you have signed up for PayPal Developer account for testing mode, and for production mode you will need real PayPal account. Obtain your Client Id and Client Secret from developer portal (for testing) OR from your real PayPal account (for production mode). PayPal REST SDK requires PHP version 5.3.0 +, so make sure your PHP is latest.

paypal-rest-api-store

PayPal PHP SDK is included in downloadable file below, but you can get your own copy from github. If you are using composer, just point to downloaded file and give “composer update” command to have your SDK updated to latest version. Well, you can forget whole composer thing right now if it doesn’t ring a bell!

Back to tutorial, I have created four files for my Online Cell Phone store, but we only need to focus on first two files to get things done. Other two files are helper script and cancellation page.

  • Index.php – (Products page) contains list of products for sale.
  • Order_process.php – Processes PayPal payment.
  • Functions.inc.php – Helper script, contains functions needed for processing.
  • Payment_cancel.html – PayPal redirects user to this page in-case of cancellation.

Products Page

In this page I have created list of items I want to sell, each item has HTML form, which contains its name, quantity, code and price ready to be posted to Order_process.php. I have tried using some CSS to make it look good, but hopefully you will do it better.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<img src="images/cell_phone1.jpg" width="220" height="220">
<div class="item-name">Star mini S5</div>
<div class="btn-wrap">
<form action="order_process.php" method="post">
Qty:
<select name="qty">
    <option>1</option><option>2</option><option>3</option><option>4</option><option>5</option><option>8</option><option>10</option><option>20</option>
</select>
<input type="hidden" name="item_name" value="Star mini S5" />
<input type="hidden" name="item_code" value="001" />
<input type="hidden" name="item_price" value="100" />
<input type="submit" value="Buy $100" />
</form>
</div>

Order Processes

Next we look into order processes page. Here you might get bit confused, but the steps are fairly simple, let me make bit easier for you by pointing out the steps below.

  • Step 1: Get product POST Values from products page.
  • Step 2: Create a payment by constructing a payment object.
  • Step 3: Get approval url from the response, and redirect the user to PayPal for approval page.
  • Step 4: After Payment confirmation by user, execute payment on behalf of user using Payment ID andPayer ID.
  • Step 5: Redirect user to return URL and display success message set earlier in PHP session.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
<?php
session_start(); //start session

define('CLIENT_ID', 'WIUEEW32IE2DSXCmsdwo9Eew23433SDOIWUDs'); //your PayPal client ID
define('CLIENT_SECRET', 'sEWOIDWE-EWeeewEWRdWE86LdfGFEfAaSDOoDS0WeDNVcXD-xFsSw'); //PayPal Secret
define('RETURN_URL', 'http://YOUR-SITE/paypal-store/order_process.php'); //return URL where PayPal redirects user
define('CANCEL_URL', 'http://YOUR-SITE/paypal-store/payment_cancel.html'); //cancel URL
define('PP_CURRENCY', 'USD'); //Currency code
define('PP_CONFIG_PATH', ''); //PayPal config path (sdk_config.ini)

include_once __DIR__ . "/vendor/autoload.php"; //include PayPal SDK
include_once __DIR__ . "/functions.inc.php"; //include our PayPal functions

#### Prepare for Payment ####
if(isset($_POST["item_code"])){
   
    $item_name = $_POST["item_name"]; //get item code
    $item_code = $_POST["item_code"]; //get item code
    $item_price = $_POST["item_price"]; //get item price
    $item_qty = $_POST["qty"]; //get quantity
    /*
    Note: DO NOT rely on item_price you get from products page, in production mode get only "item code"
    from the products page and then fetch its actual price from Database.
    Example :
    $results = $mysqli->query("SELECT item_name, item_price FROM products WHERE item_code= '$item_code'");
    while($row = $results->fetch_object()) {
        $item_name = $row->item_name;
        $item_price = item_price ;
    }  
    */


    //set array of items you are selling, single or multiple
    $items = array(
        array('name'=> $item_name, 'quantity'=> $item_qty, 'price'=> $item_price, 'sku'=> $item_code, 'currency'=>PP_CURRENCY)
    );
   
    //calculate total amount of all quantity.
    $total_amount = ($item_qty * $item_price);
   
    try{ // try a payment request
        //if payment method is paypal
        $result = create_paypal_payment($total_amount, PP_CURRENCY, '', $items, RETURN_URL, CANCEL_URL);
           
        //if payment method was PayPal, we need to redirect user to PayPal approval URL
        if($result->state == "created" && $result->payer->payment_method == "paypal"){
            $_SESSION["payment_id"] = $result->id; //set payment id for later use, we need this to execute payment
            header("location: ". $result->links[1]->href); //after success redirect user to approval URL
            exit();
        }
       
    }catch(PPConnectionException $ex) {
        echo parseApiError($ex->getData());
    } catch (Exception $ex) {
        echo $ex->getMessage();
    }
}


### After PayPal payment method confirmation, user is redirected back to this page with token and Payer ID ###
if(isset($_GET["token"]) && isset($_GET["PayerID"]) && isset($_SESSION["payment_id"])){
    try{
        $result = execute_payment($_SESSION["payment_id"], $_GET["PayerID"]);  //call execute payment function.

        if($result->state == "approved"){ //if state = approved continue..
            //SUCESS
           
            unset($_SESSION["payment_id"]); //unset payment_id, it is no longer needed
           
            //get transaction details
            $transaction_id         = $result->transactions[0]->related_resources[0]->sale->id;
            $transaction_time       = $result->transactions[0]->related_resources[0]->sale->create_time;
            $transaction_currency   = $result->transactions[0]->related_resources[0]->sale->amount->currency;
            $transaction_amount     = $result->transactions[0]->related_resources[0]->sale->amount->total;
            $transaction_method     = $result->payer->payment_method;
            $transaction_state      = $result->transactions[0]->related_resources[0]->sale->state;
           
            //get payer details
            $payer_first_name       = $result->payer->payer_info->first_name;
            $payer_last_name        = $result->payer->payer_info->last_name;
            $payer_email            = $result->payer->payer_info->email;
            $payer_id               = $result->payer->payer_info->payer_id;
           
            //get shipping details
            $shipping_recipient     = $result->transactions[0]->item_list->shipping_address->recipient_name;
            $shipping_line1         = $result->transactions[0]->item_list->shipping_address->line1;
            $shipping_line2         = $result->transactions[0]->item_list->shipping_address->line2;
            $shipping_city          = $result->transactions[0]->item_list->shipping_address->city;
            $shipping_state         = $result->transactions[0]->item_list->shipping_address->state;
            $shipping_postal_code   = $result->transactions[0]->item_list->shipping_address->postal_code;
            $shipping_country_code  = $result->transactions[0]->item_list->shipping_address->country_code;
                       
              /*
                ####  AT THIS POINT YOU CAN SAVE INFO IN YOUR DATABASE ###
                //see (https://www.sanwebe.com/2013/03/basic-php-mysqli-usage) for mysqli usage
               
                //Open a new connection to the MySQL server
                $mysqli = new mysqli('host','username','password','database_name');
               
                //Output any connection error
                if ($mysqli->connect_error) {
                    die('Error : ('. $mysqli->connect_errno .') '. $mysqli->connect_error);
                }      
               
                $insert_row = $mysqli->query("INSERT INTO transactions (payer_id, payer_name, payer_email, transaction_id)
                    VALUES ('payer_first_name' , '$payer_email' , '$transaction_id')");
                */

                       
            //Set session for later use, print_r($result); to see what is returned
            $_SESSION["results"]  = array(
                    'transaction_id' => $transaction_id,
                    'transaction_time' => $transaction_time,
                    'transaction_currency' => $transaction_currency,
                    'transaction_amount' => $transaction_amount,
                    'transaction_method' => $transaction_method,
                    'transaction_state' => $transaction_state
                    );
                       
            header("location: ". RETURN_URL); //$_SESSION["results"] is set, redirect back to order_process.php
            exit();
        }
       
    }catch(PPConnectionException $ex) {
        $ex->getData();
    } catch (Exception $ex) {
        echo $ex->getMessage();
    }

}

### Display order confirmation if $_SESSION["results"] is set  ####
if(isset($_SESSION["results"]))
{
    $html = '<!DOCTYPE HTML>';
    $html .= '<html>';
   
   
    $html .= '<head>';
    $html .= '<meta http-equiv="Content-Type" content="text/html; charset=utf-8">';
    $html .= '<title>Order Confirm Details</title>';
    $html .= '<style type="text/css">';
    $html .= '.transaction_info {margin:0px auto; background:#F2FCFF;; max-width: 750px; color:#555;}';
    $html .= '.transaction_info thead {background: #BCE4FA;font-weight: bold;}';
    $html .= '.transaction_info thead tr th {border-bottom: 1px solid #ddd;}';
    $html .= '</style>';
    $html .= '</head>';
    $html .= '<body>';

    $html .='<div align="center"><h2>Payment Success</h2></div>';
    $html .= '<table border="0" cellpadding="10" cellspacing="0" class="transaction_info">';
   
    $html .= '<thead><tr><td>Transaction ID</td><td>Date</td><td>Currency</td><td>Amount</td><td>Method</td><td>State</td></tr></thead>';
   
    $html .= '<tbody><tr>';
    $html .= '<td>'.$_SESSION["results"]["transaction_id"].'</td>';
    $html .= '<td>'.$_SESSION["results"]["transaction_time"].'</td>';
    $html .= '<td>'.$_SESSION["results"]["transaction_currency"].'</td>';
    $html .= '<td>'.$_SESSION["results"]["transaction_amount"].'</td>';
    $html .= '<td>'.$_SESSION["results"]["transaction_method"].'</td>';
    $html .= '<td>'.$_SESSION["results"]["transaction_state"].'</td>';
    $html .= '</tr>';
    $html .= '<tr><td colspan="6"><div align="center"><a href="index.php">Back to Products Page</a></div></td></tr>';
    $html .= '</tbody>';
    $html .= '</table>';
    $html .= '</body>';
    $html .= '</html>';
   
    echo $html;
   
    unset($_SESSION["results"]);
}
?>

That’s it! you should now have a functional online store of your own using PayPal REST API. There is now just one more step to follow. Before you make it live find sdk_config.ini config file, open it and change Service mode to live and don’t forget to enter real PayPal client ID and Secret in order_process.php.

Conclusion

PayPal REST API has lots of new features and supports a number of countries and currencies, please check whether your country is in the list. For countries not yet supported by the REST API, you can take a look at my other tutorial about PayPal.

Download Demo

  1. Hello,

    Could you please help me?
    Tested the code in sandbox mode, it is working properly, but when I switched to live mode
    I am getting an error saying “Got Http response code 401 when accessing https://api.sandbox.paypal.com/v1/oauth2/token.”.
    I updated the mode in sdk_config.ini to live and used live client ID and secret key in functions.inc.php. Still it redirecting to sandbox URL.
    Please guide me.
    Thanks

     Reply
  2. Thank you. I am using the sample codes from php paypal sdk rest api home page and they can prove pretty intimidating especially when you look at the success request and response objects.

    I came here to learn what are the essential data that we should capture from the API response and your example above together with the Demo is extremely useful in showing the whole transaction process.

     Reply
  3. How do i make it live ?
    i tried changing .ini file but that doesn’t work

     Reply
  4. Many Thanks for tutorial
    Its work for me

    Regards,

    Tariq

     Reply
  5. Hi,

    if I use the API I get a error back “error:14094410:SSL routines:SSL3_READ_BYTES:sslv3 alert handshake failureArray ( ) ” any idea to fix it?

    Stefan

     Reply
    • It works if you update


      public static $defaultCurlOptions = array(
      CURLOPT_SSLVERSION => 6,

  6. hi,

    Thank you for your tuto, it’s wonderfull.

    I want to view more articles in paypal paiyment but I can not. can you help me please ?

    $items = array(
    array(‘name’=> $item_name, ‘quantity’=> $item_qty, ‘price’=> $item_price, ‘sku’=> $item_code, ‘currency’=>PP_CURRENCY)
    );

    Thank you

     Reply
  7. Sir, you have saved my life! Great tutorial!

    I got 401 token error when i went live. I changed apiContext in functions.inc.php:

    function apiContext(){
    $apiContext = new PayPal\Rest\ApiContext(new PayPal\Auth\OAuthTokenCredential(CLIENT_ID, CLIENT_SECRET));
    $apiContext->setConfig( array(
    ‘mode’ => ‘live’,
    ‘http.ConnectionTimeOut’ => 30,
    ‘log.LogEnabled’ => true,
    ‘log.FileName’ => ‘PayPal.log’,
    ‘log.LogLevel’ => ‘FINE’,
    ‘validation.level’ => ‘log’
    )
    );
    return $apiContext;
    }

     Reply
  8. Hello,
    Can you please
    Got Http response code 401 when accessing https://api.paypal.com/v1/oauth2/token

     Reply
    • I changed apiContext in functions.inc.php:

      function apiContext(){
      $apiContext = new PayPal\Rest\ApiContext(new PayPal\Auth\OAuthTokenCredential(CLIENT_ID, CLIENT_SECRET));
      $apiContext->setConfig( array(
      ‘mode’ => ‘live’,
      ‘http.ConnectionTimeOut’ => 30,
      ‘log.LogEnabled’ => true,
      ‘log.FileName’ => ‘PayPal.log’,
      ‘log.LogLevel’ => ‘FINE’,
      ‘validation.level’ => ‘log’
      )
      );
      return $apiContext;
      }

  9. If you see this error, upgrade to v1.3 of the PayPal PHP SDK:
    ‘Method PayPal\Api\Sale::getTransactionFee() does not exist’

    Upgrade: https://github.com/paypal/PayPal-PHP-SDK/releases/tag/v1.3.0

    After I did this, everything worked great.

     Reply
  10. Hello what would happen if the user loses internet connection before being redirected back to the api page? whats the best way to deal with this?

    sean

     Reply
  11. In paypal classic api, we can put a hidden form element with name, custom, item_number,
    in which you can store value of who user bought this product, product id, with the whole form submitted to paypal, and with a payment confirm successfully, this value will accompany with the redirect url, return to original site. Such that using this piece of information to update the back-end database record, let say, product sales count, user profile for points earning for buying.

    How to do that in paypal REST api ?

     Reply
  12. Notice: Undefined variable: PayPalMode in C:\xampp\htdocs\Hassqeea\paypal-express-checkout\process.php on line 6

    Notice: Undefined variable: PayPalReturnURL in C:\xampp\htdocs\Hassqeea\paypal-express-checkout\process.php on line 66

    Notice: Undefined variable: PayPalCancelURL in C:\xampp\htdocs\Hassqeea\paypal-express-checkout\process.php on line 67

    Notice: Undefined variable: PayPalCurrencyCode in C:\xampp\htdocs\Hassqeea\paypal-express-checkout\process.php on line 78

    Notice: Undefined variable: PayPalApiUsername in C:\xampp\htdocs\Hassqeea\paypal-express-checkout\process.php on line 86

    Notice: Undefined variable: PayPalApiPassword in C:\xampp\htdocs\Hassqeea\paypal-express-checkout\process.php on line 86

    Notice: Undefined variable: PayPalApiSignature in C:\xampp\htdocs\Hassqeea\paypal-express-checkout\process.php on line 86

    Notice: Undefined variable: PayPalMode in C:\xampp\htdocs\Hassqeea\paypal-express-checkout\process.php on line 86
    SetExpressCheckout failed: Could not resolve host: yahoo.com.paypal.com(6)

    help me

     Reply
  13. Hello Saran,

    I am enjoying your paypal articles and i am learning a lot. But for this particular one paypal-rest-api-payment-system i am getting an error when i tried your demo. It says:

    “You must set one of service.endpoint or mode parameters in your configuration”

     Reply
  14. Hi,

    This seems to be working fine for me to the extent that clicking the button redirects to order_process.php which takes me to paypal page. But the issue is I can’t seem to use my regular paypal login. It seems to be authenticating but then it shows login error. (If I go to paypal site, my login/passwd is working just fine)

    I have created the rest app and have the client id and secret properly configured. Is any other setting required for a test login on sandbox?

    Are you supposed to use a different paypal account for testing in sandbox mode?

    Tried this multiple times but no help.

     Reply
    • Yes, you will need different credentials for sandbox and live mode. Also you need to change Service mode to live or sandbox in config.ini file.

    • hi,

      Can you help me?

      i want to add shippement, but i have an error.

      thank you

  15. Hi,

    I am getting an error saying “You must set one of service.endpoint or mode parameters in your configuration”

    Could you please guide me?

    Thanks,
    Shashank.

     Reply
    • Greate tutorial.
      On function.inc.php replace

      1
       function apiContext(){ ....

      to this

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      function apiContext(){
          $apiContext = new ApiContext(new           
          OAuthTokenCredential(CLIENT_ID, CLIENT_SECRET));
         
          $apiContext->setConfig( array(
              'mode' => 'sandbox',
              'http.ConnectionTimeOut' => 30,
              'log.LogEnabled' => true,
              'log.FileName' => 'PayPal.log',
              'log.LogLevel' => 'FINE',
              'validation.level' => 'log'
              )
            );
            return $apiContext;
      }
  16. Why are you echoing out all the html.

    ….

    Soo much cleaner.

     Reply
  17. Hi,

    Nice tutorial :-), I tried it. It seems to be working. I have a couple of questions though:

    1) what is the difference between create_paypal_payment and pay_direct_with_credit_card ?

    2) after payment, the state is always “pending”. Does this mean the seller did not get the money?

    3) in order to make sure the seller gets and accepts only instant payments to his account, what needs to be done in terms of code (any special function or parameters to use)?

    Thanks.

     Reply
  18. But what about security ?
    I can alter the price using firebug easily !

     Reply
Message Type : Question Comment ?
  • Question : Can include code, jsFiddle, codePen etc using Markdown Syntax.
  • Comment : Short comments and questions.