简体   繁体   English

使用HTTPS的Paypal IPN验证回发

[英]Paypal IPN Verification Postback with HTTPS

According to new security requirements (2016, 2017 and 2018), it seems that HTTPS will be required for exchange between server and Paypal, during an "IPN". 根据新的安全要求(2016年,2017年和2018年),似乎在“IPN”期间服务器和Paypal之间的交换需要HTTPS。 This question is linked to this subject and also this . 这个问题与这个问题有关 ,也与此有关

How should we adapt this PHP IPN code? 我们应该如何调整这个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);

Would replacing the two occurences of www.paypal.com by https://www.paypal.com be enough? https://www.paypal.com取代www.paypal.com的两个出现就足够了吗?

Also, is the fact my shop website is not HTTPS a problem, will this connection be refused? 另外,我的商店网站不是HTTPS的问题,这个连接会被拒绝吗?


Here is part of the email received from Paypal: 以下是从Paypal收到的电子邮件的一部分:

在此输入图像描述


Edit (2018/06/22) , here is the actual IPN code, after applying the accepted answer code. 在应用接受的答案代码之后编辑(2018/06/22) ,这是实际的IPN代码。 Strangely, I still get: "IPN Verification postback to HTTPS. Update needed: YES". 奇怪的是,我仍然得到:“IPN验证回发到HTTPS。需要更新:是”。 So this means the following code is still not 100% compliant to HTTPS. 所以这意味着以下代码仍然不是100%兼容HTTPS。 Why? 为什么?

<?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);
}
?>

hostname

If OpenSSL support is installed, you may prefix the hostname with either ssl:// or tls:// to use an SSL or TLS client connection over TCP/IP to connect to the remote host. 如果安装了OpenSSL支持,则可以在hostname加上ssl://tls://以使用通过TCP / IP的SSL或TLS客户端连接来连接到远程主机。

http://www.php.net/fsockopen http://www.php.net/fsockopen

The port would also need to change to 443 . 该端口还需要更改为443 So: 所以:

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

https:// would not work because you're opening a socket , which is a low-level transport. https://不起作用,因为你打开一个套接字 ,这是一个低级传输。 HTTP is an application level protocol on top of that, which the socket doesn't know or care about. HTTP是一个应用程序级协议,套接字不知道或不关心。 At the socket level it's a TLS connection. 在套接字级别,它是TLS连接。

Also, is the fact my shop website is not HTTPS a problem, will this connection be refused? 另外,我的商店网站不是HTTPS的问题,这个连接会被拒绝吗?

What kind of connection a browser has to your server is irrelevant and nobody knows that. 浏览器与您的服务器之间的连接是无关紧要的,没人知道。 You're opening a socket from a PHP program to Paypal, you may as well be doing that directly from the command line without any "HTTP" connection involved at all. 您正在从PHP程序打开一个套接字到Paypal,您也可以直接从命令行执行此操作,而不涉及任何“HTTP”连接。

I would suggest you abandon fsocket in favour of curl. 我建议你放弃fsocket以支持curl。 Its a lot more reliable (I think). 它更可靠(我认为)。 Ive just updated my curl component within my ipn.php to be compliant with Paypals requirements of HTTP1/1 and TLS1.2 (sslversion=6) The code is 我刚刚更新了我的ipn.php中的curl组件,以符合HTTP1 / 1和TLS1.2的Paypals要求(sslversion = 6)代码是

//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);

It works fine 它工作正常

Further to my comments about Curl, Paypal developers have supplied several sets of source code for IPN. 继我对Curl的评论之后,Paypal开发人员为IPN提供了几套源代码。 They supply C++, Python, ASP, PHP, and a whole bunch more. 他们提供C ++,Python,ASP,PHP等等。 You will find them on github. 你会在github上找到它们。 All of the PHP solutions use Curl. 所有PHP解决方案都使用Curl。 Even though some of the uploads are a few years old they must have known that Paypal would update their full comms (for IPN) to HTTPS. 即使有些上传时间已经过去几年,但他们必须知道Paypal会将他们的完整通信(针对IPN)更新为HTTPS。 Even with some of the older packages, a simple adding of 1 line of code to set SSL version to 6 and the old codes are good to go for Paypals new requirements 即使使用了一些较旧的软件包,只需添加1行代码即可将SSL版本设置为6,旧代码可以用于Paypals的新要求

The link at https://github.com/paypal/ipn-code-samples is a compilation of codes in Python, Ruby, Perl, Asp and a few others including PHP. https://github.com/paypal/ipn-code-samples上的链接是Python,Ruby,Perl,Asp以及包括PHP在内的其他一些代码的汇编。 A direct link to the PHP component is at https://github.com/paypal/ipn-code-samples/tree/master/php This is the one I use because its already HTTP1/1 and TLS1.2 "ready" and therefore ticks all the boxes for Paypal's new security compliance. 有关PHP组件的直接链接, 访问https://github.com/paypal/ipn-code-samples/tree/master/php这是我使用的,因为它已经是HTTP1 / 1和TLS1.2“就绪”,因此,为Paypal的新安全合规性打勾。 There area few other github samples, some over 6 years old, but this is the most up to date 那里有很少的其他github样本,有些超过6年,但这是最新的

You should probably also change that HTTP/1.0 to HTTP/1.1 now, as per PayPal's latest requirements. 根据PayPal的最新要求,您现在也应该将HTTP/1.0更改为HTTP/1.1 So that's: 所以那是:

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

In addition to deceze's answer, PayPal's update now requires you to use ipnpb.paypal.com 除了deceze的答案,PayPal的更新现在要求你使用ipnpb.paypal.com

Try using this code instead. 请尝试使用此代码。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM