These days using PayPal as your payment method is a big extra for your website, many people prefer to pay for your service or product using PayPal, this is why today we decided to explain in details how to setup PayPal integration in your website using PHP + MySQL.
In this step by step guide we will create a sample webpage with some products to checkout, once user selected a product to buy, it will be redirected in the PayPal website to complete payment and using PayPal IPN (Instant Payment Notification) our code will securely validate the payment and store information to database.
PayPal Sandbox Account
PayPal allows us to make test transactions before going live, this can be done via PayPal Sandbox accounts, so first we have to create a PayPal Sandbox account to test our PayPal integration.
Before we start accepting live payments, we need to make sure our system works, PayPal allows us to make test transactions using Sandbox accounts, so first we have to create a PayPal Sandbox account in order to test our system.
- A Sandbox account can be created from PayPal Developer Portal (https://developer.paypal.com).
- Login with your PayPal account and go to Dashboard.
- Click Accounts under Sandbox from the left menu panel.
- Click Create Account, select account type (Personal), fill other required fields and click submit button.

Products & Payments Database
In order to process payments securely we will need to store our products & payments in two database tables.
CREATE TABLE `paypal_products` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
`price` float(10,2) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
CREATE TABLE `paypal_payments` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`item_no` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
`transaction_id` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
`payment_amount` float(10,2) NOT NULL,
`currency_code` varchar(5) COLLATE utf8_unicode_ci NOT NULL,
`payment_status` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
Configuration File (core_config.php)
Now we should create a configuration file that helps us to connect securely with MySQL database and configure our payment system.
//Database credentials
define("HOST", "localhost"); // The host you want to connect to.
define("USER", "root"); // The database username.
define("PASSWORD", "changewithyourpassword"); // The database password.
define("DATABASE", "changewithyourdbname"); // The database name.
//Connect with database
$mysqli = new mysqli(HOST, USER, PASSWORD, DATABASE);
$system_mode = 'test'; // set 'test' for sandbox and leave blank for real payments.
$paypal_seller = 'changewith@youremail.com'; //Your PayPal account email address
$payment_return_success = 'https://demo.dopehacker.com/paypal_integration/payment_success.php'; //after payment, user will be redirected in this page, change with your own url
$payment_return_cancel = 'https://demo.dopehacker.com/paypal_integration/payment_cancel.php'; //if payment cancelled, user will be redirected in this page, change with your own url
if ($system_mode == 'test') {$paypal_url = 'https://www.sandbox.paypal.com/cgi-bin/webscr'; }
else {$paypal_url = 'https://www.paypal.com/cgi-bin/webscr';}
Don’t forget to change: HOST, USER, PASSWORD,DATABASE with your own database credentials & $payment_return_success, $payment_return_cancel variables to your own urls.
Products Page (products.php)
We assume you have populated your “paypal_payments” table with some products, let’s fetch these products in this page in order to checkout.
<?php
//include configuration file
include_once 'core_config.php';
?>
<html>
<head>
<title>PayPal Integration - Products</title>
</head>
<body>
<h1>Products</h1>
<?
//Fetch products from db in most secured way.
$prep_stmt = "SELECT * FROM paypal_products";
$stmt = $mysqli->prepare($prep_stmt);
if ($stmt) {
$stmt->execute();
$stmt->store_result();
$stmt->bind_result($id, $name, $price);
if ($stmt->num_rows >= 1) {
while ($stmt->fetch()) {
echo 'Product Name: '.$name;
echo '<br>';
echo 'Price: '.'$'.$price.'';
?>
<form action="<?php echo $paypal_url; ?>" method="post">
<!-- Get paypal email address from core_config.php -->
<input type="hidden" name="business" value="<?php echo $paypal_seller; ?>">
<!-- Specify product details -->
<input type="hidden" name="item_name" value="<?php echo $name; ?>">
<input type="hidden" name="item_number" value="<?php echo $id; ?>">
<input type="hidden" name="amount" value="<?php echo $price; ?>">
<input type="hidden" name="currency_code" value="USD">
<!-- IPN Url -->
<input type='hidden' name='notify_url' value='https://demo.dopehacker.com/paypal_integration/paypal_ipn.php'>
<!-- Return URLs -->
<input type='hidden' name='cancel_return' value='<? echo $payment_return_cancel; ?>'>
<input type='hidden' name='return' value='<? echo $payment_return_success; ?>'>
<!-- Submit Button -->
<input type="hidden" name="cmd" value="_xclick">
<input type="submit" value="Buy Now!" name="submit">
</form>
<?
}
} else {echo 'No Products in DB';}
$stmt->close();
}
?>
</body>
</html>
Payment Verification – PayPal IPN (paypal_ipn.php)
Once payment is completed we should validate payment and store payment information to database, to do this, we have to enable PayPal IPN – Instant payment notifications and set Notification URL.
- Login into your PayPal account
- Go to Profile & Settings
- Navigate to “My Selling Tools” from left menu.
- Click “Update” next to “Instant payment notifications”.

- Click “Choose IPN Settings”
- Set “Notification URL”, put there your “paypal_ipn.php” full url.
- Under “IPN messages”, select “Receive IPN messages (Enabled)” and click Save.

Don’t forget to change ‘notify_url’ field value to your “paypal_ipn.php” full url in “products.php” also.
Now that we have enabled the PayPal IPN, it’s time to create “paypal_ipn.php” file to validate and store payments.
<?php
namespace Listener;
//include PayPal IPN Class file (https://github.com/paypal/ipn-code-samples/blob/master/php/PaypalIPN.php)
require('PaypalIPN.php');
//include configuration file
require('core_config.php');
use PaypalIPN;
$ipn = new PaypalIPN();
if ($enable_sandbox) {$ipn->useSandbox();}
$verified = true;
$ipn->verifyIPN();
//reading $_POST data from PayPal
$data_text = "";
foreach ($_POST as $key => $value) {
$data_text .= $key . " = " . $value . "\r\n";
}
// Checking if our paypal email address was changed during payment.
$receiver_email_found = false;
if (strtolower($_POST["receiver_email"]) == strtolower($paypal_seller)) {
$receiver_email_found = true;
}
// Checking if price was changed during payment.
// Get product price from database and compare with posted price from PayPal
$correct_price_found = false;
$prep_stmt = "SELECT price FROM paypal_products WHERE id = ?";
$stmt = $mysqli->prepare($prep_stmt);
$item_number = $_POST["item_number"];
if ($stmt) {
$stmt->bind_param('s', $item_number);
$stmt->execute();
$stmt->store_result();
$stmt->bind_result($price);
if ($stmt->num_rows >= 1) {
while ($stmt->fetch()) {
if ($_POST["mc_gross"] == $price) {
$correct_price_found = true;
break;
}
}
}
$stmt->close();
}
//Checking Payment Verification
$paypal_ipn_status = "PAYMENT VERIFICATION FAILED";
if ($verified) {
$paypal_ipn_status = "Email address or price mismatch";
if ($receiver_email_found || $correct_price_found) {
$paypal_ipn_status = "Payment has been verified";
// Check if payment has been completed and insert payment data to database
// if ($_POST["payment_status"] == "Completed") {
// uncomment upper line to exit sandbox mode
// Insert payment data to database
if ($insert_stmt = $mysqli->prepare("INSERT INTO paypal_payments (item_no, transaction_id, payment_amount, payment_status) VALUES (?, ?, ?, ?)")) {
$item_number = $_POST["item_number"];
$transaction_id = $_POST["txn_id"];
$payment_amount = $_POST["mc_gross"];
$payment_status = $_POST['payment_status'];
$insert_stmt->bind_param('ssss', $item_number, $transaction_id, $payment_amount, $payment_status);
if (! $insert_stmt->execute()) {
$paypal_ipn_status = "Payment has been completed but not stored into database";
}
$paypal_ipn_status = "Payment has been completed and stored to database";
}
// }
// uncomment upper line to exit sandbox mode
}
} else {
$paypal_ipn_status = "Payment verification failed";
}
?>
Payment Success Page (payment_success.php)
After payment has been completed successfully, we should handle user redirection to this page.
<html>
<head>
<title>PayPal Integration - Payment Completed Successfully</title>
</head>
<body>
<h1>Payment Completed Successfully</h1>
</body>
</html>
Payment Cancel Page (payment_cancel.php)
If payment is cancelled in PayPal website, the user will be redirected in this page, and we will display our error message.
<html>
<head>
<title>PayPal Integration - Payment has been cancelled</title>
</head>
<body>
<h1>Payment has been cancelled</h1>
</body>
</html>
That’s it!
Test your PayPal integration, do some transactions in sandbox mode & check database if orders are there.
If everything is ok, edit $system_mode (leave it blank), $paypal_seller (your paypal email address), $payment_return_success & $payment_return_cancel (your own urls) in configuration file (core_config.php) and start accepting payments in your website via PayPal.
Thanks for reading, please share your thoughts in comments section below.