使用HTTPS的Paypal IPN验证回发

时间:2016-09-13 08:49:04

标签: php paypal paypal-ipn

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

我们应该如何调整此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的两次出现替换为<?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); } ?> 是否足够?

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

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

enter image description here

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

@echo off
SET username=abc
SET password=xyz@1234
SET servername=192.168.1.40

echo user %username%> telnetcmd.dat
echo %password%>> telnetcmd.dat
echo adbd^& >> telnetcmd.dat
echo exit>> telnetcmd.dat
telnet %servername% < telnetcmd.dat

del telnetcmd.dat

6 个答案:

答案 0 :(得分:3)

  

hostname

     

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

     

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://无效,因为您正在打开套接字,这是一种低级传输。 HTTP是一种应用程序级协议,套接字不知道或不关心它。在套接字级别,它是 TLS 连接。

  

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

浏览器与您的服务器之间的连接是无关紧要的,没人知道。您正在从PHP程序向PayPal打开套接字,您也可以直接从命令行执行此操作而不需要任何&#34; HTTP&#34;连接都涉及到。

答案 1 :(得分:2)

我建议你放弃fsocket以支持curl。它更可靠(我认为)。我刚刚更新了我的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);

工作正常

答案 2 :(得分:2)

除了我对Curl的评论之外,Paypal开发人员还为IPN提供了几套源代码。他们提供C ++,Python,ASP,PHP等等。你会在github上找到它们。所有PHP解决方案都使用Curl。即使有些上传时间已经过去几年,但他们必须知道Paypal会将他们的完整通信(针对IPN)更新为HTTPS。 即使使用了一些较旧的软件包,只需添加1行代码即可将SSL版本设置为6,旧代码可用于支付Paypals的新要求

答案 3 :(得分:2)

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年,但这是最新的

答案 4 :(得分:1)

您可能还应该按照PayPal的最新要求,将HTTP/1.0更改为HTTP/1.1。就是这样:

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

答案 5 :(得分:0)

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

请尝试使用此代码。

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