According to new security requirements (2016, 2017 and 2018), it seems that HTTPS will be required for exchange between server and Paypal, during an "IPN". This question is linked to this subject and also this.
How should we adapt this PHP IPN code?
$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);
Would replacing the two occurences of www.paypal.com
by https://www.paypal.com
be enough?
Also, is the fact my shop website is not HTTPS a problem, will this connection be refused?
Here is part of the email received from Paypal:
Edit (2018/06/22), here is the actual IPN code, after applying the accepted answer code. Strangely, I still get: "IPN Verification postback to HTTPS. Update needed: YES". So this means the following code is still not 100% compliant to HTTPS. Why?
<?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);
}
?>
hostname
If OpenSSL support is installed, you may prefix the
hostname
with eitherssl://
ortls://
to use an SSL or TLS client connection over TCP/IP to connect to the remote host.
The port would also need to change to 443
. So:
$header .= "Host: www.paypal.com\r\n";
...
$fp = fsockopen('ssl://www.paypal.com', 443, $errno, $errstr, 30);
...
fputs ($fp, $header . $req);
https://
would not work because you're opening a socket, which is a low-level transport. HTTP is an application level protocol on top of that, which the socket doesn't know or care about. At the socket level it's a TLS connection.
Also, is the fact my shop website is not HTTPS a problem, will this connection be refused?
What kind of connection a browser has to your server is irrelevant and nobody knows that. You're opening a socket from a PHP program to Paypal, you may as well be doing that directly from the command line without any "HTTP" connection involved at all.