I have a website that i will be accepting paypal IPN's from paypal. This site is a wordpress website, on a shared enviroment, that i have customized. Using the IPN simulator it always fails on my webservice listener for ipn but succeeds for the base url. Why can i not receive a success on my webservice and log the data?
Using my browser and hitting the below webservice will write my logfile. Using IPN simulator never writes to my logfile. Also my SSL access logs never receive a POST from IPN but http does. Access log at bottom
Hitting
https://example.example.org/wp-content/plugins/myplugin/controllers/payments/ipn
Fails for IPN simulator."IPN was not sent, and the handshake was not verified. Please review your information."
Hitting https://example.example.org/
Succeeds in hitting IPN was sent and the handshake was verified.
Core::error("In the ipn function");
// STEP 1: read POST data
// Reading POSTed data directly from $_POST causes serialization issues with array data in the POST.
// Instead, read raw POST data from the input stream.
$raw_post_data = file_get_contents('php://input');
$raw_post_array = explode('&', $raw_post_data);
$myPost = array();
foreach ($raw_post_array as $keyval) {
$keyval = explode ('=', $keyval);
if (count($keyval) == 2)
$myPost[$keyval[0]] = urldecode($keyval[1]);
}
Core::error("IPN");
Core::error(json_encode($myPost));
Core::error(json_encode($_GET));
Core::error(json_encode($_POST));
// read the IPN message sent from PayPal and prepend 'cmd=_notify-validate'
$req = 'cmd=_notify-validate';
if (function_exists('get_magic_quotes_gpc')) {
$get_magic_quotes_exists = true;
}
foreach ($myPost as $key => $value) {
if ($get_magic_quotes_exists == true && get_magic_quotes_gpc() == 1) {
$value = urlencode(stripslashes($value));
} else {
$value = urlencode($value);
}
$req .= "&$key=$value";
}
$path = "/home1/xx/";
$cert = "ff67367c5cd4de4ae18bcce1d70fdabd7c866135.pem";
$sandBoxUrl = "https://www.sandbox.paypal.com/cgi-bin/webscr";
$prUrl = "https://www.paypal.com/cgi-bin/webscr";
// Step 2: POST IPN data back to PayPal to validate
$ch = curl_init($sandBoxUrl);
//curl_setopt($ch, CURLOPT_CAINFO, $path . $cert);
curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_SSLVERSION, 6);
curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $req);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 1);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2);
curl_setopt($ch, CURLOPT_FORBID_REUSE, 1);
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Connection: Close'));
// In wamp-like environments that do not come bundled with root authority certificates,
// please download 'cacert.pem' from "http://curl.haxx.se/docs/caextract.html" and set
// the directory path of the certificate as shown below:
curl_setopt($ch, CURLOPT_CAINFO, '/home1/xxx/cacert.pem');
$res = curl_exec($ch);
if ( !$res ) {
Core::error(curl_error($ch));
// error_log("Got " . curl_error($ch) . " when processing IPN data");
curl_close($ch);
exit;
}
Core::error("Resposne");
Core::error($res);
curl_close($ch);
// inspect IPN validation result and act accordingly
if (strcmp ($res, "VERIFIED") == 0) {
Core::error("VERIFIED ");
// The IPN is verified, process it
// The IPN is verified, process it:
// check whether the payment_status is Completed
// check that txn_id has not been previously processed
// check that receiver_email is your Primary PayPal email
// check that payment_amount/payment_currency are correct
// process the notification
// assign posted variables to local variables
$item_name = $_POST['item_name'];
$item_number = $_POST['item_number'];
$payment_status = $_POST['payment_status'];
$payment_amount = $_POST['mc_gross'];
$payment_currency = $_POST['mc_currency'];
$txn_id = $_POST['txn_id'];
$receiver_email = $_POST['receiver_email'];
$payer_email = $_POST['payer_email'];
// IPN message values depend upon the type of notification sent.
// To loop through the &_POST array and print the NV pairs to the screen:
foreach($_POST as $key => $value) {
$data = $key . " = " . $value . "<br>";
Core::error($data);
}
} else if (strcmp ($res, "INVALID") == 0) {
// IPN invalid, log for manual investigation
Core::error("invalid ");
}
header("HTTP/1.1 200 OK");
die();
HTTPS Log After IPN Spammed
ip - - [14/Jun/2016:19:29:05 -0500] "POST /wp-admin/admin-ajax.php HTTP/1.1" 200 47 "https://wordpress.example.org/wp-admin/admin.php?page=example%2Fexample.php" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.84 Safari/537.36"
ip - - [14/Jun/2016:19:30:07 -0500] "POST /wp-admin/admin-ajax.php HTTP/1.1" 200 47 "https://wordpress.example.org/wp-admin/admin.php?page=example%2Fexample.php" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.84 Safari/537.36"
ip - - [14/Jun/2016:19:31:07 -0500] "POST /wp-admin/admin-ajax.php HTTP/1.1" 200 47 "https://wordpress.example.org/wp-admin/admin.php?page=example%2Fexample.php" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.84 Safari/537.36"
NonHttps Log After IPN Spammed
ip - - [14/Jun/2016:17:35:13 -0500] "POST /wp-content/plugins/example/controllers/payments/ipn HTTP/1.1" 406 275 "-" "-"
ip - - [14/Jun/2016:17:37:10 -0500] "POST /wp-content/plugins/example/controllers/payments/ipn HTTP/1.1" 406 275 "-" "-"
ip - - [14/Jun/2016:17:39:04 -0500] "POST /wp-content/plugins/example/controllers/payments/ipn HTTP/1.1" 406 275 "-" "-"
ip - - [14/Jun/2016:17:58:28 -0500] "POST /wp-content/plugins/example/controllers/payments/ipn HTTP/1.1" 406 275 "-" "-"
ip - - [14/Jun/2016:17:58:35 -0500] "POST /wp-content/plugins/example/controllers/payments/ipn HTTP/1.1" 406 275 "-" "-"
edit If i replace my script with this and place it in the root directory of my site it will work. It i move the script to anywhere under the root dir it will not work.
edit2 Using my script or not the IPN always succeeds on the index of my site. I dont understand why it would succeed here
The answer was that for development you need to send IPN requests from the IPN simulator at sandbox.paypal.com instead of developer.paypal.com.
You also must login to sandbox.paypal.com with your [email protected] creds that were created in developer.paypal.com.