You're specifying callback on your response, but you're missing a 'Host' header.
'Host' is required with HTTP 1.1.
Try this:
// Build the required acknowledgement message out of the notification just received
$req = 'cmd=_notify-validate'; // Add 'cmd=_notify-validate' to beginning of the acknowledgement
foreach($_POST as $key => $value) { // Loop through the notification NV pairs
$value = urlencode(stripslashes($value)); // Encode these values
$req.= "&$key=$value"; // Add the NV pairs to the acknowledgement
}
// Set up the acknowledgement request headers
$header = "POST /cgi-bin/webscr HTTP/1.1\r\n"; // HTTP POST request
$header.= "Content-Type: application/x-www-form-urlencoded\r\n";
$header.= "Host: www.sandbox.paypal.com\r\n";
$header.= "Content-Length: " . strlen($req) . "\r\n";
$header.= "Connection: Close\r\n\r\n";
// Open a socket for the acknowledgement request
$fp = fsockopen('ssl://www.sandbox.paypal.com', 443, $errno, $errstr, 30);
// Send the HTTP POST request back to PayPal for validation
var_dump(fputs($fp, $header . $req));
$res = stream_get_contents($fp, 1024);
Though I would strongly recommend you port over to cURL rather than fsockopen (like our example).
Whilst fsockopen has its uses, we find it's generally causes more problems because it's very specific in what you must send and how you must specifically read a response.
cURL under PHP is a lot more lenient in that, handling a lot of the background work for you.