Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
PayPal IPN How To guide
<?php
// STEP 1: read POST data
// Reading POSTed data directly from $_POST causes serialization issues with array data in the POST.
// Instead, read raw POST data from the input stream.
$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 IPN message sent from PayPal and prepend 'cmd=_notify-validate'
$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";
}
// STEP 2: POST IPN data back to PayPal to validate
$ch = curl_init('https://www.paypal.com/cgi-bin/webscr');
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_SSL_VERIFYPEER, 1);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
curl_setopt($ch, CURLOPT_FORBID_REUSE, 1);
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Connection: Close'));
// In wamp-like environments that do not come bundled with root authority certificates,
// please download 'cacert.pem' from "http://curl.haxx.se/docs/caextract.html" and set
// the directory path of the certificate as shown below:
// curl_setopt($ch, CURLOPT_CAINFO, dirname(__FILE__) . '/cacert.pem');
if( !($res = curl_exec($ch)) ) {
// error_log("Got " . curl_error($ch) . " when processing IPN data");
curl_close($ch);
exit;
}
curl_close($ch);
// STEP 3: Inspect IPN validation result and act accordingly
if (strcmp ($res, "VERIFIED") == 0) {
// The IPN is verified, process it:
// check whether the payment_status is Completed
// check that txn_id has not been previously processed
// check that receiver_email is your Primary PayPal email
// check that payment_amount/payment_currency are correct
// process the notification
// assign posted variables to local variables
$item_name = $_POST['item_name'];
$item_number = $_POST['item_number'];
$payment_status = $_POST['payment_status'];
$payment_amount = $_POST['mc_gross'];
$payment_currency = $_POST['mc_currency'];
$txn_id = $_POST['txn_id'];
$receiver_email = $_POST['receiver_email'];
$payer_email = $_POST['payer_email'];
// IPN message values depend upon the type of notification sent.
// To loop through the &_POST array and print the NV pairs to the screen:
foreach($_POST as $key => $value) {
echo $key." = ". $value."<br>";
}
} else if (strcmp ($res, "INVALID") == 0) {
// IPN invalid, log for manual investigation
echo "The response from IPN was: <b>" .$res ."</b>";
}
?>
<?php
// STEP 1: read POST data
// Reading POSTed data directly from $_POST causes serialization issues with array data in the POST.
// Instead, read raw POST data from the input stream.
$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 IPN message sent from PayPal and prepend 'cmd=_notify-validate'
$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";
}
// Step 2: POST IPN data back to PayPal to validate
$ch = curl_init('https://www.paypal.com/cgi-bin/webscr');
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_SSL_VERIFYPEER, 1);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
curl_setopt($ch, CURLOPT_FORBID_REUSE, 1);
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Connection: Close'));
// In wamp-like environments that do not come bundled with root authority certificates,
// please download 'cacert.pem' from "http://curl.haxx.se/docs/caextract.html" and set
// the directory path of the certificate as shown below:
// curl_setopt($ch, CURLOPT_CAINFO, dirname(__FILE__) . '/cacert.pem');
if( !($res = curl_exec($ch)) ) {
// error_log("Got " . curl_error($ch) . " when processing IPN data");
curl_close($ch);
exit;
}
curl_close($ch);
<?php
// inspect IPN validation result and act accordingly
if (strcmp ($res, "VERIFIED") == 0) {
// The IPN is verified, process it:
// check whether the payment_status is Completed
// check that txn_id has not been previously processed
// check that receiver_email is your Primary PayPal email
// check that payment_amount/payment_currency are correct
// process the notification
// assign posted variables to local variables
$item_name = $_POST['item_name'];
$item_number = $_POST['item_number'];
$payment_status = $_POST['payment_status'];
$payment_amount = $_POST['mc_gross'];
$payment_currency = $_POST['mc_currency'];
$txn_id = $_POST['txn_id'];
$receiver_email = $_POST['receiver_email'];
$payer_email = $_POST['payer_email'];
// IPN message values depend upon the type of notification sent.
// To loop through the &_POST array and print the NV pairs to the screen:
foreach($_POST as $key => $value) {
echo $key." = ". $value."<br>";
}
} else if (strcmp ($res, "INVALID") == 0) {
// IPN invalid, log for manual investigation
echo "The response from IPN was: <b>" .$res ."</b>";
}
?>
<?php
// inspect IPN validation result and act accordingly
if (strcmp ($res, "VERIFIED") == 0) {
// The IPN is verified, process it
} else if (strcmp ($res, "INVALID") == 0) {
// IPN invalid, log for manual investigation
}
?>
@DubFriend

This comment has been minimized.

Copy link

commented Apr 18, 2014

After a 8-9 hours of yak shaving with paypal's example code, and various stackoverflow posts, this script finally solved my problems thanks!

@KenGood

This comment has been minimized.

Copy link

commented Apr 25, 2014

Many thanks for this code, its a great help. I sympathise with DubFriend above, having suffered a similar experience and been on the phone to PayPal 3 times without being helped with a solution. One question, is there any reason that Step 1 of this code didn't just do:
$req = 'cmd=_notify-validate&'.$raw_post_data;

@lynnellneri

This comment has been minimized.

Copy link

commented Jun 16, 2014

Whoooh! After thoroughly reading the APN Introduction and is about to drafting my code, when I got stuck about how to capture the verification response from Paypal. And so I searched through Google and I've found this.

I am so glad I've found this code. Thanks a lot. I'll going to try it now, hehehehe.

I am still new will all these stuffs, especially the "curl" thing and HTTP POST things, hehehehe.

@antwonlee

This comment has been minimized.

Copy link

commented Jun 21, 2014

How do you assign Notification URL within PHP script?

@Sandervandenberg01

This comment has been minimized.

Copy link

commented Jul 4, 2014

@antwonlee: It's done by adding a hidden input field to your form which posts the paypal payment info. The name of the input should be "notify_url".

You could also set the url in your paypal profile settings

@riteshkhadka

This comment has been minimized.

Copy link

commented Jul 25, 2014

I am getting Unverified status (strcmp ($res, "VERIFIED") is -1) but I am receiving txn_id and payment_status=Completed. Why I am getting Unverified Status. I am using this functionality for dodirect payment through credit card.

@linobanfi

This comment has been minimized.

Copy link

commented Nov 23, 2014

hello how to setup "notify_url" in my profile to not be visible on site input.

@rankai

This comment has been minimized.

Copy link

commented Nov 26, 2014

Hi, thanks for the gist, but I got invalid instead of verified, what should I do after I deploy your code?

@efhale

This comment has been minimized.

Copy link

commented Dec 15, 2014

thanks for the code but could you tell me where I'm supposed to put this? Do I create an invisible page or load this in the page or header files? I can do very basic code modifications and I'm not scared to load code I just need to know where or how to input it into my site or paypal site?

@boomx09

This comment has been minimized.

Copy link

commented Jan 2, 2015

Super helpful, this finally worked! Thank you! One small detail that threw me for a bit is that during testing you want to use

$ch = curl_init('https://www.sandbox.paypal.com/cgi-bin/webscr');

instead of

$ch = curl_init('https://www.paypal.com/cgi-bin/webscr');

on line 32

@gogolmogol

This comment has been minimized.

Copy link

commented Mar 25, 2015

There is much easier solution:

$postdata = 'cmd=_notify-validate&';
$postdata.= file_get_contents('php://input');

$URL = "https://www.paypal.com/cgi-bin/webscr";
$opts = array('http' => array('method' => 'POST', 'header' => 'Content-type: application/x-www-form-urlencoded', 'content' => $postdata));
$context = stream_context_create($opts);
$result = file_get_contents($URL, false, $context);

Enjoy! :)

@blue-ice

This comment has been minimized.

Copy link

commented Jul 9, 2015

If you are getting unverified IPNs during testing with the Paypal Sandbox, what boomx09 did fixed my problem- change this:

$ch = curl_init('https://www.sandbox.paypal.com/cgi-bin/webscr');

from this:

$ch = curl_init('https://www.paypal.com/cgi-bin/webscr');

Thanks, boomx09 :)

@hypeJunction

This comment has been minimized.

Copy link

commented Aug 2, 2015

Payload sent by IPN may contain a multidimensional array that is not properly URL encoded.
The format chosen by PayPal (one may never know why):

transaction[0].status=Completed&transaction[1].status=Completed

instead of a nicely formatted:

transaction[0][status]=Completed&transaction[1][status]=Completed

You can use this regexp (which is probably not entirely bullet proof):


$postData = file_get_contents('php://input');
$ipn = new PPIPNMessage($postData);
if (!$ipn->validate()) {
    exit;
}
$data = array();
$fixArr = preg_replace("/\b(\w+)\\%5B(\w+)\\%5D\.([^=]*)[=]([^\&]*)([\&$])\b/", "$1%5B$2%5D%5B$3%5D=$4$5", $postData);
parse_str($fixArr, $data);
@joaorocha123

This comment has been minimized.

Copy link

commented Aug 21, 2015

Hello,
Could you tell me how to use the code? I created a ipn-listener.php file, uploaded it to the server and tried to use it but some thing does't work. I'm using IPN simulator from PAYPAL website but I ca´nt see nothing.

Thank you in advance.
João

@deshmukhlalit

This comment has been minimized.

Copy link

commented Jun 8, 2016

Hello,
Could you tell me how to use the code? I created a ipn-listener.php file, uploaded it to the server and tried to use it but some thing does't work. I'm using IPN simulator from PAYPAL website but I ca´nt see nothing.

@deshmukhlalit

This comment has been minimized.

Copy link

commented Jun 8, 2016

How do you assign Notification URL within PHP script?

@braebot

This comment has been minimized.

Copy link

commented Sep 15, 2016

Please see https://github.com/paypal/ipn-code-samples/blob/master/paypal_ipn.php for the up-to-date php code. This gist has gotten quite stale. 🌽 🍞

@yosba

This comment has been minimized.

Copy link

commented Oct 1, 2016

It's normal that Paypal send many notifycations by ipn to my site for the same purchase???? By each one Paypal send 9 or 10 notifycations, all of completed payment. ...??

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.