Paypal Integration
Paypal Integration
Parts 1 and 3 are accessible by customers on your website. Part 2 is only visible
to PayPal. The diagram below illustrates the interaction between your
customer, PayPal and your website.
The following steps break down each part of the process into easy to follow
chunks, it is assumed that you have knowledge of PHP and MySQL.
NOTE
If you are not receiving the correct response from Paypal ensure that
you are using the main test account (Verified Business Account) from
your Paypal Sandbox account.
Also ensure that you are testing the Paypal IPN Script on an online
webserver (Not MAMP, Xampp etc..) as Paypal requires a reachable
'return url', 'cancel url' and 'notify url'.
Sign up for a PayPal account if you don’t already have one. In order to use
IPN, the Paypal account you are selling from must be a Business Account.
Once you have a registered PayPal account your account must be setup
correctly to use IPN. Select 'edit profile' from your PayPal account and check
the following settings.
Under 'My Selling Preferences' >> 'Getting paid and managing risk' >>
'Instant Payment Notification Preferences'
o Set the IPN value to 'On'
o Set the IPN URL to the PHP page containing the IPN code shown
in steps 3 & 4 of this tutorial.
(http://www.example.com/payment.php)
Under 'My Selling Preferences' >> 'Getting paid and managing risk' >>
'Block payments'
o Block payments from users who pay with eCheque. (This is
because these will not be instant payments)
Under 'account information' >> 'email'
o Note down your primary email address. This email will be visible
to users so make it a professional one. User's may feel
apprehensive about sending money to an e-mail address with the
domain 'hotmail.com' or 'Yahoo.com' etc...
Your website must now send all the required values to PayPal so that the
payment can be processed.
The following code example demonstrates a basic form that we will use to
send the values:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-
scale=1">
<title>Paypal Integration Test</title>
</head>
<body>
</body>
</html>
Copy
The business name, price, submit type, notify URL and other sensitive values
will be sent during the next step.
A full list of the values to send can be found at the PayPal website under the
title "A Sample IPN Message and Response".
STEP 3 – THE REQUEST
The payment.php page will be used to handle the outgoing request to PayPal
and also to handle the incoming response after the payment has been
processed.
To make a request for payment we need to first build up the parameters and
pass these to PayPal via the query string.
We need to pass the following values:
business - the email address of your PayPal account
item_name - the name of the item being purchased
amount - the price of the item
return - the address to return to after a successful payment
cancel_return - the address to return to after a cancelled payment
notify_url - the address of the payments.php page on your website
custom - any other data to be sent and returned with the PayPal request
$paypalUrl = $enableSandbox ?
'https://www.sandbox.paypal.com/cgi-bin/webscr' :
'https://www.paypal.com/cgi-bin/webscr';
// Include Functions
require 'functions.php';
} else {
// Handle the PayPal response.
}Copy
To construct the query string we assign the post data to an array that we then
push some additional values to that we don't want to be altered by the post
data. This way we can ensure that a user cannot manipulate the amount being
paid or any other details that may be vulnerable. We then use
http_build_query to convert the array to a query string and pass this to PayPal
via the header.
STEP 4 - THE RESPONSE
We now want to handle the response from PayPal, this is the callback PayPal
makes to our notify URL we configured earlier. We reassign the post response
to a local variable and then verify the transaction is authentic and check we've
not already processed this transaction before adding the payment to our
database.
To do all this we want to add the following code to the else statement of our
payments.php script.
// Handle the PayPal response.
$req = 'cmd=_notify-validate';
foreach ($data as $key => $value) {
$value = urlencode(stripslashes($value));
$value = preg_replace('/(.*[^%^0^D])(%0A)(.*)/i',
'${1}%0D%0A${3}', $value); // IPN fix
$req .= "&$key=$value";
}
$ch = curl_init($paypalUrl);
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);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 30);
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Connection:
Close'));
$res = curl_exec($ch);
if (!$res) {
$errno = curl_errno($ch);
$errstr = curl_error($ch);
curl_close($ch);
throw new Exception("cURL error: [$errno] $errstr");
}
$info = curl_getinfo($ch);
$txnid = $db->real_escape_string($txnid);
$results = $db->query('SELECT * FROM `payments` WHERE txnid
= \'' . $txnid . '\'');
return ! $results->num_rows;
}Copy
This is also a good opportunity for you to add any additional checks you might
want to put in place before accepting the payment on your site. For example,
you might want to check the amount paid tallies with the amount you were
charging.
STEP 5 - ADD THE PAYMENT
With the response from PayPal verified and any additional checks we want to
make at our end complete it's time to add the payment to our database.
To store payment details in our database a payments table must be created.
The following MySQL will create the payments table used in this example
code.
CREATE TABLE IF NOT EXISTS `payments` (
`id` int(6) NOT NULL AUTO_INCREMENT,
`txnid` varchar(20) NOT NULL,
`payment_amount` decimal(7,2) NOT NULL,
`payment_status` varchar(25) NOT NULL,
`itemid` varchar(25) NOT NULL,
`createdtime` datetime NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;Copy
Then in our code we're calling addPayment to insert a payment into the
database. This function looks like this:-
function addPayment($data) {
global $db;
if (is_array($data)) {
$stmt = $db->prepare('INSERT INTO `payments` (txnid,
payment_amount, payment_status, itemid, createdtime) VALUES(?,
?, ?, ?, ?)');
$stmt->bind_param(
'sdsss',
$data['txn_id'],
$data['payment_amount'],
$data['payment_status'],
$data['item_number'],
date('Y-m-d H:i:s')
);
$stmt->execute();
$stmt->close();
return $db->insert_id;
}
return false;
}Copy
SANDBOX TESTING / GOING LIVE
PayPal Sandbox offers all of the functionality of PayPal, but uses "Fake
accounts" created by the developer within the sandbox. You can create fake
buyer and fake seller profiles, then test your PayPal integration through your
development website. Sandbox accounts can be created on the PayPal
Developer website for free.
When testing with the sandbox we use the www.sandbox.paypal.com URL. For
live payments we need to use www.paypal.com. Our example code is
configured to use the sandbox, but you can switch it to live payments by
changing $enableSandbox to false, this will update the URLs used to
communicate with PayPal.
Once the payment process is ready to be used by real customers you will need
to disable the sandbox mode in the code.
That’s it; you’re ready to start taking payments online through your website.