Orders Stuck in Pending Payment in Magento Due to Paypal Disabling IPN
This is quite a common issue in Magento where some orders which were paid via Paypal get stuck in ‘Pending Payment’ status. After debugging the issue, often you’ll arrive at the problem of the IPN message delivery in Paypal keeps getting disabled.
Once the IPN message delivery is disabled, Paypal can’t communicate that payment was received (or failed) back to Magento so subsequently, the order status can’t progress past ‘Pending Payment’. Once this communication fails, you may see an error message similar to the below in your error logs:-
Notice: Undefined index: invoice in /var/www/vhosts/domain.com/httpdocs/app/code/core/Mage/Paypal/Model/Ipn.php on line 173
If you happen to speak to Paypal’s support team about the issue, they will likely report that the IPN keeps getting disabled because they keep receiving a server error 503 header response code back from their IPN communication (even though the actual IPN URL in Magento can be returning a 200 header response code).
So the cause of this is usually that you’re taking payments via Paypal for more than one sales channel (this will usually be Magento and eBay or Amazon). You will have already set your IPN notification URL in Paypal to the one that Magento requires:-
For Magento 1.7.x, 1.8.x, 1.9.x : http://www.domain.com/paypal/ipn/
For Magento 1.4.x, 1.5.x, 1.6.x: http://www.domain.com/paypal/ipn/standard/
For Magento 1.3.x: http://www.domain.com/paypal/standard/ipn/
When you sell an item via eBay or Amazon, PayPal tries to send an IPN message to your Magento IPN listener which fails as the order did not originate in Magento so Paypal receive an error back. Once a few errors are received, Paypal disable your IPN message delivery automatically and then any more orders paid for with Paypal in your Magento store cannot complete subsequently getting stuck as ‘Payment Pending’.
What you will need to do is create a centralised IPN listener which will allow you to receive IPN notifications for multiple channels. Simply create a file named null_ipn.php
and place it in your Magento root. Then save the below in this file.
<?php // Revision Notes // 11/04/11 - changed post back url from https://www.paypal.com/cgi-bin/webscr to https://ipnpb.paypal.com/cgi-bin/webscr // For more info see below: // https://www.x.com/content/bulletin-ip-address-expansion-paypal-services // "ACTION REQUIRED: if you are using IPN (Instant Payment Notification) for Order Management and your IPN listener script is behind a firewall that uses ACL (Access Control List) rules which restrict outbound traffic to a limited number of IP addresses, then you may need to do one of the following: // To continue posting back to https://www.paypal.com to perform IPN validation you will need to update your firewall ACL to allow outbound access to *any* IP address for the servers that host your IPN script // OR Alternatively, you will need to modify your IPN script to post back IPNs to the newly created URL https://ipnpb.paypal.com using HTTPS (port 443) and update firewall ACL rules to allow outbound access to the ipnpb.paypal.com IP ranges (see end of message)." // 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.1\r\n"; $header .= "Content-Type: application/x-www-form-urlencoded\r\n"; $header .= "Content-Length: " . strlen($req) . "\r\n\r\n"; //If testing on Sandbox use: //$fp = fsockopen ('ssl://www.sandbox.paypal.com', 443, $errno, $errstr, 30); $fp = fsockopen ('ssl://ipnpb.paypal.com', 443, $errno, $errstr, 30); 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 // check that txn_id has not been previously processed // check that receiver_email is your Primary PayPal email // check that payment_amount/payment_currency are correct // process payment // echo the response echo "The response from IPN was: <b>" .$res ."</b><br><br>"; //loop through the $_POST array and print all vars to the screen. foreach($_POST as $key => $value){ echo $key." = ". $value."<br>"; } } else if (strcmp ($res, "INVALID") == 0) { // log for manual investigation // echo the response echo "The response from IPN was: <b>" .$res ."</b>"; } } fclose ($fp); } ?>
Then log in to your Paypal account and set your Paypal IPN Notification URL to the path to this file in your Magento root. For example: http://www.domain.com/null_ipn.php
.
Hi Geoff,
Thanks, that’s a great workaround to the problem. It’s working on PayPals IPN Simulator now using your script. Our PayPal IPN started failing, shortly after updating Magento to 1.9.1.1. Before then it worked fine.
Do you have ideas to why Magento won’t handle this external request correctly?
Thanks for stopping by and taking the time to leave a comment Piers.
So are you saying that in your instance, you only take payments via Paypal for your Magento store (and not other channels such as eBay and Amazon)?
Generally, this isn’t a Magento issue, Paypal should allow businesses to add multiple IPN URL’s. Once you set an IPN URL for Magento in Paypal and then you take a payment via another channel, it can’t match the data against the IPN listener because the order never originated there.
Yes primarily through PayPal.
Indeed you are correct, after many hours of pain I discovered that the IPN simulator was reporting a successful response through your script, but actually it was not working in Magento’s back-end. I think I was getting desperate at the point of reading your post and would try anything and had lost the capacity to think!
I have tried so many tricks and none of them worked. It turned out (believe it or not) that despite reporting a successful Magento upgrade, I got so fed up that I overwrote all the files in the core PayPal directory, went off and had dinner. Voila it started working, sending through IPNs within hours… DESPITE the IPN simulator still reporting HTTP error the next day.
Thanks for leaving a comment with an update Piers.
I think you are saying that now your Paypal IPN is working? If so, great news.
Yes, the central IPN listener in my post above is only really needed if there are IPN notifications coming from multiple sales channels.
Magento can sure make us all get like you’ve described. Sometimes taking a break and coming back half an hour later can make all the difference in fact 🙂
Looked around for quite a while for this solution, thanks a lot. We have Amazon and Ebay so that was causing the IPN issues, added the file and now it’s updating, great work.
Thanks for stopping by Mike and glad you found this solution helpful.
Hello,
I am having IPN issues with out website. We use Paypal with ebay and have another website which I will be needing to link in to paypal soon too and Amazon is on its way 🙂
How does this file work?
If this file is created and the IPN pointed to it, will eBay and Amazon still get payment updates? Can a second website be added to this too?
I could not see directly from the code how this could be done. Thanks for nay help
Sorry for not replying sooner Mark.
This script acts a centralised IPN listener so it can support multiple channels taking Paypal payments.
You just simply need to point your IPN notification URL to the location of this script from within your Paypal account.
By pointing it to the default Magento URL (as documented in the post above), this causes Paypal to look in Magento for payments coming into the account from any channel and when it can’t find them, it throws an error behind the scenes and so many of these errors will cause Paypal to disable the IPN on your account.
Hope that helps.
Hi Geoff, Thanks for the script, I had seen something similar elsewhere but wasn’t sure how updated this was. Do you know if this would work for Magento EE 1.12.0.2
Hey Haim, sorry for the delayed reply. This has been used and tested, confirmed working up to Magento CE 1.9.x. I’d expect it to work in EE 1.12.x although I can’t say I have implemented it in EE to be sure though.
Hope that helps 🙂
Geoff, you have saved the day!
Following a server move our transaction ID was empty. Spent (literally days on this issue) looking at the code, and playing ping pong support tickets with server technicians.
As it had been associated with the move I was focussed on our new hosting environment or permissions, or code not working on new php version… rather than what seems so obvious now ive read your post!
Thanks a million for taking the time to write your solution up for us all to benefit.
Al
Hey Al, thanks for taking the time to leave a comment.
Glad this article helped you resolve the problem! 🙂
Hello Geoff,
Due to “PayPal Instant Payment Notification” Warning I have disabled IPN notification from paypal. But I am facing magento order status is stuck, showing “pending payment” after Disabling IPN. If I add provided code in root, do I need to enable IPN notification in paypal?
Thanks
Hey Bubai,
Magento requires that you have the IPN in Paypal set and enabled otherwise Paypal cannot communicate back to Magento to confirm that payment has been received after a Paypal sale in Magento therefore, the order is unable to proceed past ‘Pending’ status.
If you have used the central IPN listener in this article, you will need to set the Paypal IPN URL to the location of this file, i.e.
http://www.domain.com/null_ipn.php
.Does that help explain things?
Hi Geoff,
Thanks for your valuable reply, but when i am going to enabled bellow warning received from paypal –
“Please check your server that handles PayPal Instant Payment Notification (IPN) messages. Messages sent to the following URL(s) are not being received:
https://mumsandbabes.com/index.php/paypal/ipn/
If you do not recognize this URL, you may be using a service provider that is using IPN on your behalf. Please contact your service provider with the above information.
Once you or your service provider fix this problem, you or your service provider can resend the failed messages from the IPN History page. If this problem continues, PayPal may disable the IPN feature for your account.”
Thanks
Are you accepting payments via Paypal through either eBay or Amazon in addition to your Magento store Bubai?
If so, then that will be why you are experiencing problems with the default Magento IPN URL and you would have to implement a centralised IPN listener exactly as explained in my article above…
Hi Geoff, Great Article… do you have any update to this that would apply to Magento 2.1.9 ? Thank you!!
Hey Emily, thanks for stopping by and leaving a comment. I am very sorry, but at this present moment in time, I haven’t got a Magento 2 equivalent of this article but I shall try and schedule some time in soon to take a look at this on Magento 2 and write an updated post. I assume it is the same symptoms in Magento 2 of the IPN getting disabled due to multiple sales channels trying to talk to Magento causing sales to get stuck in ‘Pending Payment’ status?
Hi Geoff, Thanks for the super fast response! At first I thought it might be the same issue… but I figured it out. Looks like the boss changed what email was the primary at Paypal. 😉 So it seems we are good again now.
Great to hear that you figured it out and it was an easy fix Emily 🙂
Thank you 🙂
Thank you so much – clearly explained solution, worked straight away!
No problem Simon, glad it worked and you found it useful, thanks for stopping by.