2011-01-31 2 views
8

Как я могу проверить, что запрос PayNal IPN POST на мой указанный notifyURL действительно поступает из PayPal?Подтвердить, что IPN-вызов осуществляется через PayPal?

Я не имею в виду сравнение данных с тем, что я отправил ранее, но как я могу проверить, что сервер/IP-адрес, из которого поступает этот запрос PayPal, действительно является допустимым?

+0

методы, перечисленные здесь для проверки, где IPN отправлять обратно пришли не являются абсолютно надежными, и на самом деле не сделает вас гораздо более безопасным, чем у вас уже есть. Внедрите лучшие практики, рекомендованные PayPal. Если бы они были небезопасными, у PayPal были бы большие проблемы, учитывая, что их весь бренд построен на доверии пользователей. – Brad

ответ

16

Протокол IPN состоит из трех этапов:

  1. PayPal отправляет IPN слушатель сообщений, уведомляющие о событии
  2. Прослушиватель посылает полную неизмененного сообщения на PayPal; сообщение должно содержать те же поля в том же порядке и кодируются в же, как и исходное сообщение
  3. PayPal отправляет одно слово назад, которое либо Verified если сообщение возникла с PayPal или недействительна, если есть любое несоответствие с тем, что было первоначально послал

https://cms.paypal.com/us/cgi-bin/?cmd=_render-content&content_ID=developer/e_howto_admin_IPNIntro

+0

спасибо, я знаю об этом, и я делаю это точно ... но как я могу быть вдвойне уверен, что его PayPal, который вызывает мой прослушиватель IPN? (шаг 1, который вы скопировали)? – siliconpi

+0

Есть ли причина, по которой вам нужно быть? В конце концов, весь пункт трехэтапного процесса, описанный выше, заключается в том, что кто-то еще не может позвонить вашему слушателю IPN и получить сообщение VERIFIED ... – Amber

+0

Я не на 100% знаком с атаками типа «человек в середине», но я думаю, что более сильная проверка, что запрос поступает из PayPal, будет более осмотрительным ... – siliconpi

1

Если я правильно помню, й e PayPal использует статический IP-адрес для своих IPN-вызовов.

Таким образом, проверка правильности IP должна работать.

В качестве альтернативы, вы можете использовать gethostbyaddr или gethostbyname.

+0

+1 для напоминания мне, что он может быть статичным. Прошло много лет с тех пор, как я программировал IPN. –

-1

Это what I use:

if (preg_match('~^(?:.+[.])?paypal[.]com$~', gethostbyaddr($_SERVER['REMOTE_ADDR'])) > 0) 
{ 
    // came from paypal.com (unless your server got r00ted) 
} 
+0

Что делать, если я купил домен blablablarandomstuffpaypal.com? не соответствует ли это регулярному выражению? ''. '' перед 'paypal' должен исправить это. – aularon

+0

@aularon: Он не будет соответствовать из-за '^'. –

+0

Совершенно верно! мой плохой :) – aularon

11

Это самый простой способ, который я нашел, чтобы сделать это, также согласно предлагает PayPal. Я использую http_build_query() для создания URL-адреса из сообщения, которое было отправлено на сайт из PayPal. В документах Paypal указано, что вы должны отправить это обратно для проверки, и это то, что мы делаем с файлом_get_contents. Вы заметите, что я использую strstr, чтобы проверить, если слово «ВЕРИФИЦИРОВАННОЕ» присутствуют и поэтому мы продолжаем в функции, если не мы возвращаем ложь ...

$verify_url = 'https://www.sandbox.paypal.com/cgi-bin/webscr?cmd=_notify-validate&' . http_build_query($_POST); 

if(!strstr(file_get_contents($verify_url), 'VERIFIED')) return false; 
+1

На самом деле, paypal говорит, что вы должны ПОЧТАТЬ тело обратно им: https://developer.paypal.com/webapps/developer/docs/classic/ipn/integration-guide/IPNIntro/ – acidtv

+0

HTTP-заголовок User-Agent требуется прямо сейчас! –

2

https://gist.github.com/mrded/a596b0d005e84bc27bad

function paypal_is_transaction_valid($data) { 
    $context = stream_context_create(array(
    'http' => array(
     'header' => "Content-type: application/x-www-form-urlencoded\r\n", 
     'method' => 'POST', 
     'content' => http_build_query($data), 
    ), 
)); 
    $content = file_get_contents('https://www.sandbox.paypal.com/cgi-bin/webscr?cmd=_notify-validate', false, $context); 

    return (bool) strstr($content, 'VERIFIED'); 
} 
3

HTTP заголовок User-Agent требуется прямо сейчас!

$vrf = file_get_contents('https://www.paypal.com/cgi-bin/webscr?cmd=_notify-validate', false, stream_context_create(array(
    'http' => array(
     'header' => "Content-type: application/x-www-form-urlencoded\r\nUser-Agent: MyAPP 1.0\r\n", 
     'method' => 'POST', 
     'content' => http_build_query($_POST) 
    ) 
))); 

if ($vrf == 'VERIFIED') { 
    // Check that the payment_status is Completed 
    // Check that txn_id has not been previously processed 
    // Check that receiver_email is your Primary PayPal email 
    // Check that payment_amount/payment_currency are correct 
    // process payment 
} 
+0

Отлично! это сработало для меня –

+0

Если я тестирую песочницу, будет ли URL-адрес www.sandbox.paypal.com аутентифицироваться или www.paypal.com? – Volomike