PHP - IPN "INVALID" Response

adamwpe
Contributor
Contributor

I'm stuck on verifying an IPN call. 

 

Every time I use IPN simulator it returns with 'INVALID'.

 

I'm using the code from GITHUB (https://github.com/paypal/ipn-code-samples) (php version) and I've tried the examples on paypal's website. I've changed my account to UTF-8 and still no joy.

 

My website has TSL 1.2 and 1.3. Tried using 'cacert.pem' from my local system. Using sandbox mode, so using URL: https://ipnpb.sandbox.paypal.com/cgi-bin/webscr

 

I noticed that the git example encodes the '@' into '%40', so I added some code to convert it back to an at symbol and it didn't resolve the problem.

 

Inbound:

 

payment_type=echeck&payment_date=Sat%20Jun%2009%202018%2022%3A32%3A35%20GMT%2B0100%20%28GMT%20Summer%20Time%29&payment_status=Pending&pending_reason=echeck&address_status=confirmed&payer_status=verified&first_name=John&last_name=Smith&payer_email=EMAIL&payer_id=TESTBUYERID01&address_name=John%20Smith&address_country=United%20States&address_country_code=US&address_zip=95131&address_state=CA&address_city=San%20Jose&address_street=123%20any%20street&business=EMAIL&receiver_email=EMAIL&receiver_id=EMAIL&residence_country=US&item_name=something&item_number=AK-1234&quantity=1&shipping=3.04&tax=2.02&mc_currency=USD&mc_fee=0.44&mc_gross=12.34&mc_gross_1=12.34&txn_type=web_accept&txn_id=675143658&notify_version=2.1&custom=xyz123&invoice=abc1234&test_ipn=1&verify_sign=undefined 

Outbound:

 

cmd=_notify-validate&payment_type=echeck&payment_date=Sat%20Jun%2009%202018%2022%3A45%3A13%20GMT%2B0100%20%28GMT%20Summer%20Time%29&payment_status=Completed&address_status=confirmed&payer_status=verified&first_name=John&last_name=Smith&payer_email=EMAIL&payer_id=TESTBUYERID01&address_name=John%20Smith&address_country=United%20States&address_country_code=US&address_zip=95131&address_state=CA&address_city=San%20Jose&address_street=123%20any%20street&business=EMAIL&receiver_email=EMAIL&receiver_id=EMAIL&residence_country=US&item_name=something&item_number=AK-1234&quantity=1&shipping=3.04&tax=2.02&mc_currency=USD&mc_fee=0.44&mc_gross=12.34&mc_gross_1=12.34&txn_type=web_accept&txn_id=403853162&notify_version=2.1&custom=xyz123&invoice=abc1234&test_ipn=1&verify_sign=undefined

Response: INVALID

 

Is it something to do that the simulator handle encoding differently?? Do I need to do something with my account? I guess it's an encoding issue, but I've ran out of ideas.

 

If you need anymore info, please let me know.

 

 

Code is here:

 

 public function verifyIPN()
    {
        if ( ! count($_POST)) {
            throw new Exception("Missing POST Data");
        }

        $raw_post_data = file_get_contents('php://input');
        $raw_post_array = explode('&', $raw_post_data);
        $myPost = array();
        foreach ($raw_post_array as $keyval) {
            $keyval = explode('=', $keyval);
            if (count($keyval) == 2) {
                // Since we do not want the plus in the datetime string to be encoded to a space, we manually encode it.
                if ($keyval[0] === 'payment_date') {
                    if (substr_count($keyval[1], '+') === 1) {
                        $keyval[1] = str_replace('+', '%2B', $keyval[1]);
                    }
                }
                
                $myPost[$keyval[0]] = urldecode($keyval[1]);
            }
        }

        // Build the body of the verification post request, adding the _notify-validate command.
        $req = 'cmd=_notify-validate';
  
        if (function_exists('get_magic_quotes_gpc')) {
            $get_magic_quotes_exists = true;
        }

        foreach ($myPost as $key => $value) {
            
            if ($get_magic_quotes_exists == true && get_magic_quotes_gpc() == 1) {
               
                $value = rawurlencode(stripslashes($value));
            } else {
                $value = rawurlencode($value);
            }
// Added this to see if it helps $value = str_replace('%40', '@', $value); $req .= "&$key=$value"; } // Post the data back to PayPal, using curl. Throw exceptions if errors occur. $ch = curl_init($this->getPaypalUri()); curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1); curl_setopt($ch, CURLOPT_POST, 1); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_POSTFIELDS, $req); curl_setopt($ch, CURLOPT_SSLVERSION, 6); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 1); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2); $this->use_local_certs = true; // This is often required if the server is missing a global cert bundle, or is using an outdated one. if ($this->use_local_certs) { curl_setopt($ch, CURLOPT_CAINFO, __DIR__ . "/cert/cacert.pem"); } curl_setopt($ch, CURLOPT_FORBID_REUSE, 1); curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 30); curl_setopt($ch, CURLOPT_HTTPHEADER, array( 'User-Agent: PHP-IPN-Verification-Script', 'Connection: Close', )); $res = curl_exec($ch); if ( ! ($res)) { $errno = curl_errno($ch); $errstr = curl_error($ch); curl_close($ch); throw new Exception("cURL error: [$errno] $errstr"); } $info = curl_getinfo($ch); $http_code = $info['http_code']; if ($http_code != 200) { throw new Exception("PayPal responded with http code $http_code"); } curl_close($ch); file_put_contents("paypal-new.txt", "response: ".file_get_contents('php://input')); file_put_contents("paypal-data.txt", "response: ".$req); file_put_contents("paypal-result.txt", "response:: ".$res); // Check if PayPal verifies the IPN data, and if so, return true. if ($res == self::VALID) { return true; } else { return false; } }  

 

Login to Me Too
1 ACCEPTED SOLUTION

Accepted Solutions
Solved

MTS_Justin
Moderator
Moderator

Hello,

You currently can't use the IPN simulator to test the "VALID" / "INVALID" status for IPN's, as the data returned by the simulator tool is missing a required variable / value combination which is required for the validation process.  We're aware of this issue and working towards a solution, in the interim or as an alternative, use the method below.

Setup two sandbox accounts, a business and a buyer and setup your IPN URL on the business account. Conduct some payments between the two accounts and then attempt to complete verification via IPN postback on the data from those transactions.


Was my post helpful? If so, please give me a kudos!

View solution in original post

Login to Me Too
4 REPLIES 4
Solved

MTS_Justin
Moderator
Moderator

Hello,

You currently can't use the IPN simulator to test the "VALID" / "INVALID" status for IPN's, as the data returned by the simulator tool is missing a required variable / value combination which is required for the validation process.  We're aware of this issue and working towards a solution, in the interim or as an alternative, use the method below.

Setup two sandbox accounts, a business and a buyer and setup your IPN URL on the business account. Conduct some payments between the two accounts and then attempt to complete verification via IPN postback on the data from those transactions.


Was my post helpful? If so, please give me a kudos!
Login to Me Too

ooper
New Community Member
Do you know how many hours of debugging and googling for help you could have saved developers over the past several years if you would have just put a small note on the IPN Simulator page indicating not to use it to check for VALID or INVALID responses? I'm guessing tens of thousands of hours!! Put me down for 4 hours before I finally found your response in here.
Login to Me Too

MTS_Justin
Moderator
Moderator
** Correction made above

Was my post helpful? If so, please give me a kudos!
Login to Me Too

crckrmn77
New Community Member

Even 5 years later, your post would have been more helpful as a BIG WARNING on the IPN Simulator page!

Login to Me Too

Haven't Found your Answer?

It happens. Hit the "Login to Ask the community" button to create a question for the PayPal community.