Скрипт Paypal IPN, проблема с feof и fgets

У меня были проблемы с моим скриптом прослушивания Paypal IPN в течение нескольких дней. Для тех из вас, кто не знаком с системой Paypal IPN, в основном Paypal отправляет ваш скрипт с сообщением о транзакции, которое вы отправляете обратно с добавлением пары битов. Если Paypal получит правильный ответ, он ответит «ПРОВЕРЕНО», а если нет, то скажет «НЕДЕЙСТВИТЕЛЬНО».

Сначала я подумал, что проблема, с которой я столкнулся, связана с командой «fsockopen»: $fp=fsockopen('ssl://sandbox.paypal.com', 443, $errno, $errstr, 30); Однако, сократив весь мой код почти до этой строки, кажется, что все нормально. Проблема возникает с командами feof и fgets. Скрипт просто зависает, и я не знаю почему. По сути, я скопировал код, предложенный на веб-сайте Paypal IPN Listener, поэтому я предполагал, что он будет работать! Если бы вы могли помочь мне понять, почему feof или fgets вызывают его зависание, ваша помощь была бы очень признательна.

Вот полный скрипт:

$postback = 'cmd=_notify-validate'; //doesn't matter what these include for now
$header='abc';

//Script has been activated, create debug
$filename = 'debug/debug1_script.txt';
$filehandle=fopen($filename, 'w');
fwrite($filehandle,$postback);
fclose($filehandle);


$fp = fsockopen ('ssl://www.sandbox.paypal.com', 443, $errno, $errstr, 30);//open the connection

//no connection, create debug file
if(!$fp){
    $filename = 'debug/debug2_fpfail.txt';
    $filehandle=fopen($filename, 'w');
    fwrite($filehandle, $errstr.'('.$errno.')');
    fclose($filehandle);
    die();
}


//post data back
fputs($fp, $header . $postback);

//create debug file
$filename = 'debug/debug3_postback.txt';
$filehandle=fopen($filename, 'w');
fwrite($filehandle, $header.$postback);
fclose($filehandle);


//script hangs with either of the two following lines included
while(!feof($fp)){
    $res=fgets($fp,1024);
}

Спасибо заранее!


person user1070084    schedule 29.11.2011    source источник
comment
Если вы используете код точно так, как он указан на этой страница кроме замены имен хостов, это работает?   -  person Francis Avila    schedule 29.11.2011


Ответы (4)


Итак, я думаю, что нашел решение, которое вместо использования

while(!feof())

и

fgets()

комбо, я использовал это:

$res=stream_get_contents($fp, 1024);

Сработало с первого раза! Теперь я могу продолжать свою жизнь.

person user1070084    schedule 30.11.2011

Всем, кто прибывает сюда через Google, не забудьте указать «Соединение: Закрыть» в своих заголовках! В противном случае хост будет держать соединение открытым, пока не истечет время ожидания!

person devios1    schedule 16.03.2012

Если у кого-то еще есть такая же проблема, CURL, похоже, является рекомендуемым выбором для IPN от PayPal.

Ознакомьтесь с образцом кода на Github по адресу: https://github.com/paypal/ipn-code-samples/blob/master/paypal_ipn.php

person mattauckland    schedule 11.04.2014

Обратное соединение с PayPal из вашего $fp сокета должно быть HTTP POST. feof() зависает, потому что PayPal никогда не слышит полный HTTP-запрос, поэтому он никогда ничего не отправляет обратно — он просто продолжает слушать, пока вы не сдадитесь.

Вам нужны дополнительные материалы (готовые переменные $header и $req) в примере кода на эта страница PayPal IPN.

Я бы переписал это, чтобы использовать CURL, если вы можете, вместо необработанных сокетов, поэтому вам не нужно форматировать полный http-запрос и читать необработанный http-ответ.

person Francis Avila    schedule 29.11.2011
comment
Большое спасибо за помощь. Я сделал, как вы говорите, и включил следующий заголовок: $header = POST /cgi-bin/webscr HTTP/1.1\r\n; $header .= Хост: ssl://www.sandbox.paypal.com\r\n; $header .= Content-Type: application/x-www-form-urlencoded\r\n; $header .= Длина содержимого: . strlen($постбэк) . \r\n\r\n; Насколько я вижу, это нормально, но происходит то же самое. С помощью while(!feof($fp)) или fgets($fp, 1024) он просто зависает. Еще раз спасибо за ваш ответ! - person user1070084; 29.11.2011
comment
Это неправильное форматирование заголовка HOST. Попробуйте использовать http 1.0, как в примере PayPal. - person Francis Avila; 29.11.2011
comment
Еще раз спасибо и извините, если вы получили несколько глупых вопросов... Я вернулся и скопировал заголовок Paypal прямо с их веб-сайта: $header .= POST /cgi-bin/webscr HTTP/1.0\r\ н; $header .= Content-Type: application/x-www-form-urlencoded\r\n; $header .= Длина содержимого: . strlen($постбэк) . \r\n\r\n; с указателем файла: $fp = fsockopen ('ssl://www.sandbox.paypal.com', 443, $errno, $errstr, 30); Но я все еще получаю тот же ответ с помощью while(!feof()) или fgets(). Есть ли какая-то дополнительная информация, которую я могу включить в заголовок? - person user1070084; 30.11.2011
comment
Похоже, на этой странице больше нет примера кода. - person Syntax Error; 17.06.2014
comment
Я также пошел проверить справочную кодовую страницу Paypal, и, похоже, она была перемещена/удалена. Может быть, теперь просто CURL? Интересно узнать, получилось ли у вас это сработать? - person David; 05.07.2016