根据新的安全要求(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收到的电子邮件的一部分:
编辑(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
答案 0 :(得分:3)
hostname
如果安装了OpenSSL支持,您可以在
hostname
前加ssl://
或tls://
作为前缀,以通过TCP / IP使用SSL或TLS客户端连接来连接到远程主机。
该端口还需要更改为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);