Paypal IPN возвращает HTTP / 1.1 200 OK - PullRequest
4 голосов
/ 04 августа 2010

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

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

Согласно документации Paypal , сервер Paypal отвечает простым ответом " ПРОВЕРЕНО " или " НЕВЕРНЫЙ ", когда вы отправляете обратно полученные данные на 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, или я что-то не так делаю?

Ответы [ 3 ]

2 голосов
/ 04 августа 2010

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

1 голос
/ 04 августа 2010

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

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

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;
}
1 голос
/ 04 августа 2010

Извините, мой первоначальный ответ был действительно плохо сформулирован :) 1001 *

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