简体   繁体   中英

PHP - PayPal IPN 301 moved permanently

I have a struggle with a PayPal IPN script written in PHP that I've used multiple times before, but now I am getting this error.

[07/31/2018 4:42 PM] - FAIL: IPN Validation Failed.
IPN POST Vars from Paypal:

    IPN Response from Paypal Server:
     HTTP/1.1 301 Moved Permanently
    Server: AkamaiGHost
    Content-Length: 0
    Location: https://www.paypal.com/smarthelp/article/how-do-i-check-and-update-my-web-browser-faq3893
    Date: Tue, 31 Jul 2018 23:42:14 GMT
    Connection: close
    Set-Cookie: akavpau_ppsd=1533081134~id=4fddfa711d2216538f54014af27277b0; Domain=www.paypal.com; Path=/; Secure; HttpOnly
    Strict-Transport-Security: max-age=63072000

I am using the script made by Micah Carrick. My edit looks like this. paypal.php

<?php
require('../inc/db.php');

define('LOG_FILE', 'ipn_results.log');
define('SSL_P_URL', 'https://www.paypal.com/cgi-bin/webscr');
define('SSL_SAND_URL','https://www.sandbox.paypal.com/cgi-bin/webscr');

class paypal_class {

   var $last_error;                 // holds the last error encountered

   var $ipn_log;                    // bool: log IPN results to text file?

   var $ipn_log_file;               // filename of the IPN log
   var $ipn_response;               // holds the IPN response from paypal   
   var $ipn_data = array();         // array contains the POST values for IPN

   var $fields = array();           // array holds the fields to submit to paypal

   function paypal_class() {

      // initialization constructor.  Called when a class is created.

      $this->paypal_url = 'https://www.paypal.com/cgi-bin/webscr';

      $this->last_error = '';

      $this->ipn_log_file = '/ipn_results.log';
      $this->ipn_log = true; 
      $this->ipn_response = '';

      // populate $fields array with a few default values.  See the PayPal
      // documentation for a list of fields and their data types. These default
      // values can be overwritten by the calling script.

      $this->add_field('rm','2');           // Return method = POST
      $this->add_field('cmd','_xclick'); 

   }

   function add_field($field, $value) {


      $this->fields["$field"] = $value;
   }

   function submit_paypal_post() {


     echo "<html>\n";
     echo "<head><title>Processing Payment...</title>";
     echo "<body onLoad=\"document.forms['paypal_form'].submit();\">\n";
     echo "<center><h2>Please wait, your order is being processed and you";
     echo " will be redirected to the paypal website.</h2></center>\n";
     echo "<form method=\"post\" name=\"paypal_form\" ";
     echo "action=\"".$this->paypal_url."\">\n";

     foreach ($this->fields as $name => $value) 
     {
         echo "<input type=\"hidden\" name=\"$name\" value=\"$value\"/>\n";
      }
     echo "<center><br/><br/>If you are not automatically redirected to ";
     echo "paypal within 5 seconds...<br/><br/>\n";
     echo "<input type=\"submit\" value=\"Click Here\"></center>\n";
     echo "</body></html>\n";

   }

   function validate_ipn() {
    mysqli_query($db, "UPDATE matches SET status = 3");
      // parse the paypal URL
      $url_parsed=parse_url($this->paypal_url);        

      // read post data from PayPal and add 'cmd'
    $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 = urlencode(stripslashes($value)); 
       } else {
            $value = urlencode($value);
       }
       $req .= "&$key=$value";
    }

      // open the connection to paypal
      $fp = fsockopen ('ssl://www.paypal.com', 443, $errno, $errstr, 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);       
         mysqli_query($db, "UPDATE matches SET status = 5");
         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
        mysqli_query($db, "UPDATE matches SET status = 8");
      }

      if (eregi("VERIFIED",$this->ipn_response)) {

         // Valid IPN transaction.
         $this->log_ipn_results(true);
         mysqli_query($db, "UPDATE matches SET status = 9");
         return true;       

      } else {

         // Invalid IPN transaction.  Check the log for details.
         $this->last_error = 'IPN Validation Failed.';
         $this->log_ipn_results(false);   
         mysqli_query($db, "UPDATE matches SET status = 6");
         return false;

      }

   }

   function log_ipn_results($success) {

      if (!$this->ipn_log) return;  // is logging turned off?

      // Timestamp
      $text = '['.date('m/d/Y g:i A').'] - '; 

      // Success or failure being logged?
      if ($success) $text .= "SUCCESS!\n";
      else $text .= 'FAIL: '.$this->last_error."\n";

      // Log the POST variables
      $text .= "IPN POST Vars from Paypal:\n";
      foreach ($this->ipn_data as $key=>$value) {
         $text .= "$key=$value, ";
      }

      // Log the response from the paypal server
      $text .= "\nIPN Response from Paypal Server:\n ".$this->ipn_response;

      // Write to log
      $fp=fopen($this->ipn_log_file,'a');
      fwrite($fp, $text . "\n\n"); 

      fclose($fp);  // close file
   }

   function dump_fields() {

      echo "<h3>paypal_class->dump_fields() Output:</h3>";
      echo "<table width=\"95%\" border=\"1\" cellpadding=\"2\" cellspacing=\"0\">
            <tr>
               <td bgcolor=\"black\"><b><font color=\"white\">Field Name</font></b></td>
               <td bgcolor=\"black\"><b><font color=\"white\">Value</font></b></td>
            </tr>"; 

      ksort($this->fields);
      foreach ($this->fields as $key => $value) {
         echo "<tr><td>$key</td><td>".urldecode($value)."&nbsp;</td></tr>";
      }

      echo "</table><br>"; 
   }
}     

paypal.class.php

<?php

    include_once('../inc/db.php');
    require ('../inc/steamauth.php');

    function filter($var)
        {
            return stripslashes(htmlspecialchars($var));
        }

    require_once('paypal.class.php');  // include the class file
    $p = new paypal_class; 
    $p->paypal_url = 'https://www.paypal.com/cgi-bin/webscr';

    $this_script = 'https://'.$_SERVER['HTTP_HOST'].$_SERVER['PHP_SELF'];


    if (empty($_GET['action'])) $_GET['action'] = 'process';  

    switch ($_GET['action']) {

       case 'process':

       $teamid = mysqli_real_escape_string($db, $_POST['teamid']);
       $type = mysqli_real_escape_string($db, $_POST['type']);

        switch($type) {

        case 'me':
            $cost = '0.01';
        break;

        case 'team':
            $cost = '0.01';
        break;

        }

          $p->add_field('business', 'MY EMAIL');
          $p->add_field('return', 'https://'.$_SERVER['HTTP_HOST']); //The success URL
          $p->add_field('custom', $teamid);
          $p->add_field('cancel_return', 'http://'.$_SERVER['HTTP_HOST']); // The "canceled" URL
          $p->add_field('notify_url', $this_script.'?action=ipn'); //The IPN URL, the URL pointing to THIS page.
          $p->add_field('item_number', filter($_POST['type']));
          $p->add_field('item_name', $_POST['type'] . '');
          $p->add_field('amount', $cost); // How ever much the VIP cost.

          $p->submit_paypal_post();

          break;

          case 'ipn':

          $db = mysqli_connect("localhost", "root", "*****", "***");

$problem =  mysqli_query($db, "UPDATE matches SET status = '1'");

          if ($p->validate_ipn()) {

              $complete = mysqli_query($db, "UPDATE matches SET status = '2'");

        }
          break;
     }     

    ?>

I've tried multiple fixes, found on StackOverflow. Mostly code edits, but I don't think that could be the problem. I've tried disabling my firewall to see if I eventually block out some PayPal IP's. But that's not the problem.

I've also tried both PHP 5.3.8 and PHP 7.2.7 but none of them works, I run this script on IIS 10 on my Windows 2016 VPS. I am also using an SSL Certificate for my website, but I've also tried without it.

I know that the IPN URL is correct since it does everything I want, except validating IPN. But the price is correct and the payment goes through. As you can see, the query $problem does even execute, but the query $complete doesn't, which is what I need.

Does anybody know what this might could be caused by?

Paypal Email from back in February:

Quote:" We also encourage you to speak with your web hosting company, e-commerce software provider or in-house web programmer/system administrator for further assistance in implementing these changes, if needed. Scheduled change dates provided in this email and on the TLS 1.2 and HTTP/1.1 Upgrade Microsite are subject to change. Please monitor our TLS 1.2 and HTTP/1.1 Upgrade Microsite for the most up-to-date information. Below are a few key points concerning security updates we will begin implementing after June 30, 2017 and we strongly recommend your systems be compatible to ensure your business is not disrupted: • The PayPal Sandbox, or testing environment, has been upgraded to allow only TLS 1.2 and HTTP/1.1 connections. • All production endpoints will be updated to accept only TLS 1.2 and HTTP/1.1 connections after June 30, 2017. Please note that if you haven't made the necessary upgrades to your systems to become compliant, your business will be unable to accept payments with PayPal until the required changes have been made. • A verification endpoint is available, which can be found at https://tlstest.paypal.com and has the latest security standards so customers can quickly check if their systems are ready to accept transactions after June 30, 2017. "

Quote: "IPN Verification Postback to HTTPS – Complete by June 30, 2017 Update Needed: Yes"

Micah didn't update his script in a while, but this one should work for you: https://github.com/xtuc/Paypal-ipn-SDK/blob/master/paypal.class.php

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM