If you have IPN enabled in your account, log into the account and look at the IPN history. You should be able to tell from here if your IPN's are being sent out, or if they are in a retrying or failed status. If you see your IPN's in here, you can click on the message id and it will show you what status is being returned by your server if it is returing one. This may help to isolate the cause of the issue. Also, here are some basic troubleshooting steps that may help with IPN issues.
Also if you are using a custom script, try using one of PayPal’s sample IPN scripts. They are very basic scripts, but they are tested working examples. This can help to determine if it’s an issue with your script or with IPN in general.
IPN troubleshooting tips
These are the most common problems affecting developers when working with IPN. The most common solutions are noted as well. Hope this information helps someone out there!
REASONS FOR INVALID
- Make sure you are posting back ALL variables/values.
For PayPal to return VERIFIED, your IPN script needs to post back ALL the variables that were posted to it in the first place. In other words, if your script only needs to manipulate 1 or 2 variables, it is not enough to post back to PayPal only the variables/values your script is concerned with. Your script should post back EVERYTHING that was initially posted to it from PayPal. This is the only way PayPal will return VERIFIED
- Make sure you are not posting back to the wrong URL.
If you are testing in the Sandbox, you need to ensure your script posts back to www.sandbox.paypal.com. If you are on the live site, the script should post back to www.paypal.com. You will receive INVALID if you are testing in the Sandbox and your script posts back to the live site (or vice versa)
PayPal's IPN server expects that your script will POST back all variables that were posted to it and more importantly, that they are encoded the same way as they were sent to your script. If your script inadvertently changed the encoding of a character or interprets an encoded character as another character and POSTs back, you will likely see INVALID. This can happen sporadically and tends to occur, for example, when a payment is received and the buyer may have an accented character in their name or the order is for some item with a non-standard character in the item name. These instances are tricky to troubleshoot but it is listed here as it can cause INVALID when you would expect VERIFIED. Look for this issue when you are seeing that certain IPNs are INVALID and all the rest are VERIFIED.
TROUBLESHOOTING TIPS - IPN is not POSTing!
- Email address on receiving account.
Make sure you've confirmed the e-mail address on the account the payment is being sent to.
If you feel IPN is not posting to your script, you can verify this by checking your server's access logs. The server access logs will tell you if PayPal is "hitting your script" at all. An access log tracks the IP addresses and/or hostnames of computers that access the server. That you can access your server's access logs is up to the server admin. Check with them if you do not know where the logs are.
Error logs
Most scripting languages output to error logs if an error occurs when running the script. If you see in your access logs that PayPal is sending the IPN but you are not seeing the intended end result from your script, odds are you have a logic or syntax error in the script. Check your error logs to verify. Again, if you don't know how or where to check these logs, you would need to consult your server's administrator.
Check Paths
An easy mistake to make. Always ensure the path to your script is correct when testing/using IPN and you see that you are not getting an IPN post. For example avoid using "localhost" urls. Since this is a back end server to server communication setting a path to localhost will cause the IPN to try to post to itself rather than outside the network to your own server/script.
IPN is an HTTP POST initiated from PayPal. If you have a firewall on your server, make sure your firewall is not blocking the post from PayPal.
- Test to make sure your script works as intended.
If your script has a syntax or logic error in it, odds are you will not see the correct result. An easy way to test your script is by sending a "dummy" post to the script and writing some code to "do something" if the response from PayPal is INVALID. Essentially, if you copy the code that you want to fire when the response from PayPal is VERIFIED to the part of the script that runs if the response is INVALID, you can send a dummy post to the script to see if your code works. Since a dummy post to the script will return INVALID (since the post was not originated from PayPal), this is why you want to add the code to the 'if INVALID' part of your script.
- Posts to your return URL (Return Method)
Some merchants are setup such that they would like to get IPN data posted to the value of their return variable in their button code (return). This is the URL the buyer is directed to after a PayPal payment has been made. To have IPN data POSTed to your return URL you must set the rm variable equal to "2" in your button code or you may not see any IPN data POSTed to your return URL. For more information see this post. ** Note that this information is about IPN data can be passed through the return and how it works with your return URL (button code variable 'return'). If you have Auto Return with PDT enabled this information does not apply to you as PDT is its own separate feature. More information on PDT can be found here.
TROUBLESHOOTING TIPS - IPN is Delayed
In most cases consistent delays in IPNs are caused when your server is not responding with a 200ok for to many of your transaction IPNs. For example, when your sever does not reply with a 200ok PayPal attempts a repost of the data. After so many reposts of the data that do not receive the 200ok your IPNs get moved to a slower cycling server, hence the delays.
First check your IPN Logs for the status of the POSTs:
In your account under the history section you should have a "IPN History" section where you can see the last 28 days worth of IPNs and is some cases can resend them. If this link doe not appear for you log into your account than go here:
https://www.paypal.com/us/cgi-bin/webscr?cmd=_display-ipns-history
These logs will have a couple different statuses:
Sent - indicates that PayPal sent the message to your IPN listener
Failed - indicates that PayPal did not receive an acknowledgement (200ok) to the message for the original POST attempt or re-POSTs
Queued - indicates that PayPal is ready to send the message
Retrying - indicates that PayPal did not receive a 200ok and the message was resent between 1 and 15 times and that PayPal is continuing to resend the message
Disabled - indicates that the message will not be resent because IPN/The account has been disabled
If you see Failed or Retrying this is most likely the cause to resolve this, you will need to go through your server logs to determine why the 200ok is not being sent back to PayPal IPN. Once this is determined and remedied and your server responds with a 200ok it brings this percentage/count down from that limit and it will begin posting IPNs from the normal cycle server.
If there are no failed it may be a delay on PayPal Servers themselves in which case you will want to create a ticket to PayPal Merchant Technical Services as paypal.com/mts for further review.
Curl vs fsockopen:
This is most often a personal preference but in some cases the host provider you are going to does not support one or the other so you may need to switch between the two. Here is an example of using fsockopen:
$header = "POST /cgi-bin/webscr HTTP/1.1\r\n";
$header .= "Host: www.paypal.com\r\n";
$header .= "Content-Type: application/x-www-form-urlencoded\r\n";
$header .= "Content-Length: " . strlen($req) . "\r\n";
$header .= "Connection: Close\r\n\r\n";
$fp = fsockopen ('ssl://www.paypal.com', 443, $errno, $errstr, 30);
Here is the same thing but using curl:
$url= 'https://www.sandbox.paypal.com/cgi-bin/webscr';
$curl_result=$curl_err='';
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL,$url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $req);
curl_setopt($ch, CURLOPT_HTTPHEADER, array("Content-Type: application/x-www-form-urlencoded", "Content-Length: " . strlen($req)));
curl_setopt($ch, CURLOPT_HEADER , 0);
curl_setopt($ch, CURLOPT_VERBOSE, 1);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($ch, CURLOPT_TIMEOUT, 30);
$res = @curl_exec($ch);
$curl_err = curl_error($ch);
curl_close($ch);
Basically if you are having trouble with one and you think it may be to one method not being supported by your host/server than simply replace the one you are using with the other.
Local Testing:
This is probably on of the most important steps in production and testing any script. In regards to IPN this can be used to pass any parameter you need to your own script to test syntax and how that script will function with the variables expected. All this really would need is to set up a form with a post action to your own IPN handler and the hidden inputs for the variables/values you want to test.
For example:
<form target="_new" method="post" action="https://www.YourDomain.com/Path/IPNhandler.php">
<input type="hidden" name="SomePayPalVar" value="SomeValue1"/>
<input type="hidden" name="SomeOtherPPVar" value="SomeValue2"/>
Than etc for all other variables you want to test with.
</br>
<input type="submit"/>
</form>
As listed in many of angelleye's threads here is a link to a good example of local testing that he has set up.