How to setup PayPal Integration in Your Website (Best Tutorial in PHP + MySQL)

7

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.
How to create PayPal Sandbox Account

Img 1, How to create PayPal Sandbox account

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.

<?
//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”.
PayPal Integration - How to find IPN in PayPal website

Img 2, How to find IPN in PayPal website

  • 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.
PayPal Integration - IPN Settings

Img 3, How to set PayPal IPN settings

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.

Download Source Code | View Live Demo

Share.

About Author

trying to fulfil my name meaning...

7 Comments

  1. Thanks for the example. One question is still open: what if there are pending payments that are not directly “confirmed” by Paypal. How do I get those updates from Paypal?
    Do I need an extra cronjob script and if so is there an example somewhere on the net. I have search and gone through a huge bunch of sites. Could not find info about Pending payment status.
    I need if to make the payment process full automated on my advertising site with paypal pay buttons (no shop).

    Hope you can inform me like you did on this excellent info page.

    • Ideal Kamerolli on

      Hi Roland,

      Good question! Surely, we need a way to check transaction status, because transactions are not always confirmed instantly by PayPal, there are many ways to check transaction status but for this time I created a simple script that allows you to check all your transaction details (including Payment Status), I recommend you to set up a cronjob and run this script every 15-30 minutes.

      First of all you have to request your NVP/SOAP API credentials, use this link to go directly in the right page where you can request your API: https://www.paypal.com/businessprofile/mytools/apiaccess/firstparty, select “Request API signature” and click “Agree & Submit”, right after you will see: API Username, API Password and Signature, our connection to PayPal will be made using this information.

      Edit our script below and replace variable values: $API_USERNAME, $API_PASSWORD, $API_SIGNATURE and $Transaction_ID with API values from PayPal.

      Get PayPal Transaction Details Script:

      
      < ?php
      $API_USERNAME = 'yourapiusername';
      $API_PASSWORD = 'yourapipassword';
      $API_SIGNATURE = 'yourapisignature';
      $Transaction_ID = 'yourtransactionid';
      
      $ch = curl_init();
      
      curl_setopt($ch, CURLOPT_URL, 'https://api-3t.paypal.com/nvp'); //In sandbox, please change api url to: https://api-3t.sandbox.paypal.com/nvp
      curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
      curl_setopt($ch, CURLOPT_POSTFIELDS, "USER=$API_USERNAME&PWD=$API_PASSWORD&SIGNATURE=$API_SIGNATURE&METHOD=GetTransactionDetails&VERSION=78&TransactionID=$Transaction_ID");
      curl_setopt($ch, CURLOPT_POST, 1);
      $headers = array();
      $headers[] = 'Content-Type: application/x-www-form-urlencoded';
      curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
      $result = curl_exec($ch);
      
      if (curl_errno($ch)) {
          echo 'Error:' . curl_error($ch);
      }
      
      parse_str($result, $transaction_details);
      
      //print_r($transaction_details); //uncomment this line to print whole array
      
      echo $transaction_details['PAYMENTSTATUS']; //replace "PAYMENTSTATUS" with other fields from array to get the desired information
      
      curl_close ($ch);
      ?>
      
      

      Now that we have the required information we can update field “payment_status” of our transaction in database, in few days I will provide a simple example how to update this information.

      This is it, I hope it will help you to make your payments fully automated!

      Thanks for your question!

    • Ideal Kamerolli on

      Hi Gilles,

      Thanks for notifying us about this mistake, in SQL file “PRIMARY KEY (`payment_id`)” should be replaced with “PRIMARY KEY (`id`)” and everything should be fine.

      BTW: For new users, we updated our post and replaced “payment_id” with “id”.

Leave A Reply