简体   繁体   中英

PayPal IPN Listener failing on postback

First time here and I am completely stumped after days of trying to resolve the problem. Here's the background to this problem...

I have a PayPal IPN listener script. In fact I have two versions of it because the first didn't work so I tried another but that didn't work either. Both of the IPN listener scripts I obtained from PayPal...

paypal_notifyA.php

From... developer . paypal . com /docs/classic/ipn/gs_IPN/

The script stops at...

fputs($fp, $header . $req);

<?php require_once("../lib/PHPMailer/PHPMailerAutoload.php"); ?>

<?php
// Paypal IPN

// Send an empty HTTP 200 OK response to acknowledge receipt of the notification 
header('HTTP/1.1 200 OK');

// Assign payment notification values to local variables
$invoiceID          = $_POST['invoice'];
$paymentStatus      = $_POST['payment_status'];
$productID          = $_POST['item_number'];
$paymentAmount      = $_POST['mc_gross'];
$paymentCurrency    = $_POST['mc_currency'];
$txnID              = $_POST['txn_id'];
$receiverEmail      = $_POST['receiver_email'];
$payerEmail         = $_POST['payer_email'];
$response           = $_POST['response'];

// Build the required acknowledgement message out of the notification just received  
$req = 'cmd=_notify-validate';                  // Add 'cmd=_notify-validate' to beginning of the acknowledgement
foreach ($_POST as $key => $value) {            // Loop through the notification NV pairs
    $value = urlencode(stripslashes($value));   // Encode these values
    $req  .= "&$key=$value";                    // Add the NV pairs to the acknowledgement
}

// Set up the acknowledgement request headers
$header  = "POST /cgi-bin/webscr HTTP/1.1\r\n";                    // HTTP POST request
$header .= "Content-Type: application/x-www-form-urlencoded\r\n";
$header .= "Content-Length: " . strlen($req) . "\r\n\r\n";

// The PayPal IPN Simulator fails on the line below...
// Open a socket for the acknowledgement request
$fp = fsockopen('tls://www.sandbox.paypal.com', 443, $errno, $errstr, 30);  // paypal.com (LIVE) - sandbox.paypal.com (TEST)

// Send the HTTP POST request back to PayPal for validation
fputs($fp, $header . $req);

while (!feof($fp)) {                        // While not EOF
    $res = fgets($fp, 1024);                // Get the acknowledgement response
    if (strcmp ($res, "VERIFIED") == 0) {   // Response contains VERIFIED - process notification

        $testStage = "Got past Verified!";
        require_once("../emails/ipn_test.php");

        // DO MY OWN VERIFIED STUFF HERE

// ***** INVALID RESPONSE ***** 
} else if (strcmp ($res, "INVALID") == 0) { // Response contains INVALID - reject notification

    // DO MY OWN INVALID STUFF HERE
}

}
fclose($fp);  // Close the file
?>

paypal_notifyB.php

From... github . com /paypal/ipn-code-samples/blob/master/paypal_ipn.php

The script stops at...

$res = curl_exec($ch);

And reports the following in the error log...

Can't connect to PayPal to validate IPN message: error:14077410:SSL routines:SSL23_GET_SERVER_HELLO:sslv3 alert handshake failure

<?php require_once("../lib/PHPMailer/PHPMailerAutoload.php"); ?>

<?php
// Paypal Notify

// Start session
session_start();

// CONFIG: Enable debug mode. This means we'll log requests into 'ipn.log' in the same directory.
// Especially useful if you encounter network errors or other intermittent problems with IPN (validation).
// Set this to 0 once you go live or don't require logging.
define("DEBUG", 1);

// Set to 0 once you're ready to go live
define("USE_SANDBOX", 1);

define("LOG_FILE", "./ipn.log");


// Read POST data
// reading posted data directly from $_POST causes serialization
// issues with array data in POST. Reading raw POST data from input stream instead.
$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)
        $myPost[$keyval[0]] = urldecode($keyval[1]);
}

// read the post from PayPal system 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";
}

// Post IPN data back to PayPal to validate the IPN data is genuine
// Without this step anyone can fake IPN data
if(USE_SANDBOX == true) {
    $paypal_url = "https://www.sandbox.paypal.com/cgi-bin/webscr";
    $livetestEmail = "info-facilitator@flysoftware.com";
} else {
    $paypal_url = "https://www.paypal.com/cgi-bin/webscr";
    $livetestEmail = "info@flysoftware.com";
}

$ch = curl_init($paypal_url);
if ($ch == FALSE) {
    return FALSE;
}

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_SSL_VERIFYPEER, 1);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
curl_setopt($ch, CURLOPT_FORBID_REUSE, 1);

if(DEBUG == true) {
    curl_setopt($ch, CURLOPT_HEADER, 1);
    curl_setopt($ch, CURLINFO_HEADER_OUT, 1);
}

// Set TCP timeout to 30 seconds
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 30);
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Connection: Close'));

// CONFIG: Please download 'cacert.pem' from "http://curl.haxx.se/docs/caextract.html" and set the directory path
// of the certificate as shown below. Ensure the file is readable by the webserver.
// This is mandatory for some environments.

$cert = __DIR__ . "./cacert.pem";
curl_setopt($ch, CURLOPT_CAINFO, $cert);

// PayPal IPN Simulator fails on the line below and reports following error...
// Can't connect to PayPal to validate IPN message: error:14077410:SSL routines:SSL23_GET_SERVER_HELLO:sslv3 alert handshake failure
$res = curl_exec($ch);

if (curl_errno($ch) != 0) { // cURL error

    if(DEBUG == true) { 
        error_log(date('[Y-m-d H:i e] '). "Can't connect to PayPal to validate IPN message: " . curl_error($ch) . PHP_EOL, 3, LOG_FILE);
    }
    curl_close($ch);
    exit;
} else {
        // Log the entire HTTP response if debug is switched on.
        if(DEBUG == true) {
            error_log(date('[Y-m-d H:i e] '). "HTTP request of validation request:". curl_getinfo($ch, CURLINFO_HEADER_OUT) ." for IPN payload: $req" . PHP_EOL, 3, LOG_FILE);
            error_log(date('[Y-m-d H:i e] '). "HTTP response of validation request: $res" . PHP_EOL, 3, LOG_FILE);
        }
        curl_close($ch);
}

// Inspect IPN validation result and act accordingly
// Split response headers and payload, a better way for strcmp

$tokens = explode("\r\n\r\n", trim($res));
$res = trim(end($tokens));

if (strcmp ($res, "VERIFIED") == 0) { // Response is verified

    $testStage = "Got past Verified!";
    require_once("../emails/ipn_test.php");

    // DO MY OWN VERIFIED STUFF HERE

// ***** INVALID RESPONSE ***** 
} else if (strcmp ($res, "INVALID") == 0) { // Response contains INVALID - reject notification

    // DO MY OWN INVALID STUFF HERE

    if(DEBUG == true) {
        error_log(date('[Y-m-d H:i e] '). "Invalid IPN: $req" . PHP_EOL, 3, LOG_FILE);
    }

}
?>

When I try both scripts in the PayPal IPN Simulator, both report...

IPN was sent and the handshake was verified.

However, both scripts don't communicate back to PayPal and the "If VERIFIED" condition is never reached. It is therefore irrelevant there is not yet backend code after this condition - just trying to get the listener to work for now!

I have talked to my web host and they stated they disabled SSLv3 in the hope that was causing the problem. It made no difference and both scripts continue to fail at the point where they communicate back to PayPal. My host claims it is not "their" fault and that it is a problem with PayPal. This is despite pointing my host in the direction of relevant SO threads (that I can't post because do not have the reputation).

stackoverflow . com / questions/35030756/paypal-ipn-openssl-error14077410ssl-routinesssl23-get-server-hellosslv3-aler

stackoverflow . com / questions/34955346/paypal-ipn-handshake-issues

And this page from PayPal...

paypal-knowledge . com / infocenter/index?page=content&id=FAQ1766&expand=true&locale=en_US

I hope someone can help me resolve this or at least confirm it is "my" scripts at fault or the server is at fault, because I'm getting nowhere!!

PS I'm very new to PHP.

Faced same problem but here using Java servlet to catch IPN notification. After receive lots of parameters, response status 200 OK is sent back. Then, a new HTTP request is formed keeping all parameters as received at first step and adding an extra command 'cmd' -- things look quite similar to your php code.

As I see, fsockopen tries to connect to 'tls://www.sandbox.paypal.com', whereas I am using ' https://www.sandbox.paypal.com/cgi-bin/webscr '. You may follow this tutorial which was quite helpful http://www.geekality.net/2011/05/28/php-tutorial-paypal-instant-payment-notification-ipn

VERIFIED was received finally. One thing to note that, due to https, there were a certificate expire warning for which I had to disable ignore cookies in Apache http client.

Hope this post eases some of your pain. 

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