PayPal is an American international e-commerce business allowing payments and money transfers to be made through the Internet. PayPal is the most popular payment gateway to send and receive payment worldwide. PayPal is a widely used payment gateway to accept payment in the web application. PayPal payment gateway is the easiest option for the web developer to implement a payment system on the website.
PayPal Standard Payment Gateway is the quickest way to accept payment online. The buyer can make the payment from the website to purchase an item online. In this tutorial, we will show you how to integrate PayPal standard payment gateway in PHP and store the transaction data in the database using PayPal IPN. Our step-by-step guide on PayPal payment gateway integration in PHP helps you to easily integrate the online payment feature in your web project.
Since the PayPal Standard payment is on the Legacy version, we recommended integrating PayPal Standard Checkout for the new payment gateway integration.
In the example script, we will implement the following functionality to demonstrate the PayPal Payment Gateway integration process.
Before getting started to integrate PayPal payment gateway API in PHP, take a look at the files structure.
paypal_integration_php/ ├── config.php ├── dbConnect.php ├── index.php ├── success.php ├── cancel.php ├── ipn.php ├── css/ │ └── style.css └── images/
PayPal has two environments such as Sandbox and Real Time. PayPal Sandbox allows developers to do their test transaction before the project go live. The real-time environment is used after the project is live on the production server. Once the PayPal payment process is working properly on the Sandbox environment, you can set the PayPal payment gateway for Real-Time environment.
Before start accepting payment from buyers via PayPal, the payment gateway needs to be tested. To test the transaction process you need to create a PayPal sandbox account.
You may follow the detailed guide on creating a PayPal Sandbox account from this tutorial – Creating PayPal Sandbox Test Account and Website Payments Pro Account
To store product and payment information two tables needs to be created in the database.
The following SQL creates a products
table in the MySQL database to store the product data.
CREATE TABLE `products` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(200) COLLATE utf8_unicode_ci NOT NULL,
`image` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
`price` float(10,2) NOT NULL,
`status` tinyint(1) NOT NULL DEFAULT '1' COMMENT '1=Active | 0=Inactive',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
The following SQL creates a payments
table in the MySQL database to store the transaction data provided by PayPal.
CREATE TABLE `payments` (
`payment_id` int(11) NOT NULL AUTO_INCREMENT,
`item_number` varchar(50) COLLATE utf8_unicode_ci NOT NULL,
`txn_id` varchar(50) COLLATE utf8_unicode_ci NOT NULL,
`payment_gross` float(10,2) NOT NULL,
`currency_code` varchar(5) COLLATE utf8_unicode_ci NOT NULL,
`payment_status` varchar(20) COLLATE utf8_unicode_ci NOT NULL,
PRIMARY KEY (`payment_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
In the config.php
file, constant variables of the PayPal and database settings are defined.
PayPal Constants:
Database Constants:
<?php
/*
* PayPal and database configuration
*/
// PayPal configuration
define('PAYPAL_ID', 'Insert_PayPal_Business_Email');
define('PAYPAL_SANDBOX', TRUE); //TRUE or FALSE
define('PAYPAL_RETURN_URL', 'http://www.example.com/success.php');
define('PAYPAL_CANCEL_URL', 'http://www.example.com/cancel.php');
define('PAYPAL_NOTIFY_URL', 'http://www.example.com/ipn.php');
define('PAYPAL_CURRENCY', 'USD');
// Database configuration
define('DB_HOST', 'MySQL_Database_Host');
define('DB_USERNAME', 'MySQL_Database_Username');
define('DB_PASSWORD', 'MySQL_Database_Password');
define('DB_NAME', 'MySQL_Database_Name');
// Change not required
define('PAYPAL_URL', (PAYPAL_SANDBOX == true)?"https://www.sandbox.paypal.com/cgi-bin/webscr":"https://www.paypal.com/cgi-bin/webscr");
The dbConnect.php
file is used to connect the database using PHP and MySQL.
<?php
// Connect with the database
$db = new mysqli(DB_HOST, DB_USERNAME, DB_PASSWORD, DB_NAME);
// Display error if failed to connect
if ($db->connect_errno) {
printf("Connect failed: %s\n", $db->connect_error);
exit();
}
Initially, all the products are fetched from the database and listed on the webpage.
<?php
// Include configuration file
include_once 'config.php';
// Include database connection file
include_once 'dbConnect.php';
?>
<div class="container">
<?php
// Fetch products from the database
$results = $db->query("SELECT * FROM products WHERE status = 1");
while($row = $results->fetch_assoc()){
?>
<div class="pro-box">
<img src="images/<?php echo $row['image']; ?>"/>
<div class="body">
<h5><?php echo $row['name']; ?></h5>
<h6>Price: <?php echo '$'.$row['price'].' '.PAYPAL_CURRENCY; ?></h6>
<!-- PayPal payment form for displaying the buy button -->
<form action="<?php echo PAYPAL_URL; ?>" method="post">
<!-- Identify your business so that you can collect the payments. -->
<input type="hidden" name="business" value="<?php echo PAYPAL_ID; ?>">
<!-- Specify a Buy Now button. -->
<input type="hidden" name="cmd" value="_xclick">
<!-- Specify details about the item that buyers will purchase. -->
<input type="hidden" name="item_name" value="<?php echo $row['name']; ?>">
<input type="hidden" name="item_number" value="<?php echo $row['id']; ?>">
<input type="hidden" name="amount" value="<?php echo $row['price']; ?>">
<input type="hidden" name="currency_code" value="<?php echo PAYPAL_CURRENCY; ?>">
<!-- Specify URLs -->
<input type="hidden" name="return" value="<?php echo PAYPAL_RETURN_URL; ?>">
<input type="hidden" name="cancel_return" value="<?php echo PAYPAL_CANCEL_URL; ?>">
<!-- Display the payment button. -->
<input type="image" name="submit" border="0" src="https://www.paypalobjects.com/en_US/i/btn/btn_buynow_LG.gif">
</form>
</div>
</div>
<?php } ?>
</div>
After successful payment on PayPal, the buyer is redirected to this page.
<?php
// Include configuration file
include_once 'config.php';
// Include database connection file
include_once 'dbConnect.php';
// If transaction data is available in the URL
if(!empty($_GET['item_number']) && !empty($_GET['tx']) && !empty($_GET['amt']) && !empty($_GET['cc']) && !empty($_GET['st'])){
// Get transaction information from URL
$item_number = $_GET['item_number'];
$txn_id = $_GET['tx'];
$payment_gross = $_GET['amt'];
$currency_code = $_GET['cc'];
$payment_status = $_GET['st'];
// Get product info from the database
$productResult = $db->query("SELECT * FROM products WHERE id = ".$item_number);
$productRow = $productResult->fetch_assoc();
// Check if transaction data exists with the same TXN ID.
$prevPaymentResult = $db->query("SELECT * FROM payments WHERE txn_id = '".$txn_id."'");
if($prevPaymentResult->num_rows > 0){
$paymentRow = $prevPaymentResult->fetch_assoc();
$payment_id = $paymentRow['payment_id'];
$payment_gross = $paymentRow['payment_gross'];
$payment_status = $paymentRow['payment_status'];
}else{
// Insert tansaction data into the database
$insert = $db->query("INSERT INTO payments(item_number,txn_id,payment_gross,currency_code,payment_status) VALUES('".$item_number."','".$txn_id."','".$payment_gross."','".$currency_code."','".$payment_status."')");
$payment_id = $db->insert_id;
}
}
?>
<div class="container">
<div class="status">
<?php if(!empty($payment_id)){ ?>
<h1 class="success">Your Payment has been Successful</h1>
<h4>Payment Information</h4>
<p><b>Reference Number:</b> <?php echo $payment_id; ?></p>
<p><b>Transaction ID:</b> <?php echo $txn_id; ?></p>
<p><b>Paid Amount:</b> <?php echo $payment_gross; ?></p>
<p><b>Payment Status:</b> <?php echo $payment_status; ?></p>
<h4>Product Information</h4>
<p><b>Name:</b> <?php echo $productRow['name']; ?></p>
<p><b>Price:</b> <?php echo $productRow['price']; ?></p>
<?php }else{ ?>
<h1 class="error">Your Payment has Failed</h1>
<?php } ?>
</div>
<a href="index.php" class="btn-link">Back to Products</a>
</div>
If the buyer wishes to cancel payment at the PayPal payment page, the buyer is redirected to this page.
<div class="container">
<div class="status">
<h1 class="error">Your PayPal Transaction has been Canceled</h1>
</div>
<a href="index.php" class="btn-link">Back to Products</a>
</div>
Make sure you have configured Auto Return for Website Payments on your PayPal business account. Otherwise, you’ll not get the transaction information from PayPal in the success.php
file. See the following guide to enable Auto Return, Payment Data Transfer and set Return URL on your PayPal account.
To make the PayPal Standard Payment secure, validate the transaction with PayPal Instant Payment Notification (IPN). Follow the below steps to setup IPN in PayPal standard payment gateway integration.
Enable IPN:
To use this feature, IPN must be enabled in the PayPal account. We’ve already published a step-by-step guide to enable IPN in PayPal, please see the below tutorial.
Add Notify URL in PayPal Form:
Add the following input field (notify_url
) HTML along with the other PayPal HTML Variables.
<input type="hidden" name="notify_url" value="<?php echo PAYPAL_NOTIFY_URL; ?>">
Validate Transaction:
Once IPN is enabled, PayPal will send the transaction data to the Notify URL (http://www.example.com/ipn.php
). Place the following code in the ipn.php
file to validate the transaction and insert payment information into the database.
<?php
// Include configuration file
include_once 'config.php';
// Include database connection file
include_once 'dbConnect.php';
/*
* Read POST data
* reading posted data directly from $_POST causes serialization
* issues with array data in POST.
* Reading raw POST data from input stream instead.
*/
$raw_post_data = file_get_contents('php://input');
$raw_post_array = explode('&', $raw_post_data);
$myPost = array();
foreach ($raw_post_array as $keyval) {
$keyval = explode ('=', $keyval);
if (count($keyval) == 2)
$myPost[$keyval[0]] = urldecode($keyval[1]);
}
// Read the post from PayPal system and add 'cmd'
$req = 'cmd=_notify-validate';
if(function_exists('get_magic_quotes_gpc')) {
$get_magic_quotes_exists = true;
}
foreach ($myPost as $key => $value) {
if($get_magic_quotes_exists == true && get_magic_quotes_gpc() == 1) {
$value = urlencode(stripslashes($value));
} else {
$value = urlencode($value);
}
$req .= "&$key=$value";
}
/*
* Post IPN data back to PayPal to validate the IPN data is genuine
* Without this step anyone can fake IPN data
*/
$paypalURL = PAYPAL_URL;
$ch = curl_init($paypalURL);
if ($ch == FALSE) {
return FALSE;
}
curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $req);
curl_setopt($ch, CURLOPT_SSLVERSION, 6);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 1);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
curl_setopt($ch, CURLOPT_FORBID_REUSE, 1);
// Set TCP timeout to 30 seconds
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 30);
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Connection: Close', 'User-Agent: company-name'));
$res = curl_exec($ch);
/*
* Inspect IPN validation result and act accordingly
* Split response headers and payload, a better way for strcmp
*/
$tokens = explode("\r\n\r\n", trim($res));
$res = trim(end($tokens));
if (strcmp($res, "VERIFIED") == 0 || strcasecmp($res, "VERIFIED") == 0) {
// Retrieve transaction info from PayPal
$item_number = $_POST['item_number'];
$txn_id = $_POST['txn_id'];
$payment_gross = $_POST['mc_gross'];
$currency_code = $_POST['mc_currency'];
$payment_status = $_POST['payment_status'];
// Check if transaction data exists with the same TXN ID
$prevPayment = $db->query("SELECT payment_id FROM payments WHERE txn_id = '".$txn_id."'");
if($prevPayment->num_rows > 0){
exit();
}else{
// Insert transaction data into the database
$insert = $db->query("INSERT INTO payments(item_number,txn_id,payment_gross,currency_code,payment_status) VALUES('".$item_number."','".$txn_id."','".$payment_gross."','".$currency_code."','".$payment_status."')");
}
}
?>
Note that: Once the PayPal IPN setup is completed, the database insertion code is not required in the success.php
file.
When the application payment flow testing is completed, you should make the PayPal payment gateway live.
In the config.php file,
PAYPAL_ID
.PAYPAL_SANDBOX
to FALSE.define('PAYPAL_ID', 'Insert_PayPal_Business_Email');
define('PAYPAL_SANDBOX', FALSE);
PayPal Pro Payment Gateway Integration in PHP
PayPal standard payment gateway is the easiest way to accept payment on the web application. With our example script, you can easily integrate the PayPal payment API on the website. To make the payment process user-friendly, you can integrate PayPal Express Checkout for the online payment.
Do you want to get implementation help, or enhance the functionality of this script? Click here to Submit Service Request
How can I add 7.25% tax rate to the transaction? My guessing it is did in the config file but not sure the correct entry? and maybe on another location as well
$itemName = “30 Day Advertisement”;
$itemPrice = 10;
$currency = “USD”;
Hello, Thank you for the paypal support,
We tried your code, We are getting only “PayerID” after successfull payment.
You are Superman. Thank you!
very very super
Hi, very interesting article, but if an user close the page after payment and not wait the 10 seconds to return on store, all is lost.
How to proceed in that case ?
Thanks !!! Excelent tutorial!
How to insert payer_email in the database table?
Hi CODEXWORLD ! thanks for this helpful code.
Can you please tell me how can i do “refund amount” partially refund or full refund based on your code.
Thanks!
Thank you for this tutorial, it was really helpful for integrating paypal payment into my website.
Awesome !!! I have found some codes for this matter online but they were either vague or they were not for free. Thanks for the great free Tutorials
Hi there , can you please advice me what to do to fix this issue . after i pay with sandbox and get redirected to success.php it shows these errors.
Notice: Undefined index: tx in /Applications/XAMPP/xamppfiles/htdocs/shop/success.php on line 14
Notice: Undefined index: amt in /Applications/XAMPP/xamppfiles/htdocs/shop/success.php on line 15
Notice: Undefined index: cc in /Applications/XAMPP/xamppfiles/htdocs/shop/success.php on line 16
Notice: Undefined index: st in /Applications/XAMPP/xamppfiles/htdocs/shop/success.php on line 17
Your order payment has been successful!
You need to enable Auto Return and Payment Data Transfer on PayPal Business account, follow this step-by-step guide – https://www.codexworld.com/how-to/configure-paypal-sandbox-auto-return-payment-data-transfer/
Thank you very much. This article helps me a lot to set up my own Paypal payment gateway
How to get item quantity in success page url ?
in the ipn.php
$item_quantity = $_POST[‘quantity’];
At first, define a hidden input field with quantity variable in the HTML form.
<input type="hidden" name="quantity" value="2">
Use the following code to get the quantity of the item.
$quantity = $_POST['quantity'];
Is this recommend for wordpress plugin development cause I already do this to my plugin the problem is it has external php which wordpress won’t allow me to load directly the core of wordpress like wp-load.php without this file I cannot save the info after paypal redirect back to my site
Hello, Can any one tell me how to refund customer without using any api calls..?
Thanks for a great Tutorial.
i am building a system in which customer can checkout for multiple items. I want that when a customer pay via paypal, information aof these multiple items and their prices should be submitted also in paypal.
how can i do that please.
Thank
To accept payments for multiple items with PayPal, see this tutorial – https://www.codexworld.com/paypal-standard-add-to-cart-multiple-items-php/
Hello, thanks for the info. Can the code be amended to add a quantity parameter in case someone wants to buy same product say twice? Or in that case it is better to use the PayPal Express Checkout ? Thanks
You can use PayPal standard payment gateway for multiple items, see this tutorial – https://www.codexworld.com/paypal-standard-add-to-cart-multiple-items-php/
How to integrate paypal recurring payment in Core PHP?
Please help ASAP
Hi
i integrated this paypal standard payment gateway in my website. now i need,
– send invoice to customer from paypal end
– if by any case transaction get failure from paypal end then i wan to do retry automatically to paypal for payment processing. is it possible ? if yes then how ?
– can i distinguish cancel url and fail url ?
Please help asap
Hi, I am new comer for paypal using php. I used the above code. It works fine. But I can’t get the payer ID. How can I get it? Please let me know the reply soon.
Hello CodexWorld, as of now im getting the undefined index in php which came from the paypal, when i look at the URL , the paypal is not passing any index like the txn_number etc, what is the problem ? Thank you in advance. ^_^
You need to configure PayPal Auto Return and Payment Data Transfer, follow this step-by-step guide – https://www.codexworld.com/how-to/configure-paypal-sandbox-auto-return-payment-data-transfer/
Further to my other comment, because the return URL contains the GET parameters, what is to stop the user manipulating these and changing them and resubmitting the page?
That’s why PayPal IPN need to be used to verify the transaction and store the payment information in the database. Please follow the instructions given in the tutorial.
Hello thanks for the helpful article. PayPal seem to change things around a lot!
I have a form and paypal button similar to that in your article above and my button, the return IPN and success page were all working fine and dandy – but then the success.php page stopped working. The IPN is received, but there is no longer any POST variables available on my success.php page. As I said, this appeared to be working fine until recently – but I have searched and cannot find any mention of any change to this from PayPal.
Anyway, I followed your advice to enable PDT and now I success.php is correctly receiving the GET variables ! YAY
However, my URL is full of the variables – which looks rather unsightly. e.g. success.php?amt=300.00&cc=USD&item_name=TEST&item_number=19827&st=Completed&tx=52222222278631R
Is there a way to still receive the variables, either GET or POST in success.php – but without all the variables in the url?
I tried – to hide them, but that didn’t work.
PayPal sends the transaction details in the query string to return_url. If you want to remove query string from the URL, you need to redirect to the same page (success.php) after receiving the payment info.
Thanks dude, after 2 days of hard try i have made it by your help.
On success page i am not getting any GET value, i fallow your instruction for pdt make it on and pass url but on success page i am not getting anything… Please help…Thanks..
You need to configure PayPal Auto Return and Payment Data Transfer, follow this guide – https://www.codexworld.com/how-to/configure-paypal-sandbox-auto-return-payment-data-transfer/
I have integrated paypal on my website but i want to modify a page I mean after posting form on that page Purchase details shows but i want to modified that details is it possible? And one more thing is it paypal plus integration?
Hello there ,
Thanks for this tutorial I want to know something about this if you can help me
an error occur when copy and paste url in url bar after payment success and hit enter after change transaction id manually fake record inserted in data base what i do for it
To overcome this issue, you need to setup PayPal IPN. See PayPal Instant Payment Notification setup steps in the tutorial.
Ok, thank you.
I was reading your “tutorial to accept payment for MULTIPLE items with PayPal – http://www.codexworld.com/paypal-standard-add-to-cart-multiple-items-php/“.
I get the idea, you have N forms, each one for each item, so you can add one by one to the chart, SEQUENTIALLY, ONE AFTER THE ANOTHER.
But my question (an need) is the following: How can I achieve a paypal chart of N items in just ONE CLICK?. I mean, in only one click I need the final chart with N items already added (without the need of adding each of them one after the another manually).
Thanks in advance.
With this way of managing an order, we are sending only one “item_name”, so the Paypal receipt will say:
Description: Bla, bla…
Price: X
Quantity: 1
Total: X
If the the total cost is 45euros but the order is composed by, let’s say, 2 books(one of them 2 times), how can we specify 2 item_names and one of them 2 times?.
See this tutorial to accept payment for multiple items with PayPal – http://www.codexworld.com/paypal-standard-add-to-cart-multiple-items-php/
I tried your code, making changes where needed (in particular, the merchant email) on the sandbox.
The success.php page is loaded after ‘Return to Merchant” button (after ‘paying’), but there are no GET values returned for success.php to act upon.
You need to enable Payment Data Transfer in your PayPal account. See this tutorial to configure it – http://www.codexworld.com/how-to/configure-paypal-sandbox-auto-return-payment-data-transfer/
Hi. Thank you very much for this useful tutorial!.
However my doubt is as follows:
As far as I know you can have many bank accounts within a paypal business account. So, in your form, when it’s submitted, how can we specify the destination bank account?.
Thannks in advance.
my project name is paypal3 and when i click on return to merchant.it is redirecting to http://localhost/paypal_integration_php/success.php, insteed of http://localhost/paypal3/success.php…. How am i resolve it
You need to specify your success URL in return form field. Open the
products.php
file and change thecancel_return
andreturn
input field value with your desired URL in PayPal form HTML.Hi,
I am new one for paypal. May i know the test card details for my testing purpose…..
Sir
can u help me in integrating the payout in php