8

如何验证对我指定的 notifyURL 的 PayPal IPN POST 请求确实来自 PayPal?

我并不是说将数据与我之前发送的数据进行比较,而是如何验证此 PayPal 请求来自的服务器/IP 地址确实是有效的?

4

6 回答 6

15

IPN 协议由三个步骤组成:

  1. PayPal 向您的 IPN 侦听器发送一条消息,通知您该事件
  2. 您的听众将完整的未更改消息发送回 PayPal;消息必须以相同的顺序包含相同的字段,并以与原始消息相同的方式进行编码
  3. PayPal 会返回一个单词,如果消息来自 PayPal,则为 VERIFIED,如果与最初发送的消息有任何差异,则为 INVALID

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

于 2011-01-31T06:37:51.483 回答
12

这是我发现的最简单的方法,也是根据 PayPal 建议的。我使用 http_build_query() 从从 paypal 发送到网站的帖子中构造 url。Paypal 文档声明您应该将其发回以进行验证,这就是我们对 file_get_contents 所做的事情。您会注意到我使用 strstr 检查是否存在“已验证”一词,因此我们继续执行该函数,如果不存在则返回 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;
于 2011-07-15T16:25:20.580 回答
3

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');
}
于 2015-05-06T15:59:24.327 回答
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
}
于 2015-10-26T19:56:54.037 回答
1

如果我没记错的话,PayPal 使用静态 IP 进行 IPN 呼叫。

因此,检查正确的 IP 应该可以工作。

或者,您可以使用gethostbyaddror gethostbyname

于 2011-01-31T12:33:47.557 回答
-1

这就是我使用的:

if (preg_match('~^(?:.+[.])?paypal[.]com$~', gethostbyaddr($_SERVER['REMOTE_ADDR'])) > 0)
{
    // came from paypal.com (unless your server got r00ted)
}
于 2011-02-14T02:14:36.567 回答