So i'm using the example code that is provided by Paypal in order to properly communicate and validate incoming IPN messages. Using the provided Paypal developer tool "IPN Simulator" i am able to confirm that my IPN listener code is able to successfully handshake with the Paypal servers, however when it is time to resend the information for validation i am only able to successfully connect with non-sandbox version of paypal (which returns invalid anyways because everything is set up for communication with sandbox paypal). When i try to connect to the sandbox version i receive an http error meaning i am unable to connect to the servers.
I think i have isolated the problem to this line of code:
$fh = fsockopen ('ssl://www.sandbox.paypal.com', 443, $errno, $errstr, 30); //HTTP error
The code below demonstrates my testing to see which urls could work:
$fh = fsockopen ('ssl://www.paypal.com', 443, $errno, $errstr, 30);//works, returns invalid
$fh = fsockopen ('tls://www.paypal.com', 443, $errno, $errstr, 30);//works, returns invalid
$fh = fsockopen ('www.paypal.com', 443, $errno, $errstr, 30);//Does not work but does not throw HTTP Error (does not return Verified or Invalid either)
$fh = fsockopen ('ssl://www.sandbox.paypal.com', 443, $errno, $errstr, 30);//HTTP error
$fh = fsockopen ('tls://www.sandbox.paypal.com', 443, $errno, $errstr, 30);//HTTP error
$fh = fsockopen ('www.sandbox.paypal.com', 443, $errno, $errstr, 30);//Does not work but does not throw HTTP Error (does not return Verified or Invalid either)
Here is my IPN listener code currently on my servers (Extra code for logging IPN data in my databases not shown for simplicity; also here is the link that this code is based off of: https://developer.paypal.com/docs/classic/ipn/gs_IPN/):
<?php
// STEP 1 - acknowledge PayPal's notification
header('HTTP/1.1 200 OK');
// STEP 2 - create the response we need to send back to PayPal for them to confirm that it's legit
$resp = 'cmd=_notify-validate';
foreach ($_POST as $parm => $var)
{
$var = urlencode(stripslashes($var));
$resp .= "&$parm=$var";
}
// STEP 3 - Get the HTTP header into a variable and send back the data we received so that PayPal can confirm it's genuine
$httphead = "POST /cgi-bin/webscr HTTP/1.1\r\n";
$httphead .= "Content-Type: application/x-www-form-urlencoded\r\n";
$httphead .= "Content-Length: " . strlen($resp) . "\r\n\r\n";
// Now create a ="file handle" for writing to a URL to paypal.com on Port 443 (the IPN port)
$errno ='';
$errstr='';
$fh = fsockopen ('ssl://www.sandbox.paypal.com', 443, $errno, $errstr, 30); //PROBLEM?
// STEP 4 - Nearly done. Now send the data back to PayPal so it can tell us if the IPN notification was genuine
if (!$fh) {
// Uh oh. This means that we have not been able to get thru to the PayPal server. It's an HTTP failure
}
// Connection opened, so spit back the response and get PayPal's view whether it was an authentic notification
else {
fputs ($fh, $httphead . $resp);
while (!feof($fh))
{
$readresp = fgets ($fh, 1024);
// $readresp = trim($readresp);
if (strcmp ($readresp, "VERIFIED") == 0) //yay verified data!
{
}
else if (strcmp ($readresp, "INVALID") == 0) //Invalid data! :(
{
}
}
fclose ($fh);
}
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title></title>
</head>
<body>
</body>
</html>
Here is my button code:
<form action="https://www.sandbox.paypal.com/cgi-bin/webscr" method="post" target="_top">
<input type="hidden" name="cmd" value="_s-xclick">
<input type="hidden" name="hosted_button_id" value="M8IC3G88S5WFQ">
<input type="image" src="https://www.sandbox.paypal.com/en_US/i/btn/btn_buynowCC_LG.gif" border="0" name="submit" alt="PayPal - The safer, easier way to pay online!">
<img alt="" border="0" src="https://www.sandbox.paypal.com/en_US/i/scr/pixel.gif" width="1" height="1">
</form>
Any help with what fsockopen()
configuration i should use?
Well i got it to work by having a private SSL certificate installed on my domain (must be 2048-bit and SHA-256) meaning you must have HTTPS.
I also started using the official Paypal listener php example code which can be found here: https://github.com/paypal/ipn-code-samples/blob/master/paypal_ipn.php.
In addition, i added curl_setopt($ch, CURLOPT_SSLVERSION, 6);
to the example code curl statements to use TSLv1.2 communication, this is required due to the current security updates Paypal is undergoing.
I'm currently hosted with Hostgator if thats any relevance to anyone (private ssl certificates are automatically 2048-bit and SHA-256 which is good).
I hope that the results of my days of struggle will also help someone going through the same problems, Cheers!