在线模式下的 PayPal IPN 和 [SSL_ERROR_SYSCALL, errno 60]

PayPal IPN in LIVE mode and [SSL_ERROR_SYSCALL, errno 60]

我的问题在题名中有简要说明。我知道不仅我有同样的问题而且很多人都面临同样的问题。因此,在问我的问题之前,我使用了所有Whosebug的搜索,看了很多此类问题的答案。我尝试了此处提供的所有解决方案选项,但其中 none 帮助我解决了这个问题。

我使用一个简单的 php-脚本 (ipnlistener) 来接收 IPN,因此有关此交易的信息被输入我的数据库并发送邮件给买家 link下载文件。 在沙盒测试模式下一切正常——数据被输入数据库,邮件被发送给买家。我还检查了 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 选项中的证书检查被禁用(false),但我仍然收到错误“errno 60”

好的。我从这个 link 下载最新的当前证书文件:https://curl.haxx.se/docs/caextract.html and set to ENABLED on the certificate check in the CURL options according to this tutorial: 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: 另外,我的服务器配置完全符合 requirements:TLS v1.2,OpenSSL 1.0.1k

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

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

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

另外需要注意的是,在购买按钮<form action ="https://www.paypal.com/cgi-bin/webscr" method ="post"/>的形式中,link仍然必须与“www”一起使用,而不是“ipnpb”。

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

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