Avatar of Ryan Bayne
Ryan BayneFlag for United Kingdom of Great Britain and Northern Ireland asked on

Paypal IPN Script Returning INVALID

Hi

I've been working on Paypal IPN for a week on and off now getting no where fast really so I'm getting desperate. Right now I'm at a point where I can test my IPN script using Sandbox tool and I get INVALID response.

Or we can use Buynow button here...
http://www.ad-hit.com/scripts/paypal/examples/buynow.php

and that doesnt cause a POST to my IPN script! I'll show the code for it below.

Anyone got any ideas why after the BuyNow process, confirming the transaction on Paypal, Paypal would not POST to my IPN? Once I get that sorted I will move on to figuring out why every response is INVALID.

Thanks
This is the main variables for the buynow button...
 
/* Add variables to Form PARAMTERS MUST ADHERE TO PAYPAL STANDARDS */
$buyNow->addVar('business','paypal@webtechglobal.co.uk');	/* Payment Email */
$buyNow->addVar('cmd','_xclick');
$buyNow->addVar('amount','2.99');
$buyNow->addVar('item_name','Ad-Hit Points 500');
$buyNow->addVar('item_number','POINTS500');
$buyNow->addVar('quantity','1');
$buyNow->addVar('tax','1.99');
$buyNow->addVar('shipping','8.00');
$buyNow->addVar('currency_code','USD');
$buyNow->addVar('no_shipping','2');		/* Must provide shipping address */
$buyNow->addVar('rm','2'); /* Return method must be POST (2) for this class */
$buyNow->addVar('custom','500');/* Ad-Hit POINTS being bought */
/* Paypal IPN URL - MUST BE URL ENCODED and is the checkpayment.php file */
$buyNow->addVar('notify_url','http://www.ad-hit/scripts/paypal/examples/checkpayment.php');	
/* Set URL for Thank you Page (if any) in variable */
$buyNow->addVar('return','http://www.ad-hit.com/index.php?page=pages_member/paypal_success');
 
 
This is the top of my IPN script, checkpayment.php I have put an mail there to test its use. It only gets this far when testing through the sandbox not when using my buynow button...
 
<?php
mail('admin@webtechglobal.co.uk', "TEST checkpayment Run", "checkpayment.php was accessed during this transaction");
						
/* Get Paypal Class */
require_once('../paypal.class.php');
 
/* Paypal is name of the Class */
$doCheck = new Paypal;

Open in new window

E-CommercePHPWeb Development

Avatar of undefined
Last Comment
Ray Paseur

8/22/2022 - Mon
SOLUTION
Beverley Portlock

Log in or sign up to see answer
Become an EE member today7-DAY FREE TRIAL
Members can start a 7-Day Free trial then enjoy unlimited access to the platform
Sign up - Free for 7 days
or
Learn why we charge membership fees
We get it - no one likes a content blocker. Take one extra minute and find out why we block content.
See how we're fighting big data
Not exactly the question you had in mind?
Sign up for an EE membership and get your own personalized solution. With an EE membership, you can ask unlimited troubleshooting, research, or opinion questions.
ask a question
ASKER
Ryan Bayne

Its ON.

No URL entered however I didnt think you had to as I need multiple sites using the one account.

I've only got Log entries from payments made with Sandbox. So my guess is the problem lays with my BuyNow form telling paypal exactly what I want as in a POST to IPN script using notify_url.

Simply because there doesnt seem to be an attempt to do so. I've placed mail around the script so I can a few emails telling me what part of the script is running and whats not and the first line is not even being reached.

SOLUTION
Beverley Portlock

Log in or sign up to see answer
Become an EE member today7-DAY FREE TRIAL
Members can start a 7-Day Free trial then enjoy unlimited access to the platform
Sign up - Free for 7 days
or
Learn why we charge membership fees
We get it - no one likes a content blocker. Take one extra minute and find out why we block content.
See how we're fighting big data
Not exactly the question you had in mind?
Sign up for an EE membership and get your own personalized solution. With an EE membership, you can ask unlimited troubleshooting, research, or opinion questions.
ask a question
ASKER
Ryan Bayne

Yes using the IPN tool I can get something happening. Not desired results but I would prefer to forget that right now and test by the button.

If I can get the same thing happening with the button I'll stop using the test tool plus anyone helping can use the button to see what I mean. The code should forward the user to MY page after payment and it does not so you can witness that yourself.
SOLUTION
Log in to continue reading
Log In
Sign up - Free for 7 days
Get an unlimited membership to EE for less than $4 a week.
Unlimited question asking, solutions, articles and more.
ASKER
Ryan Bayne

Alright so those are always required. And email I take it is my email, yes that makes sense!

See how I get on thanks. Get back to you soon.
I started with Experts Exchange in 2004 and it's been a mainstay of my professional computing life since. It helped me launch a career as a programmer / Oracle data analyst
William Peck
ASKER
Ryan Bayne

Do you mean the buyers country because that information wouldnt be in the form but I've never seen a variable name for sellers country!

Any idea what that is
ASKER
Ryan Bayne

I cant see a cancel_return variable in the list here...

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

I assume its when the buyer cancels they will be returned to it so the value is to be url yes
SOLUTION
Log in to continue reading
Log In
Sign up - Free for 7 days
Get an unlimited membership to EE for less than $4 a week.
Unlimited question asking, solutions, articles and more.
ASKER CERTIFIED SOLUTION
Log in to continue reading
Log In
Sign up - Free for 7 days
Get an unlimited membership to EE for less than $4 a week.
Unlimited question asking, solutions, articles and more.
SOLUTION
Log in to continue reading
Log In
Sign up - Free for 7 days
Get an unlimited membership to EE for less than $4 a week.
Unlimited question asking, solutions, articles and more.
ASKER
Ryan Bayne

OK heres what I have so far, couple still missing according to what you said but I'm reading up on each variable to ensure I understand.

Now the page viewed when clicking on buynow button on my page, displays an error...
https://developer.paypal.com/us/cgi-bin/devscr

Aint sure if its my changes or something wrong with the sandbox
/* Add variables to Form PARAMTERS MUST ADHERE TO PAYPAL STANDARDS */
$buyNow->addVar('business','paypal@webtechglobal.co.uk');	/* Account ID or Primary Email*/
$buyNow->addVar('receiver_email','paypal@webtechglobal.co.uk');	/* Primary payment email */
$buyNow->addVar('cmd','_xclick');
$buyNow->addVar('amount','2.99');
$buyNow->addVar('item_name','Ad-Hit Points 500');
$buyNow->addVar('item_number','POINTS500');
$buyNow->addVar('quantity','1');
$buyNow->addVar('tax','1.99');
$buyNow->addVar('shipping','8.00');
$buyNow->addVar('currency_code','GBP');
$buyNow->addVar('no_shipping','2');		/* Must provide shipping address */
$buyNow->addVar('rm','2'); /* Return method must be POST (2) for this class */
$buyNow->addVar('custom','500');/* Ad-Hit POINTS being bought */
$buyNow->addVar('address_country_code','GB');/* sellers address country code */
 
/* Paypal IPN URL - MUST BE URL ENCODED and is the checkpayment.php file */
$buyNow->addVar('notify_url','http://www.ad-hit/scripts/paypal/examples/checkpayment.php');	
/* Set URL for Thank you Page (if any) in variable */
$buyNow->addVar('return','http://www.ad-hit.com/index.php?page=pages_member/paypal_success');
/* Cancel return URL */
$buyNow->addVar('return','http://www.ad-hit.com/index.php?page=pages_member/paypal_cancel');

Open in new window

Get an unlimited membership to EE for less than $4 a week.
Unlimited question asking, solutions, articles and more.
Ray Paseur

I'm not sure that notify_url and IPN are the same, but in any case, wouldn't we would need to see that script to explain why you're getting the 'invalid' notice?  It's coming from the IPN, right?
ASKER
Ryan Bayne

Ray what do you use $postdata     $postdata       .= "\n $key = $value ";  for I cant tell?

I'll compare your script to my own properly once I can get my buynow button working. This is really two problems but I'll split full points.

Thanks for your help
SOLUTION
Log in to continue reading
Log In
Sign up - Free for 7 days
Get an unlimited membership to EE for less than $4 a week.
Unlimited question asking, solutions, articles and more.
ASKER
Ryan Bayne

Yes ofcourse here ya go. It is a class... my actual IPN file is checkpayment.php which starts like...

The first line is for testing. I mentioned that this mail doesnt happen at all with the buynow button but it does with paypal IPN tool in sandbox. So the buynow button goes through the transaction and the IPN is not used. Probably is a problem with the form I'm submitting but this is a downloaded class online, well tested etc so I'm not too sure.

<?php
mail('admin@webtechglobal.co.uk', "TEST checkpayment Run", "checkpayment.php was accessed during this transaction");
                                    
/* Get Paypal Class */
require_once('../paypal.class.php');

/* Paypal is name of the Class */
$doCheck = new Paypal;

/* Record any bad/unauthorized transactions for debugging and security */
$doCheck->setLogFile('logfile.txt');

/* Actually check payment - isPaid = true if payment good else false*/
$isPaid = $doCheck->checkPayment($_POST);

//Final part, process data at our end for our needs as payment is a success, issue product also
if($isPaid == true)
{

go on to process payment...
<?php 
class Paypal 
{	/* commented out by ryan
	private $VARS;
	private $button;
	private $logFile;
	$isTest=false;
	*/
	
	/* Print Form as Link */
	function getLink()
	{
		$url = $this->getPaypal();
		$link = 'https://'.$url.'/cgi-bin/webscr?';
		foreach($this->VARS as $item => $sub){
			$link .= $sub[0].'='.$sub[1].'&';
		}
		return $link;
	}
	
	/* Print Form */
	function showForm()
	{
		$url = $this->getPaypal();
		$FORM  = '<form action="https://'.$url.'/cgi-bin/webscr" method="post" target="_blank" style="display:inline;">'."\n";
		
		foreach($this->VARS as $item => $sub){
			$FORM .= '<input type="hidden" name="'.$sub[0].'" value="'.$sub[1].'">'."\n";
		}
				
		$FORM .= $this->button;    
		$FORM .= '</form>';
		echo $FORM;
	}
	
	/* Add variable to form */
	function addVar($varName,$value)
	{
		$this->VARS[${varName}][0] = $varName;
		$this->VARS[${varName}][1] = $value;
	}
	
	/* Add button Image */
	function addButton($type,$image = NULL)
	{
		switch($type)
		{
			/* Buy now */
			case 1:
				$this->button = '<input type="image" height="21" style="width:86;border:0px;"';
				$this->button .= 'src="https://www.paypal.com/en_US/i/btn/btn_paynow_SM.gif" border="0" name="submit" ';
				$this->button .= 'alt="PayPal - The safer, easier way to pay online!">';
				break;
			/* Add to cart */	
			case 2:
				$this->button = '<input type="image" height="26" style="width:120;border:0px;"';
				$this->button .= 'src="https://www.paypal.com/en_US/i/btn/btn_cart_LG.gif" border="0" name="submit"';
				$this->button .= 'alt="PayPal - The safer, easier way to pay online!">';
				break;
			/* Donate */	
			case 3:
				$this->button = '<input type="image" height="47" style="width:122;border:0px;"';
				$this->button .= 'src="https://www.paypal.com/en_US/i/btn/btn_donateCC_LG.gif" border="0" name="submit"';
				$this->button .= 'alt="PayPal - The safer, easier way to pay online!">';
				break;
			/* Gift Certificate */
			case 4:	
				$this->button = '<input type="image" height="47" style="width:179;border:0px;"';
				$this->button .= 'src="https://www.paypal.com/en_US/i/btn/btn_giftCC_LG.gif" border="0" name="submit"';
				$this->button .= 'alt="PayPal - The safer, easier way to pay online!">';
				break;
			/* Subscribe */
			case 5:	
				$this->button = '<input type="image" height="47" style="width:122;border:0px;"';
				$this->button .= 'src="https://www.paypal.com/en_US/i/btn/btn_subscribeCC_LG.gif" border="0" name="submit"';
				$this->button .= 'alt="PayPal - The safer, easier way to pay online!">';
				break;
			/* Custom Button */
			default:
				$this->button = '<input type="image" src="'.$image.'" border="0" name="submit"';
				$this->button .= 'alt="PayPal - The safer, easier way to pay online!">';
		}
		$this->button .= "\n";
	}
	
	/* Set log file for invalid requests */
	function setLogFile($logFile)
	{
		$this->logFile = $logFile;
	}
	
	/* Helper function to actually write to logfile */
	function doLog($_POST)
	{
		ob_start();
		echo '<pre>'; print_r($_POST); echo '</pre>';
		$logInfo = ob_get_contents();
		ob_end_clean();
		
		$file = fopen($this->logFile,'a');
		fwrite($file,$logInfo);
		fclose($file);
	}
	
	/* Check payment */
	function checkPayment($_POST)
	{
	 	mail('admin@webtechglobal.co.uk', "IPN TEST", "function checkpayment line 108 in paypal.class.php - application has arrived at this point");
 
		/* read the post from PayPal system and add 'cmd' */
		$req = 'cmd=_notify-validate';
		
		/* Get post values and store them in req */
		foreach ($_POST as $key => $value) 
		{
			$value = urlencode(stripslashes($value));
			$req .= "&$key=$value";
		}
		
		$url = $this->getPaypal();
		
		/* 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 ('ssl://'.$url, 443, $errno, $errstr, 30); //try different port if having issues
		//$fp = fsockopen ('ssl://'.$url, 80, $errno, $errstr, 30);
	
		if (!$fp) 
		{
		    mail('admin@webtechglobal.co.uk', "FP FALSE", "function checkpayment line 135 in paypal.class.php - application has arrived at this point");
			return false; 
		} 
		else 
		{   	 	mail('admin@webtechglobal.co.uk', "FP TRUE", "function checkpayment line 139 in paypal.class.php - application has arrived at this point");
 
			fputs ($fp, $header . $req);
			while (!feof($fp)) 
			{
				$res = fgets ($fp, 1024);
				if (strcmp ($res, "VERIFIED") == 0) 
				{	mail('admin@webtechglobal.co.uk', "VERFIED", "function checkpayment line 146 in paypal.class.php - application has arrived at this point");	
					return true; //checkpayment.php receives true
				} 
				else //	if (strcmp ($res, "INVALID") == 0)
				{
					/*	log for manual investigation	*/
					if($this->logFile != NULL)
					{ mail('admin@webtechglobal.co.uk', "INVALID", "function checkpayment line 153 in paypal.class.php - application has tried to write to log please confirm");
						$this->doLog($_POST);
					}
					return false;
				}
			}
			fclose ($fp);
		}
		return false;
	}
	
	/* Set Test */
	function useSandBox($value)
	{
		$this->isTest=$value;
	}
	
	/* Private function to get paypal url */
	function getPaypal()
	{
		if($this->isTest == true)
		{
			return 'www.sandbox.paypal.com';
		} 
		else 
		{
			return 'www.paypal.com';
		}
	}
}
?>

Open in new window

All of life is about relationships, and EE has made a viirtual community a real community. It lifts everyone's boat
William Peck
SOLUTION
Log in to continue reading
Log In
Sign up - Free for 7 days
Get an unlimited membership to EE for less than $4 a week.
Unlimited question asking, solutions, articles and more.
ASKER
Ryan Bayne

OK I was a bit far from getting the form right, I think I been at this script too long lol

I cant test the button anymore Sandbox is not working. I'll have to wait until it is then get back to you on the result later. I'll work on getting past INVALID returns just now.

thanks so far all
/* Add variables to Form PARAMTERS MUST ADHERE TO PAYPAL STANDARDS */
$buyNow->addVar('business','paypal@webtechglobal.co.uk');	/* Account ID or Primary Email*/
$buyNow->addVar('receiver_email','paypal@webtechglobal.co.uk');	/* Primary payment email */
$buyNow->addVar('cmd','_xclick');
$buyNow->addVar('amount','2.99');
$buyNow->addVar('item_name','Ad-Hit Points 500');
$buyNow->addVar('item_number','POINTS500');
$buyNow->addVar('quantity','1');
$buyNow->addVar('tax','1.99');
$buyNow->addVar('shipping','8.00');
$buyNow->addVar('currency_code','GBP');
$buyNow->addVar('no_shipping','2');		/* Must provide shipping address */
$buyNow->addVar('rm','2'); /* Return method must be POST (2) for this class */
$buyNow->addVar('custom','500');/* Ad-Hit POINTS being bought */
$buyNow->addVar('country','GB');/* sellers address country code */
/* Paypal IPN URL - MUST BE URL ENCODED and is the checkpayment.php file */
$buyNow->addVar('notify_url','http://www.ad-hit/scripts/paypal/examples/checkpayment.php');	
/* Set URL for Thank you Page (if any) in variable */
$buyNow->addVar('return','http://www.ad-hit.com/index.php?page=pages_member/paypal_success');
/* Cancel return URL */
$buyNow->addVar('cancel_return','http://www.ad-hit.com/index.php?page=pages_member/paypal_cancel');

Open in new window

ASKER
Ryan Bayne

Just as I posted that I tried again and the sandbox is working. But still no change. Is the sandbox actually meant to make the IPN happen through a transaction? Do you know this for sure?

I may just go onto getting the INVALID returns fixed then do live testing, would there be any point?
SOLUTION
Log in to continue reading
Log In
Sign up - Free for 7 days
Get an unlimited membership to EE for less than $4 a week.
Unlimited question asking, solutions, articles and more.
ASKER
Ryan Bayne

Ray I cant see this line in my script...
      $paypal_headers      .= $paypal_reply;
and it appears to be at a vital stage just before VERIFIED or INVALID is decided. Can you say what it does exactly?

OK bportlock I'll continue to get the button working and go with that. Didnt really like the sound of live testing early anyway!
Get an unlimited membership to EE for less than $4 a week.
Unlimited question asking, solutions, articles and more.
ASKER
Ryan Bayne

Still no luck I think I've got a lot to learn with this so just closing the question. What I never understand with Paypal IPN scripts is that I'm downloading them from tested sources and using them with Sandbox without making changes. They are meant to return VERIFIED in that case so its a bit frustrating.

thanks for your help on this
Beverley Portlock

I was setting up a PayPal account last night and the kept getting the INVALID message. It turned out that php_openssl was not installed as part of the PHP installation. Something to check maybe?
Ray Paseur

To answer this...

Ray what do you use $postdata     $postdata       .= "\n $key = $value ";  for I cant tell?

I use it in another place in my script to print or email the data that was posted.  Mostly for my own edification.  IIRC, I might throw that whole line into a data base table, but I'm not recalling that right now.

HTH ~Ray
Experts Exchange is like having an extremely knowledgeable team sitting and waiting for your call. Couldn't do my job half as well as I do without it!
James Murphy
Ray Paseur

To answer this...

Ray I cant see this line in my script...
      $paypal_headers      .= $paypal_reply;
and it appears to be at a vital stage just before VERIFIED or INVALID is decided. Can you say what it does exactly?

When you read over a socket, you get headers first, then data (like HTML) after the headers.  In the context that I use that statement, it causes the variable $paypall_headers to contain the headers and $paypal_reply to contain the data.

Best of luck with your project, ~Ray