2011-01-31 10 views
8

W jaki sposób mogę sprawdzić, czy żądanie PayPal PON IPN do mojego określonego adresu rozliczeniowego rzeczywiście pochodzi z systemu PayPal?Sprawdź, czy połączenie IPN pochodzi z systemu PayPal?

Nie mam na myśli porównywania danych z tym, co wcześniej wysłałem, ale jak mogę sprawdzić, czy adres serwera/IP, z którego pochodzi ten wniosek PayPal, jest rzeczywiście ważny?

+0

metod wymienionych tutaj walidacji gdzie IPN zakładać z powrotem pochodzi nie są niezawodne, a tak naprawdę nie sprawi, że znacznie bardziej bezpieczny niż już jesteś. Wprowadź najlepsze praktyki zalecane przez PayPal. Gdyby nie były bezpieczne, PayPal miałby większe problemy, biorąc pod uwagę, że ich marka jest zbudowana na zaufaniu użytkowników. – Brad

Odpowiedz

16

Protokół IPN składa się z trzech etapach:

  1. PayPal wysyła słuchacz IPN do komunikat, który informuje nas o wydarzeniu
  2. Twój słuchacz wysyła kompletny niezmienioną wiadomość z powrotem do systemu PayPal; komunikat musi zawierać te same pola w tej samej kolejności i być zakodowane w taki sam sposób jak w oryginalnej wiadomości
  3. PayPal wysyła jednego słowa z powrotem, co albo jest weryfikowana komunikat pochodzi z PayPal lub nieważny, jeśli istnieje rozbieżność z tym, co było pierwotnie wysłane

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

+0

dziękuję, jestem tego świadomy i robię to dokładnie ... ale jak mogę być podwójnie pewny, że jego PayPal, który wywołuje mój słuchacz IPN? (krok 1, który skopiowałeś)? – siliconpi

+0

Czy jest jakiś powód, dla którego powinieneś być? W końcu, cały opis procesu 3-etapowego opisanego powyżej jest taki, że niemożliwe jest, aby ktoś inny zadzwonił do twojego słuchacza IPN i nadal otrzymał odpowiedź WERYFIKOWANĄ ... – Amber

+0

Nie jestem w 100% zaznajomiony z atakami typu "człowiek w środku", ale myślę, że silniejsza weryfikacja, że ​​żądanie pochodzi z systemu PayPal, byłaby bardziej rozważna ... – siliconpi

1

Jeśli dobrze pamiętam, th e PayPal używa statycznego adresu IP dla swoich połączeń IPN.

Sprawdzanie prawidłowego adresu IP powinno działać.

Alternatywnie można skorzystać z gethostbyaddr lub gethostbyname.

+0

+1 za przypomnienie, że może to być statyczne. minęły lata, odkąd zrobiłem programowanie IPN. –

-1

To what I use:

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

Co się stanie, jeśli kupię domenę blablablarandomstuffpaypal.com? nie pasuje do tego wyrażenia regularnego? a '[.]' before 'paypal' powinno to naprawić. – aularon

+0

@aularon: Nie pasowałoby do '^'. –

+0

Całkowicie rację! moje złe :) – aularon

11

Jest to najprostszy sposób znalazłem to zrobić, jak również za sugeruje PayPal. Używam http_build_query() do skonstruowania adresu URL z posta, który został wysłany na stronę z paypal. Dokumenty Paypal oświadczają, że powinieneś wysłać to z powrotem do weryfikacji i to właśnie robimy z file_get_contents. można zauważyć, że używam strstr aby sprawdzić, czy słowo „zweryfikowana” jest obecne, a więc w dalszym ciągu w funkcji, jeśli nie my return false ...

$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

W rzeczywistości, paypal mówi, że powinieneś POST CIAŁA z powrotem do nich: https://developer.paypal.com/webapps/developer/docs/classic/ipn/integration-guide/IPNIntro/ – acidtv

+0

Nagłówek HTTP User-Agent wymagany teraz! –

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 nagłówek User-Agent wymagany teraz!

$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

Świetnie! to zadziałało dla mnie –

+0

Jeśli testuję z piaskownicą, czy adres URL to www.sandbox.paypal.com, aby uwierzytelnić się z, lub www.paypal.com? – Volomike