实时模式下的 PayPal IPN 和 [SSL_ERROR_SYSCALL, errno 60]

Posted

技术标签:

【中文标题】实时模式下的 PayPal IPN 和 [SSL_ERROR_SYSCALL, errno 60]【英文标题】:PayPal IPN in LIVE mode and [SSL_ERROR_SYSCALL, errno 60] 【发布时间】:2018-06-23 10:50:56 【问题描述】:

问题标题中简要说明了我的问题。我知道不仅我有同样的问题,而且很多人都面临它。因此,在问我的问题之前,我使用了对所有 *** 的搜索,并阅读了很多此类问题的答案。我尝试了这里提供的所有解决方案选项,但没有一个能帮助我解决这个问题。

我使用一个简单的 php 脚本 (ipnlistener) 来接收 IPN,因此有关此交易的信息被输入到我的数据库中,并向买家发送邮件,其中包含下载文件的链接。 在沙盒测试模式下一切正常 - 数据输入数据库并将邮件发送给买家。我还检查了 IPN 模拟器,也没有收到任何错误 - 它发出消息“IPN 已发送并且握手已验证。”

但是,一旦我切换到 LIVE 模式,我就会在日志中看到以下条目:“SSL_ERROR_SYSCALL, errno 60”并且在此脚本执行停止,直到下一次尝试发送 IPN,这也以同样的错误结束。

下面是我使用的 ipnlistener.php 的代码:

<?php
$raw_post_data  = file_get_contents('php://input');
$raw_post_array = explode('&', $raw_post_data);
$paypal_post    = array();

foreach ($raw_post_array as $keyval) 
    $keyval = explode ('=', $keyval);
    if (count($keyval) == 2) 
        $paypal_post[$keyval[0]] = urldecode($keyval[1]);
    


//extract vars
extract($paypal_post, EXTR_OVERWRITE);

// build request
$req = 'cmd=' . urlencode('_notify-validate');
$ipn_vars = 'cmd=' . urlencode('_notify-validate');
foreach ($paypal_post as $k => $v) 
    $v = urlencode($v);
    $req .= "&$k=$v";


// sort array keys (only after building $req var which will be used to send curl to paypal)
ksort($paypal_post);
foreach ($paypal_post as $k => $v) 
    $ipn_vars .= "\n$k=" . urldecode($v);


// paypal mode
$paypal_mode = 1;

// sandbox on/off
if($paypal_mode == 1) 
    $paypal_url = 'https://www.paypal.com/cgi-bin/webscr';
    //for IPN-simulator:
    //$paypal_url = 'https://ipnpb.paypal.com/cgi-bin/webscr';  

// else is production site
else 
    $paypal_url = 'https://www.sandbox.paypal.com/cgi-bin/webscr';
    //for IPN-simulator:
    //$paypal_url = 'https://ipnpb.sandbox.paypal.com/cgi-bin/webscr';


$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $paypal_url);
curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $req);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
curl_setopt($ch, CURLOPT_FORBID_REUSE, 1);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 30);
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Connection: Close'));
$res = curl_exec($ch);

//Check if any error occured
if(curl_errno($ch)) 
    error_log("Got " . curl_error($ch); . " when processing IPN data");

else 
    if (strcmp (trim($res), "VERIFIED") == 0) 
        //here is the code for adding information to the database, downloading the link for downloading the file and sending the mail to the buyer.
    
    else if (strcmp (trim($res), "INVALID") == 0) 
        //here is the code to send mail to the seller, if the transaction has not been verified
    

?>

如您所见,在此代码中,CURL 选项中的证书检查是 DISABLED (false),但我仍然收到错误“errno 60”

好的。我从这个链接下载了最新的当前证书文件:https://curl.haxx.se/docs/caextract.html 并根据本教程在 CURL 选项中的证书检查上设置为启用:http://unitstep.net/blog/2009/05/05/using-curl-in-php-to-access-https-ssltls-protected-sites/,更改这些行:

curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 1);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);

并添加证书文件的完整路径(当然,我指出了放置它的文件的真实路径):

curl_setopt($ch, CURLOPT_CAINFO, getcwd() . '/cert/cacert.pem');

但我仍然不断收到相同的错误:SSL_ERROR_SYSCALL, errno 60

请告诉我 - 我的代码有什么问题?我的错误是什么?我还能如何解决我的问题?

PS:另外,我的服务器配置完全符合要求:TLS v1.2,OpenSSL 1.0.1k

【问题讨论】:

确认你的 cacert.pem 路径是 true 路径;当前工作目录 (getcwd()) 可能会更改。例如,通过$_SERVER['DOCUMENT_ROOT'] . "/cert/cacert.pem" 提供路径可能会更好,即使当前工作目录发生更改,它也将成立。 我不知道这是否会有所作为,但在我的一个 Paypal 实例中,我在 VERIFY 行上方也有一行 curl_setopt($ch, CURLOPT_SSLVERSION, 6);。这有帮助吗? @Martin 谢谢你的回答!当然,我指出了文件的真实路径,他把它放在了这个表格里:/pub/home/cert/cacert.pem。我也试过这个方法$_SERVER['DOCUMENT_ROOT'],并把curl_setopt($ch, CURLOPT_SSLVERSION, 6)这一行添加到CURL选项中,但错误依然存在。 @Martin 奇怪的是,即使我在 curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); 这几行的 CURL 选项中关闭证书检查,我仍然会收到相同的错误:errno 60。天呐?? 一些谷歌搜索似乎表明这是您安装 OpenSSL 的某种问题;而不是使用 Paypal 或您的 PHP 设置。我已经更新了你的标签。 【参考方案1】:

好的。有一段时间我不得不从这个问题上分心,因为我正在从事另一个项目。但我找到了解决方案。一切都变得很简单,它根本不在证书中,也不在 cURL 设置中。

最近似乎 PayPal 更改了在 LIVE 模式下检查 IPN 的链接,现在在参数 $paypal_url = 'https://www.paypal.com/cgi-bin/webscr'; 中链接不是以“www”开头,而是以“ ipnpb”。也就是说,代码中的这一行应该是这样的:$paypal_url = 'https://ipnpb.paypal.com/cgi-bin/webscr'; 之前此链接仅用于 IPN-Simulator,现在用于 LIVE 模式!

对于 Sandbox,也希望使用 https://ipnpb.sandbox.paypal.com/cgi-bin/webscr 而不是 https://www.sandbox.paypal.com/cgi-bin/webscr,但目前它在两个版本中都可以使用。

另外需要注意的是,在购买按钮&lt;form action ="https://www.paypal.com/cgi-bin/webscr" method ="post"/&gt;的形式中,链接还是必须和“www”一起使用,不能和“ipnpb”一起使用>”。

当我更正代码 ipn.php 脚本中的链接时 - 这一切都对我有用!

更多详细信息请点击此处:https://www.paypal-notice.com/en/IPN-Verification-Postback-to-HTTPS/

【讨论】:

以上是关于实时模式下的 PayPal IPN 和 [SSL_ERROR_SYSCALL, errno 60]的主要内容,如果未能解决你的问题,请参考以下文章

Paypal Sandbox IPN: 14077410:sslroutines:ssl23_get_server_hello:sslv3 警报握手失败

PayPal IPN OPENSSL 错误:14077410:SSL 例程:SSL23_GET_SERVER_HELLO:sslv3 警报握手失败

使用 fsockopen 的警报握手失败 paypal IPN 集成

PayPal IPN 侦听器 - SSL 证书握手失败

Paypal 自适应支付和 IPN

PayPal IPN 是不是需要 SSL 证书?