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

时间:2018-01-14 17:34:05

标签: curl ssl-certificate paypal-ipn php-openssl

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

我使用一个简单的php脚本(ipnlistener)来接收IPN,因此有关此事务的信息被输入到我的数据库中,并通过链接下载文件发送给买家。 在Sandbox测试模式下一切正常 - 数据输入数据库,邮件发送给买方。我还检查了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选项中设置为ENABLED: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,错误60

请告诉我 - 我的代码出了什么问题?我的错误是什么以及如何解决我的问题?

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

1 个答案:

答案 0 :(得分:0)

好。有一段时间我不得不分心这个问题,因为我参与了另一个项目。但我找到了解决方案。一切都变得简单,而且证书中根本没有,也没有在cURL设置中。

从最近的时间开始,PayPal已经更改了在LIVE模式下检查IPN的链接,现在参数$paypal_url = 'https://www.paypal.com/cgi-bin/webscr';链接不以&#34; www &#开头34;但是&#34; ipnpb &#34;。也就是说,代码中的这一行应该是这样的:$paypal_url = 'https://ipnpb.paypal.com/cgi-bin/webscr'; 以前,此链接仅用于IPN模拟器,但现在它用于实时模式!

对于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"/>的形式,该链接仍必须与&#34; www &#34; ,而不是&#34; ipnpb &#34;。

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

更多详细信息,请访问:https://www.paypal-notice.com/en/IPN-Verification-Postback-to-HTTPS/