Missing POST Data

Juanma1979
Contributor
Contributor

Hello community!

 

I'm having an issue here and I'm about to throw in the towle and use another system different from Paypal because I have lost more than a day trying to use the same code they provide:

 

 

<?php namespace Listener;

require('PaypalIPN.php');

use PaypalIPN;

$ipn = new PaypalIPN();

// Use the sandbox endpoint during testing.
$ipn->useSandbox();
$verified = $ipn->verifyIPN();
if ($verified) {
	$response = "verified";
	file_put_contents("test.txt", $response);
    /*
     * Process IPN
     * A list of variables is available here:
     * https://developer.paypal.com/webapps/developer/docs/classic/ipn/integration-guide/IPNandPDTVariables/
     */
} else {
	$response = "negativo2";
	file_put_contents("test.txt", $response);
}

// Reply with an empty 200 response to indicate to paypal the IPN was received correctly.
header("HTTP/1.1 200 OK");
?>

and the paypalipn.php

 

<?php

class PaypalIPN
{

    /**
     * @var bool $use_sandbox     Indicates if the sandbox endpoint is used.
     */
    private $use_sandbox = false;
    /**
     * @var bool $use_local_certs Indicates if the local certificates are used.
     */
    private $use_local_certs = true;

    /** Production Postback URL */
    const VERIFY_URI = 'https://ipnpb.paypal.com/cgi-bin/webscr';
    /** Sandbox Postback URL */
    const SANDBOX_VERIFY_URI = 'https://ipnpb.sandbox.paypal.com/cgi-bin/webscr';


    /** Response from PayPal indicating validation was successful */
    const VALID = 'VERIFIED';
    /** Response from PayPal indicating validation failed */
    const INVALID = 'INVALID';


    /**
     * Sets the IPN verification to sandbox mode (for use when testing,
     * should not be enabled in production).
     * @return void
     */
    public function useSandbox()
    {
        $this->use_sandbox = true;
    }

    /**
     * Sets curl to use php curl's built in certs (may be required in some
     * environments).
     * @return void
     */
    public function usePHPCerts()
    {
        $this->use_local_certs = false;
    }


    /**
     * Determine endpoint to post the verification data to.
     * @return string
     */
    public function getPaypalUri()
    {
        if ($this->use_sandbox) {
            return self::SANDBOX_VERIFY_URI;
        } else {
            return self::VERIFY_URI;
        }
    }


    /**
     * Verification Function
     * Sends the incoming post data back to PayPal using the cURL library.
     *
     * @return bool
     * @throws Exception
     */
    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';
        $get_magic_quotes_exists = false;
        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 = urlencode(stripslashes($value));
            } else {
                $value = urlencode($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 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('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);

        // Check if PayPal verifies the IPN data, and if so, return true.
        if ($res == self::VALID) {
            return true;
        } else {
            return false;
        }
    }
}
?>

and it's allways turning

 

[25-Feb-2018 16:46:49 UTC] PHP Fatal error:  Uncaught exception 'Exception' with message 'Missing POST Data' in /home2/laplatas/public_html/php/PaypalIPN.php:72
Stack trace:
#0 /home2/laplatas/public_html/php/zzz.php(11): PaypalIPN->verifyIPN()
#1 {main}
  thrown in /home2/laplatas/public_html/php/PaypalIPN.php on line 72
[25-Feb-2018 16:47:44 UTC] PHP Fatal error:  Uncaught exception 'Exception' with message 'Missing POST Data' in /home2/laplatas/public_html/php/PaypalIPN.php:72
Stack trace:
#0 /home2/laplatas/public_html/php/zzz.php(11): PaypalIPN->verifyIPN()
#1 {main}
  thrown in /home2/laplatas/public_html/php/PaypalIPN.php on line 72

The adress of IPN is:

https://www.laplata.surf/php/zzz.php (the first file I added to this post)

The button is sending the notify_url to:

https://www.laplata.surf/php/zzz.php (same first file)

The button is sending the user to:

https://www.laplata.surf/php/booking_correct.php (The thanks page)

 

My question is, it can be a problem of my server? or I'm setting wrong the URL's

 

 

Login to Me Too
3 REPLIES 3

MTS_Ciaran
Moderator
Moderator

Hey @Juanma1979

 

Ive moved the other post to archive just so you're aware..... 

 

on the issue itself, I tested it on the IPN simulator (https://developer.paypal.com/developer/ipnSimulator/) and it worked fine. What data is actually getting posted to the script.... can you try capture it earlier in the script and logging it? How are you triggering the script during your testing?

Login to Me Too

iRio
Contributor
Contributor

I had similar problem and it was in different response formats of ipn-simulator and real ipn notifications.

"IPN messages" I received was json-formatted string.

But actually my listener was received webhooks only (not IPN notifications). Check, if your listener path configured properly.

Login to Me Too

scfduffy
Contributor
Contributor

24 hours later ... I manage to solve my own problem with this...

 

Have you enabled IPN on the "sandbox" seller account?

 

Also important might be enabling it also on your live account.

 

You have to login either to the "sandbox lets pretend its paypal for real" website here or login to your actual paypal account through the main (not the developer) site at paypal.com. If your still testing, its the sanbox pretend site and obviously you want to replicate that on the live account either now if its convenient or conflicting with anything your already using live.

 

Okay so now you have the front page of a real or sandbox account.

 

On the top right corner just left of the logout button is a "cog" icon for settings.

 

Click on that then go "account settings" and a new page appears.

 

If you have a business account (which is essential for IPN), on the left hand menu there is a section "business profile". Within that is the "notifications" menu item.

 

Clicking that brings up a page which lets you enable or update IPN settings. Click it, then click "edit settings" on the page that appears, enable IPN and set the URL to the listener script (like "example_usage.php" from GIT) on your server.

 

Voila! See if it works now.

 

 

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.