Solved

PHP - need helo with PayPal IPN listener.

Posted on 2014-03-19
5
902 Views
Last Modified: 2016-03-24
Hi,
I have the following PayPal IPN listener script but need help understanding the foreach statements below and assigning posted variables to local variables.

Should I use

$address_street = $_POST['address_street'];

or

$address_street = $myPost['address_street'];


Thanks

<?php
// CONFIG: Enable debug mode. This means we'll log requests into 'ipn.log' in the same directory.
// Especially useful if you encounter network errors or other intermittent problems with IPN (validation).
// Set this to 0 once you go live or don't require logging.
define("DEBUG", 1);

// Set to 0 once you're ready to go live
define("USE_SANDBOX", 0);

define("LOG_FILE", "./ipn.log");

// 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


if(USE_SANDBOX == true) {
	$paypal_url = "https://www.sandbox.paypal.com/cgi-bin/webscr";
} else {
	$paypal_url = "https://www.paypal.com/cgi-bin/webscr";
}


$ch = curl_init($paypal_url);
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_SSL_VERIFYPEER, 1);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
curl_setopt($ch, CURLOPT_FORBID_REUSE, 1);


if(DEBUG == true) {
	curl_setopt($ch, CURLOPT_HEADER, 1);
	curl_setopt($ch, CURLINFO_HEADER_OUT, 1);
}


// CONFIG: Optional proxy configuration
//curl_setopt($ch, CURLOPT_PROXY, $proxy);
//curl_setopt($ch, CURLOPT_HTTPPROXYTUNNEL, 1);


// Set TCP timeout to 30 seconds
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 30);
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Connection: Close'));


// CONFIG: Please download 'cacert.pem' from "http://curl.haxx.se/docs/caextract.html" and set the directory path
// of the certificate as shown below. Ensure the file is readable by the webserver.
// This is mandatory for some environments.


//$cert = __DIR__ . "./cacert.pem";
//curl_setopt($ch, CURLOPT_CAINFO, $cert);


$res = curl_exec($ch);
if (curl_errno($ch) != 0) // cURL error
	{
	if(DEBUG == true) {	
		error_log(date('[Y-m-d H:i e] '). "Can't connect to PayPal to validate IPN message: " . curl_error($ch) . PHP_EOL, 3, LOG_FILE);
	}
	curl_close($ch);
	exit;


} else {
		// Log the entire HTTP response if debug is switched on.
		if(DEBUG == true) {
			error_log(date('[Y-m-d H:i e] '). "HTTP request of validation request:". curl_getinfo($ch, CURLINFO_HEADER_OUT) ." for IPN payload: $req" . PHP_EOL, 3, LOG_FILE);
			error_log(date('[Y-m-d H:i e] '). "HTTP response of validation request: $res" . PHP_EOL, 3, LOG_FILE);

			// Split response headers and payload
			list($headers, $res) = explode("\r\n\r\n", $res, 2);
		}
		curl_close($ch);
}


// Inspect IPN validation result and act accordingly
if (strcmp ($res, "VERIFIED") == 0) {
	
	// check whether the payment_status is Completed
	// check that txn_id has not been previously processed
	// check that receiver_email is your PayPal email
	// check that payment_amount/payment_currency are correct
	// process payment and mark item as paid.
	// assign posted variables to local variables

	$mc_gross = $_POST['mc_gross'];
	$invoice = $_POST['invoice'];
	$protection_eligibility = $_POST['protection_eligibility'];
	$address_status = $_POST['address_status'];
	$payer_id = $_POST['payer_id'];
	$tax = $_POST['tax'];
	$address_street = $_POST['address_street'];


} 


?>

Open in new window

0
Comment
Question by:sabecs
  • 3
5 Comments
 
LVL 11

Accepted Solution

by:
Andrew Angell earned 250 total points
ID: 39941465
Technically, you should get basically the same thing.  It looks like they're just using $myPost to help generate the response back to PayPal for verification.  They loop through it later to generate $req, which is what is then sent to PayPal.

I've always stuck with $_POST['varname'] and it works (assuming your txn_type includes the parameter you're looking for) so that's what I'd go with.

I like to use shorthand if/else syntax on those to avoid warnings in situations where the variable isn't included.

$address_street = isset($_POST['address_street']) ? $_POST['address_street'] : '';

Open in new window

0
 
LVL 109

Expert Comment

by:Ray Paseur
ID: 39942060
Where in the world did you find this thing?  It's surely not the PayPal example, right?!

There are a lot of moving parts in a PayPal IPN script!

A good foundation in PHP would be helpful here.
http://www.experts-exchange.com/Web_Development/Web_Languages-Standards/PHP/A_11769-And-by-the-way-I-am-new-to-PHP.html

If you only have time to study PHP from one book, I would go with Welling/Thompson.  Get the latest edition and when a new edition comes out, get the new edition and give the obsolete edition to one of your enemies.

I have some time later today, and I'll try to give you an annotated (comments) version of the script, but in between now and then go through the script line-by-line looking at the functions.  If you have any doubt about exactly how the function works, look it up on PHP.net and learn exactly how it works!  Example: urlencode()
0
 
LVL 109

Assisted Solution

by:Ray Paseur
Ray Paseur earned 250 total points
ID: 39942691
assigning posted variables to local variables
This misunderstands the concept of variable scope.  "Posted" variables are found in $_POST which is a PHP superglobal array.  It is present in every scope and namespace, thus is it always a local variable.  It's also mutable and I think it should not be, but that's a philosophical argument for another time.

Reading the raw post data from stdin presents a security risk.  It takes too much time to explain it all, but if you want a reason, the reason is that php://input does not necessarily contain only the POST request variables.  The preferred way to handle posted data is to use $_POST.  That's why it's there.

I was going to annotate the script, but after reading it more carefully I'm going to recommend that you get rid of it and start over.  Make this exact Google search:
https://www.google.com/search?q=paypal+ipn

In the results you will find these references and code examples with very good explanations.  They cover the "Classic API" which seems to be what you're using.

Introducing IPN
IPN and PDT Variables
Getting Started
IPN Simulator
Testing
the IPN Guide PDF (70 pages)

The overview is this...

1. PayPal makes a POST-method request to your IPN script whenever a payment-related event occurs.  Usually, hopefully, this is a received payment, but it can also be things like a declined check or a reversal.  Your programming will have to account for these things, as shown in the IPN Guide.

2. Your IPN script makes a verification post back to PayPal with the exact information that PayPal sent in the POST request.

3. PayPal responds with VERIFIED and you thereby know you can trust the information.

Anything else is up to your business application needs.
0
 

Author Comment

by:sabecs
ID: 39943942
Thanks for your comments, very much appreciated.
I will need to have a closer look at all the documentation.

I can't remember exactly where I found the script I am using, but is looks very similar to the one PayPal suggest: https://developer.paypal.com/docs/classic/ipn/ht_ipn/
0
 
LVL 109

Expert Comment

by:Ray Paseur
ID: 39944135
The PayPal suggestion look like it came from PHP4.  Maybe that is an artifact of the "classic" designation - meaning "from the 1950's" and it may be time to upgrade to the newer APIs.  Technology is always advancing.

In 2004 I would have copied the PayPal IPN example without understanding it.  Today I would try to understand it, forgive it where it was deficient, and improve it where I could.  It's been a few years since I went under the hood to look at PayPal inner workings.  If you can find a JSON or XML interface, that will be easier to use than the classic.
0

Featured Post

Does Powershell have you tied up in knots?

Managing Active Directory does not always have to be complicated.  If you are spending more time trying instead of doing, then it's time to look at something else. For nearly 20 years, AD admins around the world have used one tool for day-to-day AD management: Hyena. Discover why

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Introduction HTML checkboxes provide the perfect way for a web developer to receive client input when the client's options might be none, one or many.  But the PHP code for processing the checkboxes can be confusing at first.  What if a checkbox is…
I imagine that there are some, like me, who require a way of getting currency exchange rates for implementation in web project from time to time, so I thought I would share a solution that I have developed for this purpose. It turns out that Yaho…
Explain concepts important to validation of email addresses with regular expressions. Applies to most languages/tools that uses regular expressions. Consider email address RFCs: Look at HTML5 form input element (with type=email) regex pattern: T…
The viewer will learn how to count occurrences of each item in an array.

810 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question