0
votes

I'm using the following class to process the IPN data: https://github.com/WadeShuler/PHP-PayPal-IPN (and it has been working fine for ages)

The last successfully processed payment was on September 28, the next IPN payment that came though on October 5 returned a response of INVALID, as has every payment since.

If I test in the IPN simulator, the message processes successfully. Sandbox or Live, the response is INVALID. I would have thought the Sandbox would have a facility where I can review why a message was rejected as INVALID, but that doesn't seem to be the case? Would certainly have been the easy way to see the rejection reason, am I missing something?

The link that brings you to Paypal from my site is:

https://www.sandbox.paypal.com/cgi-bin/webscr?cmd=_ext-enter&redirect_cmd=_xclick&[email protected]&item_name=QLD++%28Pacific+pines+secondary+Sat+25th+July+%29&item_number=FYD15000003&custom=0001000003&currency_code=AUD&amount=0.01&no_shipping=1&image_url=http://www.fydentry.com/img/follow-your-dreams-100.jpg&return=http://www.fydentry.com/entry-test.php&cancel_return=http://www.fydentry.com/entry-test.php&notify_url=http://www.fydentry.com/payback-test.php

The data posted back from Paypal is:

transaction_subject=0001000003&txn_type=web_accept&payment_date=07%3A05%3A07+Oct+15%2C+2015+PDT&last_name=buyer&residence_country=AU&pending_reason=multi_currency&item_name=QLD++%28Pacific+pines+secondary+Sat+25th+July+%29&payment_gross=&mc_currency=AUD&business=sales-facilitator%40fydentry.com&payment_type=instant&protection_eligibility=Ineligible&verify_sign=Acssfl2b2v1gxOK33TD2StcDhf-OAZxwix74kxFlSgpWMku6myuy.WFL&payer_status=verified&test_ipn=1&tax=0.00&payer_email=sales-buyer%40fydentry.com&txn_id=9BV63134E20871700&quantity=1&receiver_email=sales-facilitator%40fydentry.com&first_name=test&payer_id=FY3RYW98GNMXG&receiver_id=95FC3QCK53MHC&item_number=FYD15000003&handling_amount=0.00&payment_status=Pending&shipping=0.00&mc_gross=0.01&custom=0001000003&charset=windows-1252&notify_version=3.8&ipn_track_id=cfbd422d97d69

The response I send back to Paypal is:

cmd=_notify-validate&transaction_subject=0001000003&txn_type=web_accept&payment_date=07%3A05%3A07+Oct+15%2C+2015+PDT&last_name=buyer&residence_country=AU&pending_reason=multi_currency&item_name=QLD++%28Pacific+pines+secondary+Sat+25th+July+%29&payment_gross=&mc_currency=AUD&business=sales-facilitator%40fydentry.com&payment_type=instant&protection_eligibility=Ineligible&verify_sign=Acssfl2b2v1gxOK33TD2StcDhf-OAZxwix74kxFlSgpWMku6myuy.WFL&payer_status=verified&test_ipn=1&tax=0.00&payer_email=sales-buyer%40fydentry.com&txn_id=9BV63134E20871700&quantity=1&receiver_email=sales-facilitator%40fydentry.com&first_name=test&payer_id=FY3RYW98GNMXG&receiver_id=95FC3QCK53MHC&item_number=FYD15000003&handling_amount=0.00&payment_status=Pending&shipping=0.00&mc_gross=0.01&custom=0001000003&charset=windows-1252&notify_version=3.8&ipn_track_id=cfbd422d97d69

And the code in payback-test.php is:

<?php
  include_once("f_common.php");
  include_once("IpnListener.php");

  use wadeshuler\paypalipn\IpnListener;

  $listener = new IpnListener();
  $listener->use_sandbox = true;
  $dbh = open_db();

  $res = 'UNKNOWN';

  try {
    $listener->requirePostMethod();
    $verified = $listener->processIpn();
  } catch (Exception $e) {
    error_log($e->getMessage());
    exit(0);
  }


  if ($verified) {
      $res = "VERIFIED";
  } else {
      $res = "INVALID";
    }

  $stmt_debug = $dbh->prepare('INSERT INTO fyd_paypal_ipn (post_data, response_data, status, message_time) VALUES (:post_data, :response_data, :status, UTC_TIMESTAMP())');
  $stmt_debug->execute(array(':post_data' => $listener->rawPostData, ':response_data' => $listener->debug_response, ':status' => $res));
?>

Note that for the purpose of this exercise, I also modified the IpnListener class so that I can get a copy of the response for debugging purposes.

At the top of the file in the variable declarations, I made $rawPostData public, and added this variable:

public $debug_response;

And store the value right before we use it:

        $this->debug_response = $req;

        if ($this->use_curl) {
            $res = $this->curlPost($req);
        } else {
            $res = $this->fsockPost($req);
        }

I'm assuming something has changed on the Paypal side to stop this working in the first place, but I can't see what it is, particularly as my response appears to be correct (identical), and I can't find anything in the Sandbox side that helps me identify why it is being regarded as invalid? Unfortunately the debug code at the bottom where I track the IPN post data and response is new, so I don't have an older (working!) set of messages to compare the contents to.

2
Damb your website needs some serious css work.RRA Webteam
The css is worth every cent my wife paid for it :) Yeah, that's on the "to do" list somewhere.Peter Barton
Good luck and it's a great ideaRRA Webteam

2 Answers

0
votes

I've gotten to the bottom of it, it appears to be a certificate issue, combined with a script error.

My certificate file was out of date to the one currently in Wade's code. I spotted that and updated the certificate file yesterday. I've now verified that this was the root cause of my original failure.

However, while updating that, I also updated to the latest class - which was really just removing some deprecated code that I wasn't using and is no longer supported, but I missed one small change which broke things.

There's a line in the IpnListener class which sets the certificate location:

curl_setopt($ch, CURLOPT_CAINFO, dirname(dirname(__FILE__)) . '/cert/api_cert_chain.crt');

But the directory name ends up wrong on my server, and it can't find the certificate. The previous version of the class read:

curl_setopt($ch, CURLOPT_CAINFO, dirname(__FILE__) . '/cert/api_cert_chain.crt');

which worked. Now that I've changed it back, everything works again. Note that the domain I'm working from is set up in a sub-directory to my primary domain, which is possibly why the new code ends up pointing to the wrong place (one level above where I need it to be).

And I'm still confused as to why the IPN simulator worked, while the Sandbox and Live systems didn't.