Recent PayPal IPN Issues: Postmortem
- Jacob@DPD
- December 8, 2010
- 1 Comment
Instant Payment Notifications (IPNs) are key to how DPD processes and validates PayPal orders. We receive an IPN for each successful purchase that triggers an email and activates the buyer’s purchase. To make sure we are receiving an actual IPN from PayPal to prevent unauthorized download, DPD contacts and verifies each IPN with PayPal. We either get a VALID
or INVALID
response.
In the past week or so we noticed a spike in failed IPN verifications from PayPal due to the continued rollout of PayPal’s new site. These sort of breakages aren’t uncommon with PayPal and they’re reasonably quick to address these types of issues. We normally don’t have to make any changes on our end before PayPal rolls out a fix. This time was different- There was no fix or even mention of the issue on PayPal’s site and failed IPN verifications were piling up.
So we dug into the logs and figured out what changed. Yesterday we rolled out changes to address the problem. We’re happy to report that we are now seeing a 100% success rate in validating IPNs.
If you are seeing new purchases with the “Error” status, this is most likely caused by an incompatable character encoding in your PayPal account profile having trouble with names and addresses with special characters in them. Please take a moment to enable UTF-8 (item #5) in your PayPal account. This fixes 99% of the remaining IPN validation errors.
What follows is a technical analysis of what happened and how we fixed it. We are posting this in hopes of helping other PayPal developers.
Geeky Programmer Stuff Below…
(Code samples are in PHP.)
The first problem is with generating the validation params. In every IPN validation sample out there, including on PayPal’s own site, you will see the following code to build the validation request:
$req = 'cmd=_notify-validate';
foreach($params as $key => $value) {
$value = urlencode(stripslashes($value));
$req.= "&$key=$value";
}
There are two things wrong with this snippet. First, PayPal sometimes sends three extra parameters. The most important of those is the cmd
parameter. This causes the validation command to switch from _notify-validate
to whatever PayPal includes in their IPN and PayPal responds with a 400 Bad Request
error. The CONTEXT
, myAllTextSubmitID
, and form_charset
parameters do not have any effect on validation. Adding a unset($params['cmd']);
before the foreach
fixes the problem.
Secondly, the call to stripslashes
is not needed. PayPal likes for you to send back the string exactly as they sent it to you, and they send strings with slashes included. Go figure.
The fixed validation request builder looks like:
$req = 'cmd=_notify-validate';
unset($params['cmd']);
foreach($params as $key => $value) {
$value = urlencode($value);
$req.= "&$key=$value";
}
by Mike Mooney
Aug 21st, 2011
Holy mackeral, thank you. The “cmd” parameter was indeed my problem, and that would have taken forever for my to resolve.