Why does tlstest.paypal.com work from browser but not from my PHP code (useful for Paypal IPN)?

梦想与她 提交于 2019-12-01 14:51:58

It works on my side by changing tls:// to ssl:// which makes absolutely no sense to me, but this is also why using fsockopen is a too low level library to just do HTTP exchanges with it (you should use a proper HTTP client library) and at the same time not configurable enough regarding TLS stuff.

With $fp = fsockopen('tls://tlstest.paypal.com', 443, $errno, $errstr, 30); I get :

HTTP/1.1 426 Unknown
Server: AkamaiGHost
Mime-Version: 1.0
Content-Type: text/html
Content-Length: 267
Expires: Fri, 22 Jun 2018 19:49:46 GMT
Date: Fri, 22 Jun 2018 19:49:46 GMT
Connection: keep-alive
Upgrade: TLS/1.2

<HTML><HEAD>
<TITLE>Access Denied</TITLE>
</HEAD><BODY>
<H1>Access Denied</H1>

You don't have permission to access "http&#58;&#47;&#47;tlstest&#46;paypal&#46;com&#47;" on this server.<P>
Reference&#32;&#35;18&#46;8024a17&#46;1529696986&#46;1fc51318
</BODY>
</HTML>

but with $fp = fsockopen('ssl://tlstest.paypal.com', 443, $errno, $errstr, 30); I get:

HTTP/1.1 200 OK
Content-Type: text/html
Content-Length: 20
Date: Fri, 22 Jun 2018 20:05:35 GMT
Connection: keep-alive

And then it hangs, probably because it is a keep-alive connection and the buffer is smaller than 1024 so that you do not get the following body content. Which is probably "PayPal_Connection_OK", as it exactly matches the length displayed in Content-Length. This again shows that you should use an HTTP client library instead of trying to (badly) reimplement HTTP on top of fsockopen.

For completeness, here is a working code (full credit to PatrickMevzek's answer):

<?php
$req = '';
$header = "POST / HTTP/1.1\r\n";
$header .= "Host: tlstest.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('ssl://tlstest.paypal.com', 443, $errno, $errstr, 3);

if (!$fp) {
    echo $errno;
    echo $errstr;
} else {
    fputs($fp, $header);
    while (!feof($fp))
    {
        $res = fgets($fp, 21);   // 21 because length of "PayPal_Connection_OK"
        echo $res;
    }
    fclose($fp);
}
?>

Here is the answer from server:

# php -f test.php
HTTP/1.1 200 OK
Content-Type: text/html
Content-Length: 20
Date: Fri, 22 Jun 2018 20:19:56 GMT
Connection: keep-alive

PayPal_Connection_OK
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!