I know this question has been asked heaps, but I've been through all the answers that I can find and none have helped; many are years old, so I'm not sure if that's part of the problem.
I've been testing a paypal IPN listener by sending an IPN through Sandbox. It states that the IPN has been sent and the handshake verified, but the status that is returned to the listener is always invalid. I've tried several different examples, but none work. I've stripped my code right back, just logging the input text, the output text, the verification status from paypal and the http status code:
<?php
define("LOG_FILE", "./ipn.log");
define("DEBUG", 0);
define("USE_SANDBOX", 1); //for testing
//get raw input
$stream_input = file_get_contents('php://input');
error_log(date('[Y-m-d H:i e] '). $stream_input. PHP_EOL, 3, LOG_FILE); //log result for comparison to return string
//choose correct URL
if(USE_SANDBOX == 1) {
$paypal_url = "https://www.sandbox.paypal.com/cgi-bin/webscr";
} else {
$paypal_url = "https://www.paypal.com/cgi-bin/webscr";
}
// add cmd for return request
$return_string = 'cmd=_notify-validate&' . $stream_input;
error_log(date('[Y-m-d H:i e] '). $return_string. PHP_EOL, 3, LOG_FILE); //log result for comparison
//cURL setup
$ch = curl_init($paypal_url);
if ($ch == FALSE) {
return FALSE;
}
curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $return_string);
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_CONNECTTIMEOUT, 30);
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Connection: Close'));
$verification_status = curl_exec($ch);
$http_status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
//log result
error_log(date('[Y-m-d H:i e] '). $verification_status . PHP_EOL, 3, LOG_FILE);
error_log(date('[Y-m-d H:i e] '). $http_status . PHP_EOL, 3, LOG_FILE);
//log cURL errors
if (curl_errno($ch) != 0) // cURL error
{
if(DEBUG == true) {
error_log(date('[Y-m-d H:i e] '). "Can't connect to PayPal to validate IPN message: " . curl_error($ch) . PHP_EOL, 3, LOG_FILE);
}
curl_close($ch);
exit;
} else {
// Log the entire HTTP response if debug is switched on.
if(DEBUG == true) {
error_log(date('[Y-m-d H:i e] '). "HTTP request of validation request:". curl_getinfo($ch, CURLINFO_HEADER_OUT) ." for IPN payload: $return_array" . PHP_EOL, 3, LOG_FILE);
error_log(date('[Y-m-d H:i e] '). "HTTP response of validation request: $verification_status" . PHP_EOL, 3, LOG_FILE);
}
curl_close($ch);
}
?>
And this is the output I get in the log:
[2016-06-20 03:52 America/New_York] payment_type=instant&payment_date=Mon%20Jun%2020%202016%2017%3A50%3A12%20GMT+1000%20%28AUS%20Eastern%20Standard%20Time%29&payment_status=Canceled_Reversal&address_status=confirmed&payer_status=verified&first_name=John&last_name=Smith&[email protected]&payer_id=TESTBUYERID01&address_name=John%20Smith&address_country=United%20States&address_country_code=US&address_zip=95131&address_state=CA&address_city=San%20Jose&address_street=123%20any%20street&[email protected]&[email protected]&[email protected]&residence_country=US&item_name=something&item_number=AK-1234&quantity=1&shipping=3.04&tax=2.02&mc_currency=USD&mc_fee=0.44&mc_gross=12.34&mc_gross_1=12.34&txn_type=web_accept&txn_id=146655022¬ify_version=2.1&parent_txn_id=SOMEPRIORTXNID003&reason_code=other&custom=xyz123&invoice=abc1234&test_ipn=1&verify_sign=AFcWxV21C7fd0v3bYYYRCpSSRl31AXwY9QNq9ZSeZMzEi6Nyk68hdvbc
[2016-06-20 03:52 America/New_York] cmd=_notify-validate&payment_type=instant&payment_date=Mon%20Jun%2020%202016%2017%3A50%3A12%20GMT+1000%20%28AUS%20Eastern%20Standard%20Time%29&payment_status=Canceled_Reversal&address_status=confirmed&payer_status=verified&first_name=John&last_name=Smith&[email protected]&payer_id=TESTBUYERID01&address_name=John%20Smith&address_country=United%20States&address_country_code=US&address_zip=95131&address_state=CA&address_city=San%20Jose&address_street=123%20any%20street&[email protected]&[email protected]&[email protected]&residence_country=US&item_name=something&item_number=AK-1234&quantity=1&shipping=3.04&tax=2.02&mc_currency=USD&mc_fee=0.44&mc_gross=12.34&mc_gross_1=12.34&txn_type=web_accept&txn_id=146655022¬ify_version=2.1&parent_txn_id=SOMEPRIORTXNID003&reason_code=other&custom=xyz123&invoice=abc1234&test_ipn=1&verify_sign=AFcWxV21C7fd0v3bYYYRCpSSRl31AXwY9QNq9ZSeZMzEi6Nyk68hdvbc
[2016-06-20 03:52 America/New_York] INVALID
[2016-06-20 03:52 America/New_York] 200
I've tested the input and output strings against each other, and they are identical except for the 'cmd=_notify-validate&' at the start of the output string. I have tried sending the output back as an array using urlencode as most of the examples do, but no luck there either.
Please, what am I missing?