Paypal IPN, возвращающий HTTP / 1.1 200 OK

Я тестирую интеграцию веб-сайта с Paypal, используя стандарт веб-платежей и переменные HTML.

Я написал простой PHP-скрипт для обработки уведомлений IPN.

Согласно документации Paypal, сервер Paypal отвечает простым ответом « VERIFIED » или « INVALID », как только вы отправляете полученные данные обратно в Paypal.

В моем обработчике я выполняю сравнение строк с учетом регистра для этих двух ключевых слов, если одно из этих известных ключевых слов не найдено, тогда оно рассматривается как ошибка.

<?php $fp = fsockopen ($socket_url, 80, $errno, $errstr, 10); if (!$fp){ // SOCKET ERROR return false; } else { fputs ($fp, $header . $req); $is_ok = false; while (!feof($fp)) { $res = fgets ($fp, 1024); if (strcmp("VERIFIED",$this->ipn_response)==0) { //do something ... } // if the IPN POST was 'INVALID' else if (strcmp ($res, "INVALID") == 0) { fclose ($fp); return false; } else { echo "Unknown response from Paypal: $res"; fclose ($fp); return false; } } fclose ($fp); return true; } ?> 

Мое сообщение об ошибке показывает, что я получаю ответ «HTTP / 1.1 200 OK» от Paypal.

Неизвестный ответ от Paypal: «HTTP / 1.1 200 OK»

Изменен ли API PayPal, или я делаю что-то неправильно?

Ответ PayPal находится в теле ответа HTTP. Вам нужно обработать заголовки HTTP, прежде чем вы сможете добраться до тела. Или, поочередно, просто продолжайте чтение строк, пока не найдете пустую строку, а следующая строка будет телом.

Извините, мой оригинальный ответ был очень плохо сформулирован 🙂

fgets читает только строка за строкой, первая строка – ответ HTTP. Ваш код никогда не дает возможности продолжить чтение, хотя, как вы «выходите из системы» после обработки первой строки.

Я был бы склонен заменить ваш цикл while чем-то вроде:

  while (!feof($fp)) { $res = trim(fgets($fp, 1024)); if (strcmp($res, "VERIFIED")==0) { //do something ... } else if (strcmp($res, "INVALID") == 0) { fclose ($fp); return false; } } 

Как сказал @Mike, вы должны прочитать все тело – в вашем случае вы просто проверяете, будет ли VERIFIED или INVALID в первых 1024 байтах ответа, что, вероятно, является заголовком.

Кстати, вам не нужно использовать fsockopen() , большинство людей делают это, потому что PayPal предоставляет пример, использующий его, чтобы он работал в старых установках. CURL или file_get_contents с помощью HTTP POST-контекста отлично справятся с заданием, вот пример, который я закодировал для PHP-структуры phunction :

 public static function PayPal($email, $status = 'Completed', $sandbox = false) { if (preg_match('~^(?:.+[.])?paypal[.]com$~', gethostbyaddr($_SERVER['REMOTE_ADDR'])) > 0) { $url = ($sandbox !== true) ? '' : '.sandbox'; $result = self::CURL('https://www' . $url . '.paypal.com/cgi-bin/webscr/', array_merge(array('cmd' => '_notify-validate'), $_POST), 'POST'); if ($result == 'VERIFIED') { $email = strlen($email) * strcasecmp($email, $_POST['receiver_email']); $status = strlen($status) * strcasecmp($status, $_POST['payment_status']); if (($email == 0) && ($status == 0)) { return true; } } } return false; }