Paypal IPN Sandbox - IPN Listener - no verified or invalid

Niels picture Niels · Jul 18, 2013 · Viewed 6.9k times · Source

I have set up test accounts Business and Personal in developer for trying out sandbox mode.

I have made a payment button on my site. I click the button and go to paypal. Test user personal account is used for paying. Payment goes through and is Completed when i look in the Paypal business account. Redirect to my site works good.

So in my eyes i should have a "working" system.

My IPN Listener though does not return either verified or invalid.

This is my listener:

 <?php
 require("../widgets/init.inc.php");

//Test the script is launced
$log_query = mysql_query("INSERT INTO `log` VALUES (' ','zz','ff','rr', 'rr')");                

// Link to PayPal Codes //
// https://cms.paypal.com/us/cgi-bin/?cmd=_render-content&content_ID=developer/e_howto_html_IPNandPDTVariables // 

// read the post from PayPal system and add 'cmd' //
$req = 'cmd=_notify-validate';

foreach ($_POST as $key => $value) {
$value = urlencode(stripslashes($value));
$req .= "&$key=$value";
}

// post back to PayPal system to validate //
$header .= "POST /cgi-bin/webscr HTTP/1.0\r\n";
$header .= "Content-Type: application/x-www-form-urlencoded\r\n";
$header .= "Content-Length: " . strlen($req) . "\r\n\r\n";

//For the below line i have tried "www.sandbox.paypal" as well as "www.paypal"
$fp = fsockopen ('ssl://www.paypal.com', 443, $errno, $errstr, 30);

// 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'];
$txnId = $_POST['txn_id'];
$receiverEmail = $_POST['receiver_email'];
$payerEmail = $_POST['payer_email'];
//$id = ($_POST['custom']);

if (!$fp) {

} else {
fputs ($fp, $header . $req);
while (!feof($fp)) {
$res = fgets ($fp, 1024);
if (strcmp ($res, "VERIFIED") == 0) {

if ($payment_status=='Completed') {

//$txnIdCheck = mysql_query("SELECT `txnId` FROM `log` WHERE `txnId`='".$txnId."'");  
//if (mysql_num_rows($txnIdCheck) !=1) {

// enter your email address associated with your paypal account here // 
if ($receiverEmail=='[email protected]') { 

/* when a new premium member makes payment paypal will update our database. The txn_id from paypal, members email address, date of payment and members id we gave them when they joined our site will be inserted into the log table. At the same time the memberAdmin table for the member will be updated by adding a '1' to premium and the date of payment so the new premium member will have access to premium areas of your site. */

//Check if verified is launced          
$log_query_2 = mysql_query("INSERT INTO `log` VALUES (' ','yes','yes','yes', 'yes')");          

//$log_query = mysql_query("INSERT INTO `log` VALUES (' ','".intval($id)."','".$txnId."','".$payerEmail."', now())");                   

//$update_premium = mysql_query("UPDATE `memberAdmin` SET `premium`=1, `premiumDate`=now() WHERE `id`=".intval($id)."");    

}       
//}
}
}
else if (strcmp ($res, "INVALID") == 0) {         
//Check if invalid is launced
$log_query_2 = mysql_query("INSERT INTO `log` VALUES (' ','no','no','no', 'no'");   
}
}
fclose ($fp);
}
?>

I have activated the IPN at the paypal business account site. I have made a txt file of the returned information from paypal, and it looks like this:

==== Thu, 18 Jul 2013 01:34:21 +0200 ====
POST: mc_gross = 0.01
POST: protection_eligibility = Ineligible
POST: payer_id = 73WPPK8HKSW7C
POST: tax = 0.00
POST: payment_date = 15:15:20 Jul 17, 2013 PDT
POST: payment_status = Completed
POST: charset = windows-1252
POST: first_name = Niels
POST: mc_fee = 0.01
POST: notify_version = 3.7
POST: payer_status = verified
POST: business = [email protected]
POST: quantity = 1
POST: verify_sign = A-ddKAwtxju4TpHGJOGq6c3ewj26AyiHsD.XO90coZ.4rVzOT7VyooKO
POST: payer_email = [email protected]
POST: txn_id = 6WH41489RE087103M
POST: payment_type = instant
POST: last_name = Tester
POST: receiver_email = [email protected]
POST: payment_fee = 0.01
POST: receiver_id = PCX638B2M7WPA
POST: txn_type = web_accept
POST: item_name = 500Credits
POST: mc_currency = USD
POST: item_number = 1
POST: residence_country = DE
POST: test_ipn = 1
POST: handling_amount = 0.00
POST: transaction_subject = 500Credits
POST: payment_gross = 0.01
POST: shipping = 0.00
POST: ipn_track_id = 2dffcbf8767d3
InvoiceID: 
Custom1: 
Custom2: 
Custom3: 

It seems like it is a lot harder to get this to work than what I think it should be.

Answer

Niels picture Niels · Jul 18, 2013

I found the problem.. AND THE ANNOYING THING IS THAT PAYPAL DOCUMENTATION IS WRONG AGAIN.. I don't understand that the documentation can state press this button and press this button.. WHEN there are no buttons like this in the site...

For this problem - The documentation does state a wrong method / does not include full code needed.

THE PROBLEM: The $res returned this:

HTTP/1.0 400 Bad Request
Server: BigIP
Connection: close
Content-Length: 19
Invalid Host header

what needs to be added is :

$header .= "Host: www.sandbox.paypal.com\r\n";

AND then the above code looks like this:

// post back to PayPal system to validate //
$header .= "POST /cgi-bin/webscr HTTP/1.0\r\n";
$header .= "Host: www.sandbox.paypal.com\r\n";
$header .= "Content-Type: application/x-www-form-urlencoded\r\n";
$header .= "Content-Length: " . strlen($req) . "\r\n\r\n";
$fp = fsockopen ('ssl://www.sandbox.paypal.com', 443, $errno, $errstr, 30);

This was the full code i ended up using:

<?php
require("../widgets/init.inc.php");         

// Link to PayPal Codes //
// https://cms.paypal.com/us/cgi-bin/?cmd=_render-content&content_ID=developer/e_howto_html_IPNandPDTVariables // 

// read the post from PayPal system and add 'cmd' //
$req = 'cmd=_notify-validate';

foreach ($_POST as $key => $value) {
 $value = urlencode(stripslashes($value));
 $req .= "&$key=$value";
}

// post back to PayPal system to validate //
$header .= "POST /cgi-bin/webscr HTTP/1.0\r\n";
$header .= "Host: www.sandbox.paypal.com\r\n";
$header .= "Content-Type: application/x-www-form-urlencoded\r\n";
$header .= "Content-Length: " . strlen($req) . "\r\n\r\n";
$fp = fsockopen ('ssl://www.sandbox.paypal.com', 443, $errno, $errstr, 30);

// 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'];
$txnId = $_POST['txn_id'];
$receiverEmail = $_POST['receiver_email'];
$payerEmail = $_POST['payer_email'];
//$id = ($_POST['custom']);


if (!$fp) {

} else {
fputs ($fp, $header . $req);
while (!feof($fp)) {
$res = fgets ($fp, 1024);

$log_query_pre = mysql_query("INSERT INTO `log` VALUES (' ','$receiverEmail','$payment_status','$res', 'yes')");    

  if (strcmp ($res, "VERIFIED") == 0) {

if ($payment_status=='Completed') {

//$txnIdCheck = mysql_query("SELECT `txnId` FROM `log` WHERE `txnId`='".$txnId."'");  
//if (mysql_num_rows($txnIdCheck) !=1) {

// enter your email address associated with your paypal account here // 
if ($receiverEmail=='[email protected]') { 

/* when a new premium member makes payment paypal will update our database. The txn_id from paypal, members email address, date of payment and members id we gave them when they joined our site will be inserted into the log table. At the same time the memberAdmin table for the member will be updated by adding a '1' to premium and the date of payment so the new premium member will have access to premium areas of your site. */

//Check if verified is launced          
$log_query_2 = mysql_query("INSERT INTO `log` VALUES (' ','yes','yes','yes', 'yes')");      

//$log_query = mysql_query("INSERT INTO `log` VALUES (' ','".intval($id)."','".$txnId."','".$payerEmail."', now())");                   

//$update_premium = mysql_query("UPDATE `memberAdmin` SET `premium`=1, `premiumDate`=now() WHERE `id`=".intval($id)."");    

}       
//}
}
}
else if (strcmp ($res, "INVALID") == 0) {         
//Check if invalid is launced
$log_query_2 = mysql_query("INSERT INTO `log` VALUES (' ','no','no','no', 'no')");  
}
}
fclose ($fp);
}
?>