【问题标题】:Paypal IPN Verification Postback with HTTPS使用 HTTPS 的 Paypal IPN 验证回发
【发布时间】:2017-01-20 19:22:46
【问题描述】:

根据新的安全要求(2016 年、2017 年和 2018 年),在“IPN”期间,服务器和 Paypal 之间的交换似乎需要 HTTPS。 This question is linked to this subjectthis

我们应该如何调整这个 PHP IPN 代码?

$header .= "POST /cgi-bin/webscr HTTP/1.0\r\n";
$header .= "Host: www.paypal.com:80\r\n";
$header .= "Content-Type: application/x-www-form-urlencoded\r\n";
$header .= "Content-Length: " . strlen($req) . "\r\n\r\n";

$fp = fsockopen ('www.paypal.com', 80, $errno, $errstr, 30);

$req = 'cmd=_notify-validate';

...

fputs ($fp, $header . $req);

www.paypal.com 的两次出现替换为https://www.paypal.com 就足够了吗?

另外,我的店铺网站不是HTTPS是不是有问题,这个连接会被拒绝吗?


这是从 Paypal 收到的电子邮件的一部分:


编辑 (2018/06/22),这是应用接受的答案代码后的实际 IPN 代码。奇怪的是,我仍然得到:“IPN 验证回发到 HTTPS。需要更新:是”。所以这意味着下面的代码仍然不是 100% 兼容 HTTPS。为什么?

<?php
$req = 'cmd=_notify-validate';
foreach ($_POST as $key => $value) {
  $value = trim(urlencode(stripslashes($value)));
  $req .= "&$key=$value";
}

$header .= "POST /cgi-bin/webscr HTTP/1.0\r\n";
$header .= "Host: www.paypal.com\r\n";
$header .= "Content-Type: application/x-www-form-urlencoded\r\n";
$header .= "Content-Length: " . strlen($req) . "\r\n\r\n";
$fp = fsockopen('tls://www.paypal.com', 443, $errno, $errstr, 30);

// variables
$item_name = $_POST['item_name'];
$business = $_POST['business'];
$item_number = $_POST['item_number'];
$payment_status = $_POST['payment_status'];
// and many more

if (!$fp)
{
  // HTTP ERROR
} else
{
  fputs ($fp, $header . $req);
  while (!feof($fp))
  {
    $res = fgets ($fp, 1024);
    if (strcmp ($res, "VERIFIED") == 0)
    {
        // send email to customer, etc.
    }
  }
  fclose ($fp);
}
?>

【问题讨论】:

标签: php paypal paypal-ipn


【解决方案1】:

hostname

如果安装了 OpenSSL 支持,您可以在 hostname 前加上 ssl://tls://,以使用 SSL 或 TLS 客户端连接通过 TCP/IP 连接到远程主机。

http://www.php.net/fsockopen

端口也需要更改为443。所以:

$header .= "Host: www.paypal.com\r\n";
...
$fp = fsockopen('ssl://www.paypal.com', 443, $errno, $errstr, 30);
...
fputs ($fp, $header . $req);

https:// 不起作用,因为您正在打开一个 socket,这是一个低级传输。 HTTP 是最重要的应用程序级协议,套接字不知道或不关心它。在套接字级别,它是一个 TLS 连接。

另外,我的店铺网站不是HTTPS是不是有问题,这个连接会被拒绝吗?

浏览器与您的服务器有什么样的连接是无关紧要的,没有人知道这一点。您正在打开一个从 PHP 程序到 Paypal 的套接字,您也可以直接从命令行执行此操作,而根本不涉及任何“HTTP”连接。

【讨论】:

  • 请注意,该端口必须为 443,并且服务器管理员可以将任何端口设置为安全端口。 (虽然我希望一些设置自定义安全端口的人在阅读 SO 答案时也会意识到这一点)
  • 是的,如果你被告知要使用 HTTPS 而没有进一步的细节,那么使用 443 以外的任何端口都是非常残忍的。:)
  • @Basj 只要Host: www.paypal.com:443,如果有的话。 Host: www.paypal.com 本身应该就可以了,完全省略标头也可以。
  • @Basj 我不知道ssltls 是否真的有区别,但TLS 是协议的当前版本,因此在命名和版本控制方面都应该是首选。
  • @Basj 浏览器与您的服务器有什么样的连接是无关紧要的,没有人知道这一点。您正在从 PHP 程序打开一个到 Paypal 的套接字,您也可以直接从命令行执行此操作,根本不涉及任何“HTTP”连接。
【解决方案2】:

除了 deceze 的回答,PayPal 的更新现在要求你使用ipnpb.paypal.com

尝试使用此代码。

$fp = fsockopen('ssl://ipnpb.paypal.com', "443", $err_num, $err_str, 60);

【讨论】:

  • 感谢@FluxCoder。您可以添加指向源的链接(Paypal 的更新),或者在此处引用它,以供将来参考?
【解决方案3】:

我建议你放弃 fsocket 以支持 curl。它更可靠(我认为)。我刚刚更新了我的 ipn.php 中的 curl 组件,以符合 HTTP1/1 和 TLS1.2 (sslversion=6) 的 Paypals 要求 代码是

//NOW SEND IT ALL BACK TO PAYPAL AS CONFIRMATION//
// USING CURL AS PHP FSOCKOPEN IS LESS RELIABLE //
$curl_result=$curl_err='';
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL,$paypal_url);
curl_setopt($ch, CURLOPT_CAINFO, "cacert.pem");
curl_setopt($ch, CURLOPT_SSLVERSION, 6);
curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $req);
curl_setopt($ch, CURLOPT_HTTPHEADER, array("Content-Type: application/x-www-form-urlencoded", "Content-Length: " . strlen($req)));
curl_setopt($ch, CURLOPT_HEADER, 0);   
curl_setopt($ch, CURLOPT_VERBOSE, 1);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 1);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
curl_setopt($ch, CURLOPT_FORBID_REUSE, 1);
curl_setopt($ch, CURLOPT_TIMEOUT, 30);
$curl_result = @curl_exec($ch);
$curl_err = curl_error($ch);
curl_close($ch);

效果很好

【讨论】:

  • 谢谢。为什么curlfsockopen 更可靠? (我之所以这么问,是因为我认为我的 IPN 每年都可以完美地处理数百次 fsockopen 调用)。
  • fsockopen 只是打开一个套接字,然后你就可以使用你的通信了。必须添加任何其他内容。另一方面,Curl 是 PHP 的 HTTP(和 HTTPS)通讯管理器。使用 HTTPS,Curl 是完整的包,这是 fsockopen 无法做到的。如果您的服务器上有 fsockopen 工作,那么可能会坚持使用它,但如果您更新服务器,预计会出现一些问题,另一端更新服务器或 HTTPS 成为要求,就像现在 Paypal 现在坚持 HTTP1 的情况一样/1 和 TLS 1.2,fsock 将不得不与之抗争
  • 您能否发布@gri2a 使用 curl 的 IPN php 的完整示例,同时显示$req = 'cmd=_notify-validate'; 和验证(使用 fsockopen 我使用了while (!feof($fp)) { $res = fgets ($fp, 1024); ?非常感谢您。
【解决方案4】:

除了我关于 Curl 的 cmets,Paypal 开发人员还为 IPN 提供了几组源代码。他们提供 C++、Python、ASP、PHP 等等。你会在 github 上找到它们。所有的 PHP 解决方案都使用 Curl。尽管有些上传是几年前的,但他们一定知道 Paypal 会将他们的完整通信(针对 IPN)更新为 HTTPS。 即使使用一些较旧的软件包,只需添加 1 行代码即可将 SSL 版本设置为 6,旧代码也适用于 Paypals 的新要求

【讨论】:

    【解决方案5】:

    https://github.com/paypal/ipn-code-samples 的链接是 Python、Ruby、Perl、Asp 和包括 PHP 在内的其他一些代码的汇编。 PHP 组件的直接链接位于https://github.com/paypal/ipn-code-samples/tree/master/php 这是我使用的那个,因为它已经“准备好”HTTP1/1 和 TLS1.2,因此勾选了 Paypal 新的安全合规性的所有框。 其他 github 样本很少,有的超过 6 年,但这是最新的

    【讨论】:

    • 欢迎来到 Stack Overflow!虽然链接是分享知识的好方法,但如果它们在未来被破坏,它们将无法真正回答问题。将回答问题的链接的基本内容添加到您的答案中。如果内容太复杂或太大而无法在此处放置,请描述所提出解决方案的总体思路。请记住始终保留指向原始解决方案网站的链接引用。见:How do I write a good answer?
    【解决方案6】:

    根据 PayPal 的最新要求,您现在可能还应该将 HTTP/1.0 更改为 HTTP/1.1。那就是:

    $header .= "POST /cgi-bin/webscr HTTP/1.1\r\n";
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-01-04
      • 1970-01-01
      • 1970-01-01
      • 2016-05-27
      • 2017-01-10
      • 2012-03-09
      • 2015-05-27
      • 2015-08-14
      相关资源
      最近更新 更多