Search code examples
phpcodeigniterpaypalpaypal-ipn

Is this Codeigniter Paypal IPN Library & Controller safe enough from any malicious behaviour?


I am simply asking if this code below is safe enough from unathorized fake IPN requests and etc? Would appreciate if you point what could be improved or if its good the way it is since it works perfectly already. Thank you a lot for spending your time to answer to my question.

Paypal_Lib.php file | Validate_IPN() function

    function validate_ipn()
    {
        // parse the paypal URL
        $url_parsed = parse_url($this->paypal_url);       

        // generate the post string from the _POST vars aswell as load the
        // _POST vars into an arry so we can play with them from the calling
        // script.
        $post_string = '';   
        if (isset($_POST))
        {
            foreach ($_POST as $field=>$value)
            {       // str_replace("\n", "\r\n", $value)
                    // put line feeds back to CR+LF as that's how PayPal sends them out
                    // otherwise multi-line data will be rejected as INVALID

                $value = str_replace("\n", "\r\n", $value);
                $this->ipn_data[$field] = $value;
                $post_string .= $field.'='.urlencode(stripslashes($value)).'&';

            }
        }

$post_string.="cmd=_notify-validate"; // append ipn command

        // open the connection to paypal
        $fp = fsockopen('ssl://www.sandbox.paypal.com',"443",$err_num,$err_str,30); 
        if(!$fp)
        {
            // could not open the connection.  If loggin is on, the error message
            // will be in the log.
            $this->last_error = "fsockopen error no. $errnum: $errstr";
            $this->log_ipn_results(false);       
            return false;
        } 
        else
        { 
            // Post the data back to paypal
            fputs($fp, "POST $url_parsed[path] HTTP/1.1\r\n"); 
            fputs($fp, "Host: $url_parsed[host]\r\n"); 
            fputs($fp, "Content-type: application/x-www-form-urlencoded\r\n"); 
            fputs($fp, "Content-length: ".strlen($post_string)."\r\n"); 
            fputs($fp, "Connection: close\r\n\r\n"); 
            fputs($fp, $post_string . "\r\n\r\n"); 

            // loop through the response from the server and append to variable
            while(!feof($fp))
                $this->ipn_response .= fgets($fp, 1024); 

            fclose($fp); // close connection
        }

        if (eregi("VERIFIED",$this->ipn_response))
        {
            // Valid IPN transaction.
            $this->log_ipn_results(true);
            return true;         
        } 
        else 
        {
            // Invalid IPN transaction.  Check the log for details.
            $this->last_error = 'IPN Validation Failed.';
            $this->log_ipn_results(false);  
            return false;
        }
    }

**

Paypal.php controller function to handle the IPN. It checks if its validated and if the amount is 197 USD in this example.

    function ipn()
    {
        // Payment has been received and IPN is verified.  This is where you
        // update your database to activate or process the order, or setup
        // the database with the user's order details, email an administrator,
        // etc. You can access a slew of information via the ipn_data() array.

        // Check the paypal documentation for specifics on what information
        // is available in the IPN POST variables.  Basically, all the POST vars
        // which paypal sends, which we send back for validation, are now stored
        // in the ipn_data() array.

        // For this example, we'll just email ourselves ALL the data.

// IT'S ONLY TEST DATA BELOW!
        $item = '507';
        $payment_currency = $_POST['mc_gross'];
        $payment_currency2 = '197';
        if (($payment_currency === $payment_currency2) && ($this->paypal_lib->validate_ipn())) {
    $this->db->query( 'update users set users_money=users_money+212345, users_credits=users_credits+2123 WHERE users_id=' . $item );
    }

Solution

  • It's safe

    In Paypal_Lib.php file validate_ipn() method will send the POST data(received to ipn method) to paypal server

    if (isset($_POST))
        {
            foreach ($_POST as $field=>$value)
            {       // str_replace("\n", "\r\n", $value)
                    // put line feeds back to CR+LF as that's how PayPal sends them out
                    // otherwise multi-line data will be rejected as INVALID
    
                $value = str_replace("\n", "\r\n", $value);
                $this->ipn_data[$field] = $value;
                $post_string .= $field.'='.urlencode(stripslashes($value)).'&';
    
            }
        }
    

    to verify whether that POST request came from paypal or other server.

    Now Paypal will responds to verification request with VERIFIED or not. If it's verified means payment had made in paypal server So you can proceed to next steps.

    If it don't respond with VERIFIED for validation request, it means that's the fake request(come other than paypal server).