^ Scroll to Top
Contact us | Login

Archive for September, 2010

Paypal IPN INVALID on LIVE server but VALID on TEST server FIXED

Tuesday, September 14th, 2010


This paylap IPN INVALID problem has been the bane of my life for the past few days.  I have been building a invoicing system to invoice my clients, this system uses the paypal IPN to update my invoices in my system as paid and send a thank you email to the customer.

I started running my test transactions on paypals sandbox server and everything worked fine, every transaction processed properly but as soon as i tried a few small transactions on the LIVE paypal site they were coming back as INVALID by the IPN script, they were being processed and completing successfully but just not being validated by the IPN script.

Naturally you start to weed out what the difference’s can be and the only things changing between the TEST & LIVE server was the server address, the buyer email and seller email addresses (you have to use test email accounts on the test server).  Eventually after trying PHP IPN scripts direct from the paypal site and stil getting the same result i thought it was maybe a problem with my personal account so i got my mother to try a live transaction and it failed too.

After trying everything i could think of, wasting a lot of time and making sure it was not my fault i decided to call paypal support, the tech-guy i eventually spoke to was very good and ran me through everything and didn’t make me feel rushed at all. I sent him the scripts i had been using and he checked them and they seemed to look ok to him so he was a bit puzzled as well. After eliminating my scripts as the problem he was happy to try a few test live transactions from his live test account and hay presto they worked!!! We then tried to find out why his worked and mine and my mothers failed, there was no obvious answer so i got a friend to  try a live transaction and it worked too. It was very confusing to me and the tech but i decided to go live and i sent out a few invoices from my new invoicing system and the first two that were paid came back as INVALID grrr…

I now had a long list of  VALID & INVALID IPN responses, and i lined them up in a table and went through every detail, i firstly noticed that the ones that actually VALIDATED had unconfirmed addresses and the INVALID ones had confirmed addresses.   I then ran a few tests and captured the IPN response before it was sent to paypal with the one paypal had in it’s IPN history, i then noticed that address line one and address line two(optional) were put on the same line in the IPN response but there was a carriage return between the first and second line.

I noticed that paypal sends this carriage as %0D%0A but carriage returns in php 5.2 is %0A which is what my server was sending back causing the INVALID IPN response. The reason this never happened with paypal’s sandbox test server is that the test accounts you make in the sandbox don’t have the second address line which is optional and which was causing the problem, also the IPN tester in the sandbox account doesn’t have the second address line, so it is almost imposable to recreate this problem on the test server, and in case you were wondering the tech and my friend’s liver test’s that worked both didn’t have the second optional address line filed out.

Solution

The one line of code that could have saved me hundreds in wasted time.

$value = preg_replace('/(.*[^%^0^D])(%0A)(.*)/i','${1}%0D%0A${3}',$value);

This line replaces the %0A with %0D%0A in your IPN repose string thus solving the INVALID warning and making it VALID where it should be.

I am not sure what is causing the difference in the way the server are encoding the url but if you are having this same problem just add the line to your IPN script like i did below.

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

		foreach ($_POST as $key => $value)
		{
			$value = urlencode(stripslashes($value));
			$value = preg_replace('/(.*[^%^0^D])(%0A)(.*)/i','${1}%0D%0A${3}',$value);// IPN fix
			$req .= "&$key=$value";

Thanks for reading and if this helps you please feel free to leave me a comment.