Jump to content


Photo

paypal ipn script not working


  • Please log in to reply
4 replies to this topic

#1 phencesgirl

phencesgirl
  • Members
  • PipPip
  • Member
  • 10 posts

Posted 03 October 2006 - 04:32 PM

Hello! I am a newbie, trying to modify this script that I found, so that it will work with paypal's ipn(instant payment notification) option.

As I understand it, paypal should post some information to the url I have specified in my profile. Then, I need to post the same info back to paypal, and then I can update tables, etc...to process the order. 

I have set up my paypal profile so that ipn is enabled, and the URL that it is set to should call this script:

<?php
//paypal.php IPN validation
/*
Derived from info at paypal developer forums and
http://www.eliteweaver.co.uk/testing/ipntest.php
*/

// No ipn post means this script does not exist
if (!@$_POST['txn_type']){@header("Status: 404 Not Found"); exit;
}else{
header("Status: 200 OK"); }

$paypal['business']="my_email_address@example.net"; //this I have edited
$paypal['url'] = 'https://www.sandbox.paypal.com/cgi-bin/webscr'; //I do have a sandbox account

$ipn_log_file = '/log/ipn_log.txt'; //I have made this directory
$ipn_log = '['.date('m/d/Y g:i A').'] - ';
$postipn = 'cmd=_notify-validate';

foreach ($_POST as $ipnkey => $ipnval) {
if (get_magic_quotes_gpc()){$ipnval = stripslashes ($ipnval);}
// Fix issue with magic quotes
if (!eregi("^[_0-9a-z-]{1,30}$",$ipnkey)|| !strcasecmp ($ipnkey, 'cmd')){unset($ipnkey);unset($ipnval);}
// ^ Antidote to potential variable injection and poisoning
if (@$ipnkey != '') { 
@$_PAYPAL[$ipnkey] = $ipnval; unset ($_POST);
/* Remove empty keys (not values) Assign data to new global array Destroy the original ipn post array*/
$postipn.='&'.@$ipnkey.'='.urlencode(@$ipnval); 
}
}
$error=0;
$url_parsed=parse_url($paypal['url']);
// Post back the reconstructed instant payment notification
$socket = @fsockopen($url_parsed['host'],80,$err_no,$err_str,30);
$header = "POST /cgi-bin/webscr HTTP/1.0\r\n";
$header.= "Content-Type: application/x-www-form-urlencoded\r\n";
$header.= "Content-Length: ".strlen($postipn)."\r\n";
$header.= "Accept: */*\r\n\r\n";

if(!$socket) {
// could not open the connection. the error message will be in the log.
$fso_error = "fsockopen error no. $errnum: $errstr";
$ipn_log .= "\n FSO:". $fso_error;
} else {
$fputs=@fputs ($socket,$header.$postipn."\r\n\r\n");
while (!feof($socket)){$response = fgets($socket,1024); }
@fclose ($socket);
$fso_error = "socket ok";
}
$response = trim($response);

// assign posted variables to local variables
$receiver_id=$_PAYPAL['receiver_id'];
$payment_type=$_PAYPAL['payment_type'];
$payment_status=$_PAYPAL['payment_status'];
$txn_type=$_PAYPAL['txn_type'];
$txn_id=$_PAYPAL['txn_id'];
$mc_gross=$_PAYPAL['mc_gross'];
$payment_gross=$_PAYPAL['payment_gross'];
$mc_fee=$_PAYPAL['mc_fee'];
$payment_fee=$_PAYPAL['payment_fee'];
$mc_currency=$_PAYPAL['mc_currency'];
$tax=$_PAYPAL['tax'];
$shipping=$_PAYPAL['shipping'];
$item_name=$_PAYPAL['item_name'];
$item_number=$_PAYPAL['item_number'];
$quantity=$_PAYPAL['quantity'];
$payer_status=$_PAYPAL['payer_status'];
$payer_email=$_PAYPAL['payer_email'];
$first_name=$_PAYPAL['first_name'];
$last_name=$_PAYPAL['last_name'];
$payer_id=$_PAYPAL['payer_id'];
$receiver_id=$_PAYPAL['receiver_id'];
$receiver_email=$_PAYPAL['receiver_email'];
$business=$_PAYPAL['business'];
$verify_sign=$_PAYPAL['verify_sign'];
$custom=$_PAYPAL['custom'];

$ipn_log .= "IPN POST:\n";
foreach ($_PAYPAL as $key=>$value) {
$ipn_log .= "$key=$value, ";
}

if (!strcmp ($response, "VERIFIED")) {
		// IPN was confirmed as both genuine and VERIFIED
		// Check that the "payment_status" variable is: Completed and that the "receiver_email" is yours
		if ($_POST['payment_status'] == 'Completed' && $_POST['receiver_email'] == 'my_email_address@example.net') { //this email I have edited as well
	
		// Update your db and process this payment accordingly
		$item_name = $_POST['item_name'];
		$payment_amount = $_POST['payment_amount'];
		$payment_currency = $_POST['payment_currency'];
		
		//get the quantity bought of each item.
		$sql="SELECT * FROM cart WHERE username='$item_name' AND confirmed='no'";
		$result = mysql_query($sql) or die(mysql_error());
		while ($row = mysql_fetch_array($result, MYSQL_ASSOC)) {
			extract($row);	
			$total= mysql_query("SELECT SUM(order_total) FROM cart WHERE username='$item_name' AND confirmed='no'");
				
			// process payment
			//update the quantity in the products table
			$pid = $row['product_id'];
			$stock = $row['stock'];
			$quantity = $row['quantity'];
			$newstock = $stock - $quantity;
							
			$sql="UPDATE products SET quantity='$newstock' WHERE product_id='$pid'";
			mysql_query($sql) or die(mysql_error());
							
			//update the quantity in the wish table
			$sql="UPDATE wish SET quantity='$newstock' WHERE product_id='$pid'";
			mysql_query($sql) or die(mysql_error());
							
			//change cart table's confirmed column to yes
			$sql="UPDATE cart SET confirmed='yes' WHERE username='$item_name' AND product_id='$pid'";
			mysql_query($sql) or die(mysql_error());
	}
// Log the response from the paypal server
$ipn_log .= "\n IPN Response VERIFIED:\n ";
$ipn_log .= "\n FSO:". $fso_error;
	} 
	}else{
		// IPN was not validated as genuine and is INVALID
		$ipn_log .= "\n IPN Response INVALID:\n ".$postipn;
		$ipn_log .= "\n FSO:". $fso_error;
	}
// Write to log
$fp=fopen($ipn_log_file,'a');
fwrite($fp, $ipn_log . "\n\n");
fclose($fp); // close file
?>
So, am I correct that this script should output nothing in the browser, but should update the tables if the payment is completed? I have tested this script using paypal's sandbox, but it is not updating my tables at all. Also, I am not sure why the local variables have to equal '$_PAYPAL' variables, instead of '$_POST' variables.

All help will be appreciated. Thank you!

#2 steveclondon

steveclondon
  • Members
  • PipPipPip
  • Advanced Member
  • 161 posts

Posted 03 October 2006 - 04:57 PM

Its been a while since I did all of this but If I remember correctly you have two types pdt that provides information back as soon as the client gets redirected back from paypal and then the ipn which is sent to your ipn page on your site. The ipn page does not handle anything. On the script I wrote it emailed if it successfully updated in the information in the database. If you are stuck still I can post my code up here.

#3 phencesgirl

phencesgirl
  • Members
  • PipPip
  • Member
  • 10 posts

Posted 03 October 2006 - 05:52 PM

Thank you for your reply! 

I don't think I need an email if the db was updated properly.  If there was a problem with payment, then I would like the script to just write the error info to the specified directory. 

But the main problem in this script is that it is not updating the db.  This script I found is a little above my head(since I am really new to php).  So, here is another script that I wrote mostly, which should do the same thing(albeit without the extra features) as the script I found and posted first:
<?php
	// 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";
	$fp = fsockopen ('www.sandbox.paypal.com', 80, $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'];
	$txn_id = $_POST['txn_id'];
	$receiver_email = $_POST['receiver_email'];
	$payer_email = $_POST['payer_email'];
	
	if (!$fp) {
		// HTTP ERROR
	} else {
		fputs ($fp, $header . $req);
		while (!feof($fp)) {
			$res = fgets ($fp, 1024);
			if (strcmp ($res, "VERIFIED") == 0) {	
				// check the payment_status is Completed
				if ($payment_status == 'COMPLETED') {
					//get the quantity bought of each item.
					$sql="SELECT * FROM cart WHERE username='$item_name' AND confirmed='no'";
					$result = mysql_query($sql) or die(mysql_error());
					while ($row = mysql_fetch_array($result, MYSQL_ASSOC)) {
						extract($row);	
						$total= mysql_query("SELECT SUM(order_total) FROM cart WHERE username='$item_name' AND confirmed='no'");
						// check that payment_amount/payment_currency are correct
						if ($payment_amount == $total && $payment_currency == 'USD' && $receiver_email == 'my_email_addy_goes_here') {
							// process payment
							//update the quantity in the products table
							$pid=$row['product_id'];
							$stock = $row['stock'];
							$quantity = $row['quantity'];
							$newstock = $stock - $quantity;
							
							$sql="UPDATE products SET quantity='$newstock' WHERE product_id='$pid'";
							mysql_query($sql) or die(mysql_error());
							
							//update the quantity in the wish table
							$sql="UPDATE wish SET quantity='$newstock' WHERE product_id='$pid'";
							mysql_query($sql) or die(mysql_error());
							
							//change cart table's confirmed column to yes
							$sql="UPDATE cart SET confirmed='yes' WHERE username='$item_name' AND product_id='$pid'";
							mysql_query($sql) or die(mysql_error());
						}//end if statement
					} //end while loop
			} else if (strcmp ($res, "INVALID") == 0) {
				// log for manual investigation
			}
		} //end if statement
	fclose ($fp);
	} //end while loop
  }//end else statement
?>

This script should update the tables, as long as the receiver email == my paypal primary email address, and the total payment amount is correct.  Can't see why it is having this problem and not updating the tables.  Thank you!

#4 Daniel0

Daniel0
  • Staff Alumni
  • Advanced Member
  • 11,956 posts

Posted 03 October 2006 - 06:08 PM

PayPal has a developer center that contains some information about this topic:
https://developer.paypal.com/

#5 phencesgirl

phencesgirl
  • Members
  • PipPip
  • Member
  • 10 posts

Posted 03 October 2006 - 08:05 PM

thank you, Daniel0.  I have been reading a lot in paypal's developer's central site, and I have searched through the forums there, however, it hasn't helped me to figure out this problem.  ??? 

My db tables are not being updated.  The script is set up to update them if the ipn is verified, and the payment is completed.  However, both of those things appear to be happening, because the paypal sandbox email account that I have emails me everytime I try to 'pay' for something, and those emails say that the payment went through alright (in the sandbox). 

Then, it seems there must be something wrong with the way my script is getting the $_POST variables.  Thank you all for dealing with this newbie! 




0 user(s) are reading this topic

0 members, 0 guests, 0 anonymous users