PayPal is the most convenient way to receive payments. PayPal has more than 350 million users. If you want to sale any product on your website, PayPal is the best way to get paid. Its easy and safe as Credit card/Bank account information is not required to be submitted on Seller’s website. We are going to integrate PayPal in website using new REST API by PayPal.
Recently I posted Simple PayPal Button integration which used Classic API by PayPal. But the new REST API is more secure with lots of new features.
Detailed information about PayPal REST API is available here. Let’s start with tutorial now. Please download complete files. We will be working with create.php, execute.php & example.php. Proper understanding of these files is necessary.
Configurations:
Bootstrap.php: Changing the client ID & Secret is optional in testing mode. But obtain your PayPal Client ID & Secret for REST API if you want to start selling in real world.
1 2 3 4 5 6 |
$apiContext = new ApiContext( new OAuthTokenCredential( 'EBWKjlELKMYqRNQ6sYvFo64FtaRLRR5BdHEESmha49TM', 'EO422dn3gQLgDbuwqTjzrFgFtaRLRR5BdHEESmha49TM' ) ); |
Product Page (example.php):
example.php is product listing page where buyers will see your products. I have included sample products. It doesn’t matter your page is displaying single product or list of products. You can get product details from database too.
Each product item has it’s form, which contains hidden input fields itemname, itemprice, shipping, tax, currencycode & paypaldesc.Product quantity select-box allows user to select quantity. When user decides to buy the product and clicks buy button, then product data is posted to create.php.
Note: It is advised that you store product price, shipping, tax, currency code in database. And fetch pricing information in create.php from database. Please check sample code of fetching product price from database in create.php code.
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 |
<div class="product"> <span class="title">Sony Alpha NEX-5TL : $ 325</span> <span class="detail">The NEX-5TL is a powerful, pocketable digital camera – great for capturing incredible pictures almost anywhere. </span> <form action="create.php" method="post"> <input type="hidden" value="1" name="productid"/> <input type="hidden" value="Sony Alpha NEX-5TL" name="itemname"/> <input type="hidden" value="325" name="itemprice"/> <input type="hidden" value="5" name="shipping"/> <input type="hidden" value="4.2" name="tax"/> <input type="hidden" value="USD" name="currencycode"/> <input type="hidden" value="Buy Sony Alpha NEX-5TL" name="paypaldesc"/> <span class="quantity"> <select name="quantity"> <option value="1">1</option> <option value="2">2</option> <option value="3">3</option> </select> </span> <input class="submit" type="submit" value="Buy Now ($325 Each)" name="subbutton"/> </form> </div> <div class="product"> <span class="title">Brand NEW Apple iPhone 3GS : $ 205</span> <span class="detail">This item is 100% brand new and from overseas. Stock is limited. </span> <form action="create.php" method="post"> <input type="hidden" value="2" name="productid" /> <input type="hidden" value="Brand NEW Apple iPhone 3GS" name="itemname" /> <input type="hidden" value="205" name="itemprice"/> <input type="hidden" value="0" name="shipping"/> <input type="hidden" value="4.2" name="tax"/> <input type="hidden" value="USD" name="currencycode"/> <input type="hidden" value="Buy Brand NEW Apple iPhone 3GS" name="paypaldesc"/> <span class="quantity"> <select name="quantity"> <option value="1">1</option> <option value="2">2</option> <option value="3">3</option> </select> </span> <input class="submit" type="submit" value="Buy Now ($205 Each)" name="subbutton"/> </form> </div> |
Create.php:
Data received from example.php is processed, total payable amount is calculated using product price, shipping and tax information. We can define URLs where buyer will be redirected after payment cancellation/success. After that payment is created using ‘create’ method passing it a valid apiContext. The return object contains the state and the PayPal URL to which the buyer must be redirected to (for payment). Check out below code now.
Note: For payment on PayPal Sandbox website, please create a Personal sandbox account through http://developer.paypal.com/ or https://www.sandbox.paypal.com.
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 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 |
<?php $productid = $_POST['productid']; $name = $_POST['itemname']; $quantity = intval($_POST['quantity']); $description = $_POST['paypaldesc']; /* ### Comment below 4 lines and uncomment below mysqli code if you want to fetch product information from database */ $price = intval($_POST['itemprice']); $shipping = intval($_POST['shipping']); $tax = intval($_POST['tax']); $currency = $_POST['currencycode']; /* #### GET PRODUCT INFORMATION ### //Create new table and stre infromation in it for mysqli code to work //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); } $product_info = $mysqli->query("SELECT * FROM ProductInfo WHERE product_id = '".$mysqli->mysqli_real_escape_string($productid)."'"); if(mysqli_num_rows($product_info) > 0){ $row = mysqli_fetch_assoc($product_info); // Assign values fetched from database $price = intval($row['itemprice']); $shipping = intval($row['shipping']); $tax = intval($row['tax']); $currency = $row['currencycode']; }else{ die('Error : ('. $mysqli->errno .') '. $mysqli->error); } */ // calculate sub total $subtotal = $quantity * $price; // Calculate total ammount paypable $totalprice = $subtotal + $shipping + $tax; // # Create Payment using PayPal as payment method // This sample code demonstrates how you can process a // PayPal Account based Payment. // API used: /v1/payments/payment require __DIR__ . '/bootstrap.php'; use PayPal\Api\Amount; use PayPal\Api\Details; use PayPal\Api\Item; use PayPal\Api\ItemList; use PayPal\Api\Payer; use PayPal\Api\Payment; use PayPal\Api\RedirectUrls; use PayPal\Api\Transaction; session_start(); // ### Payer // A resource representing a Payer that funds a payment // For paypal account payments, set payment method // to 'paypal'. $payer = new Payer(); $payer->setPaymentMethod("paypal"); // ### Itemized information // (Optional) Lets you specify item wise // information $item1 = new Item(); $item1->setName($name) ->setCurrency($currency) ->setQuantity($quantity) ->setPrice($price); //$item2 = new Item(); //$item2->setName('Granola bars') // ->setCurrency('USD') // ->setQuantity(5) // ->setPrice('2.00'); $itemList = new ItemList(); //$itemList->setItems(array($item1, $item2)); $itemList->setItems(array($item1)); // ### Additional payment details // Use this optional field to set additional // payment information such as tax, shipping // charges etc. $details = new Details(); $details->setShipping($shipping) ->setTax($tax) ->setSubtotal($subtotal); // ### Amount // Lets you specify a payment amount. // You can also specify additional details // such as shipping, tax. $amount = new Amount(); $amount->setCurrency($currency) ->setTotal($totalprice) ->setDetails($details); // ### Transaction // A transaction defines the contract of a // payment - what is the payment for and who // is fulfilling it. $transaction = new Transaction(); $transaction->setAmount($amount) ->setItemList($itemList) ->setDescription($description); // ### Redirect urls // Set the urls that the buyer must be redirected to after // payment approval/ cancellation. $baseUrl = getBaseUrl(); $redirectUrls = new RedirectUrls(); $redirectUrls->setReturnUrl("$baseUrl/execute.php?success=true") ->setCancelUrl("$baseUrl/execute.php?success=false"); // ### Payment // A Payment Resource; create one using // the above types and intent set to 'sale' $payment = new Payment(); $payment->setIntent("sale") ->setPayer($payer) ->setRedirectUrls($redirectUrls) ->setTransactions(array($transaction)); // ### Create Payment // Create a payment by calling the 'create' method // passing it a valid apiContext. // (See bootstrap.php for more on `ApiContext`) // The return object contains the state and the // url to which the buyer must be redirected to // for payment approval try { $payment->create($apiContext); } catch (PayPal\Exception\PPConnectionException $ex) { echo "Exception: " . $ex->getMessage() . PHP_EOL; echo "<pre>"; var_dump($ex->getData()); exit(1); } // ### Get redirect url // The API response provides the url that you must redirect // the buyer to. Retrieve the url from the $payment->getLinks() // method foreach($payment->getLinks() as $link) { if($link->getRel() == 'approval_url') { $redirectUrl = $link->getHref(); break; } } $payment_id = $payment->getId(); // ### Redirect buyer to PayPal website // Save the payment id so that you can 'complete' the payment // once the buyer approves the payment and is redirected // back to your website. // // It is not a great idea to store the payment id // in the session. In a real world app, you may want to // store the payment id in a database. // to store product id and payment id in database // for verification in execute.php verification $_SESSION['paymentId'] = $payment_id; /* #### Store Payment ID in database ### //Create new table and store payment id againt product id in //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); } $payment_info = $mysqli->query("INSERT INTO payment_records (product_id,payment_id) VALUES ('$productid','$payment_id'"); if(!$payment_info){ die('Error : ('. $mysqli->errno .') '. $mysqli->error); } */ if(isset($redirectUrl)) { header("Location: $redirectUrl"); exit; } |
Execute.php:
User is redirected back to our website after authentication from PayPal. Now you can complete the payment that has been approved by buyer, by logging into PayPal website. If you are using database to store Payment ID from create.php, you can authenticate Payment ID stored in $_SESSIONS with Payment ID stored in database. After authentication payment is executed.
Now you can do the following:
- Show payment confirmation page.
- Allow buyer to download software/product.
- Store Transaction information from $result array into your database.
- Much more can be done as needed.
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 |
<?php // #Execute Payment // This shows how you can complete // a payment that has been approved by // the buyer by logging into paypal site. // You can optionally update transaction // information by passing in one or more transactions. // API used: POST '/v1/payments/payment/<payment-id>/execute'. require __DIR__ . '/bootstrap.php'; use PayPal\Api\ExecutePayment; use PayPal\Api\Payment; use PayPal\Api\PaymentExecution; session_start(); if(isset($_GET['success']) && $_GET['success'] == 'true') { // payment id was previously stored in session in // create.php $paymentId_session = $_SESSION['paymentId']; // if you used database to store product id and payment id // use below mysqli code to fetch payment_id from database /* #### GET PAYMENT ID ### //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); } $payment_info = $mysqli->query("SELECT * FROM payment_records WHERE payment_id = '".$mysqli->mysqli_real_escape_string($paymentId_session)."'"); if(mysqli_num_rows($payment_info) > 0){ $row = mysqli_fetch_assoc($payment_info); // Assign values fetched from database $productid = $row['product_id']; $paymentId = $row['payment_id']; }else{ die('Error : ('. $mysqli->errno .') '. $mysqli->error); } if( $paymentId != $paymentId_session){ die("Payment id not verified"); // only use below lines for testing, comment them in live website // echo "Payment id from session:" . $paymentId_session; // echo "Payment id from database:" . $paymentId ; } */ // Get the payment Object by passing paymentId $payment = Payment::get($paymentId, $apiContext); // PaymentExecution object includes information necessary // to execute a PayPal account payment. // The payer_id is added to the request query parameters // when the user is redirected from paypal back to your site $execution = new PaymentExecution(); $execution->setPayerId($_GET['PayerID']); //Execute the payment // (See bootstrap.php for more on `ApiContext`) $result = $payment->execute($execution, $apiContext); echo "<html><body><pre>"; print_r($result); } else { echo "User cancelled payment."; } |
Known issues:
1: PayPal SDK works fine on Localhost, but testing on live Web Server may occur some “Fatal Errors”. Please check if there is any PHP caching activated on Web Server. PHP caching like APC, Eaccelerator, OPCache can create problems.In case of any issue try disabling PHP cache plugins and restarting Web Server.
2: After extensive testing of payment system on PayPal Sandbox Website. If you are not able to pay(PayPal does not authenticate your login credentials) and shows Dispatch Error, Please check log file for more information. Please try clearing all sessions and delete all cookies for http://sandbox.paypal.com or try using a different browser.
Changes for Live Selling:
In sdk_config.ini change mode=sandbox to mode=live before integrating it in live website. Also don’t forget to change Client ID and Secret key in bootstrap.php which I mentioned earlier.
1 2 |
[Service] mode=sandbox ; can be set to sandbox / live |
Hope you like it. Nothing is perfect. Suggestions and improvements are welcomed in comments.
You’re a life saver!
I’ve never found a documentation so messed up as the Paypal API Docs!
They should just put a link to your tutorial there! 😀
Thanks!
I agree, I thought it was just me. Could never figure out the how to even get through the paypal api docs. I use Stripe api, fun and easy to use.
Indeed, I usually don’t reply but this documentation is way better.
Thanks!
Excellent job.but i can’t download source files. can you please send me via mail ?
Thanks
When I was buying in example.php, I had this error:
Exception: Received HTTP code 407 from proxy after CONNECT
null
I had configured http.Proxy variable in sdk_config.ini
The best documentation about paypal API Rest I ever seen. Thank you so much.
This tutorial explains the basic things needed to know in implementing the paypal API Rest. Thanks for sharing.
Hi,
I am running this application in Xampp Apache in localhost. After submitting the product form just like the example.php shown above, I am getting this following Fatal error.
Fatal error: Class ‘ApiContext’ not found in D:\Program_Files\xampp\htdocs\paypalTest\bootstrap.php on line 9
P.S. – I am require-ing the autoload.php file in the beginning of my application’s index page.
Woooow!!! Nice!!! This tutorial really best!!! Thanks!!!!
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 ?
Hi Adrian. I will try to write a tutorial about it in few days
Your demo is not working now. Please fix
Thanks for pointing out the issue Zachary. I fixed it
what would happen if the user loses their internet connection AFTER paypal takes the payment but BEFORE they are successfully redirected back to the website?
Payment will be processed and record inserted in your database also. So you can send user an email also, which includes payment details and order delivery links
We try to run your live demo, It reply back this
Fatal error: Uncaught exception ‘ReflectionException’ with message ‘Method PayPal\Api\Sale::getTransactionFee() does not exist’ in /home/umar/domains/earlysandwich.com/public_html/demos/demo_files/integrate-paypal-rest-api-php-mysql/vendor/paypal/sdk-core-php/lib/PayPal/Common/PPReflectionUtil.php:60 Stack trace: #0 /home/umar/domains/earlysandwich.com/public_html/demos/demo_files/integrate-paypal-rest-api-php-mysql/vendor/paypal/sdk-core-php/lib/PayPal/Common/PPReflectionUtil.php(60): ReflectionMethod->__construct(‘PayPal\Api\Sale’, ‘getTransactionF…’) #1 /home/umar/domains/earlysandwich.com/public_html/demos/demo_files/integrate-paypal-rest-api-php-mysql/vendor/paypal/sdk-core-php/lib/PayPal/Common/PPReflectionUtil.php(24): PayPal\Common\PPReflectionUtil::propertyAnnotations(‘PayPal\Api\Sale’, ‘transaction_fee’) #2 /home/umar/domains/earlysandwich.com/public_html/demos/demo_files/integrate-paypal-rest-api-php-mysql/vendor/paypal/sdk-core-php/lib/PayPal/Common/PPModel.php(48): PayPal\Common\PPReflectionUtil::getPropert in /home/umar/domains/earlysandwich.com/public_html/demos/demo_files/integrate-paypal-rest-api-php-mysql/vendor/paypal/sdk-core-php/lib/PayPal/Common/PPReflectionUtil.php on line 60
Please suggest the way to overcome this issue.
Thanks,
Prashant.
Please send src files.
Sir when I tried it on localhost….it gives the following error…
error:14094410:SSL routines:SSL3_READ_BYTES:sslv3 alert handshake failure
I’m using XAMPP
Suggest me the solution…Thanks
Sir i tried this code on localhost but no working…..giving the following error
Exception: error:14094410:SSL routines:SSL3_READ_BYTES:sslv3 alert handshake failure
please suggest me the solution….Thanks
Thanks for this fantastic demo! I am running into an odd problem I wonder if you’ve seen. In the sandbox, if I pick the “Bank account (eCheck)” payment method, the transaction completes successfully and I see the dump of the $result variable. But if I choose a different payment method, the payment is not executed. Specifically, if I pay via my sandbox’s Paypal Balance, the execute.php rpogram bombs when
$result = $payment->execute($execution, $apiContext);
is called. If I choose PayPal Credit, it bombs when$payment = Payment::get($paymentId, $apiContext);
runs.Looks like demo page is broken again, shows “Exception: SSL connect error NULL”