【问题标题】:Paypal ipn return 403 in the last month with php codePaypal ipn在上个月返回403,带有php代码
【发布时间】:2021-10-16 04:56:26
【问题描述】:

上个月我的 patpal 集成返回错误,我认为 paypal 的政策发生了一些变化。这是错误:

[08/12/2021 11:59 AM] - FAIL: IPN Validation Failed.
IPN Response from Paypal Server:
 HTTP/1.1 403 Forbidden
Content-Type: text/html
Content-Length: 38
Connection: close
DC: phx-origin-www-1.paypal.com
Strict-Transport-Security: max-age=31536000; includeSubDomains

<html><body>403 Forbidde</body></html>

它从上个月开始。 这是我使用的 api url:

https://api-3t.paypal.com/nvp

这是贝宝类

<?php

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 __construct() {

        // initialization constructor.  Called when class is created.

        $this->paypal_url = 'https://ipnpb.paypal.com/cgi-bin/webscr';
        $this->api_url = 'https://api-3t.paypal.com/nvp';

        $this->last_error = '';

        $this->ipn_log_file = 'ipn_log.txt';
        $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 defaul
        // values can be overwritten by the calling script.
        // Return method = POST
        $this->add_field('cmd', '_cart');
    }

    function add_field($field, $value) {

        // adds a key=>value pair to the fields array, which is what will be 
        // sent to paypal as POST variables.  If the value is already in the 
        // array, it will be overwritten.

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

    function submit_paypal_post($type = false) {

        // this function actually generates an entire HTML page consisting of
        // a form with hidden elements which is submitted to paypal via the 
        // BODY element's onLoad attribute.  We do this so that you can validate
        // any POST vars from you custom form before submitting to paypal.  So 
        // basically, you'll have your own form which is submitted to your script
        // to validate the data, which in turn calls this function to create
        // another hidden form and submit to paypal.
        // The user will briefly see a message on the screen that reads:
        // "Please wait, your order is being processed..." and then immediately
        // is redirected to paypal.

        $form = array();
        $output = "<html>\n";
        $output .= "<head><title>טוען תשלום...</title></head>\n";
        $output .= "<body onLoad=\"document.form.submit();\">\n";
        $output .= "<form method=\"post\" name=\"form\" action=\"" . $this->paypal_url . "\">\n";

        foreach ($this->fields as $name => $value) {
            $output .= "<input type=\"hidden\" name=\"$name\" value=\"$value\">";
            $form[] = array(
                "name" => $name,
                "value" => $value,
                "type" => "hidden"
            );
        }

        $output .= "</form>\n";
        $output .= "</body></html>\n";

        if ($type)
            return array("form" => $form, "action" => $this->paypal_url);

        return $output;
    }

    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 = '';
        foreach ($_POST as $field => $value) {
            $this->ipn_data[$field] = $value;
            $post_string .= $field . '=' . urlencode($value) . '&';
        }
        $post_string.="cmd=_notify-validate"; // append ipn command
        // open the connection to paypal
        $fp = fsockopen("ssl://" . $url_parsed["host"], 443, $err_num, $err_str, 30);
        if (!$fp) {
            $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 (preg_match("/VERIFIED/i", $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;
        }
    }

    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() {

        // Used for debugging, this function will output all the field/value pairs
        // that are currently defined in the instance of the class using the
        // add_field() function.

        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>";
    }

    public function pay($username, $password, $signature, $email, $amount, $note = "Instant Payment") {
        $version = urlencode("51.0");
        $api = $this->api_url;

        $type = urlencode("EmailAddress");
        $currency = urlencode("USD");
        $subject = urlencode("Instant Paypal Payment");
        
        $string = "&EMAILSUBJECT=" . $subject . "&RECEIVERTYPE=" . $type . "&CURRENCYCODE=" . $currency;
        $string .= "&L_EMAIL0=" . urlencode($email) . "&L_Amt0=" . urlencode($amount) . "&L_NOTE0=" . urlencode($note);

        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $api);
        curl_setopt($ch, CURLOPT_VERBOSE, 1);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLOPT_POST, 1);

        $request = "METHOD=MassPay&VERSION=" . $version . "&PWD=" . $password . "&USER=" . $username . "&SIGNATURE=" . $signature . "$string";

        curl_setopt($ch, CURLOPT_POSTFIELDS, $request);
        $httpResponse = curl_exec($ch);
        if (!$httpResponse) {
            exit("MassPay failed: " . curl_error($ch) . '(' . curl_errno($ch) . ')');
        }

        $httpResponseArray = explode("&", $httpResponse);
        $httpParsedResponse = array();
        foreach ($httpResponseArray as $i => $value) {
            $tempArray = explode("=", $value);
            if (sizeof($tempArray) > 1) {
                $httpParsedResponse[$tempArray[0]] = $tempArray[1];
            }
        }

        if ((0 == sizeof($httpParsedResponse)) || !array_key_exists('ACK', $httpParsedResponse)) {
            exit("Invalid HTTP Response for POST request($request) to " . $api);
        }

        return $httpParsedResponse;
    }

}

我能做什么? 我试图在谷歌搜索任何政策更新,但没有运气。 tnx

【问题讨论】:

    标签: php api paypal


    【解决方案1】:

    IPN Integration Guide 中所述,请确保在请求标头中包含 User-Agent: 字段,其值是任何 > 7 个字符左右的字符串

    对于实时 IPN 验证,您还应该使用域 ipnpb.paypal.com 而不是 www.paypal.com

    【讨论】:

    • Tnx 为您解答,但未解决问题
    • 你传递了哪些标题,以及如何传递?
    猜你喜欢
    • 2020-03-16
    • 2012-02-02
    • 2018-10-29
    • 2016-01-14
    • 2017-12-15
    • 1970-01-01
    • 2013-09-06
    • 2012-07-23
    • 2011-10-26
    相关资源
    最近更新 更多