I'm working with the paypal adaptive payments and my IPN listener worked fine in the sandbox, but now that we're testing live transactions, it always returns "INVALID", but the actual money has been transferred.
Any help on why I always receive "INVALD" is appreciated.
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
class Paypal_ipn extends CI_Controller {
public function index() {
log_message('error', '');
log_message('error', '');
log_message('error', '##################');
log_message('error', '##################');
// read the post from PayPal system and add 'cmd'
$req = 'cmd=_notify-validate&'.file_get_contents("php://input");
$header = null;
// post back to PayPal system to validate
$header .= "POST /cgi-bin/webscr HTTP/1.0\r\n";
$header .= "Host: www.sandbox.paypal.com\r\n"; // this line is needed for sandbox, but may not be needed for prod.
$header .= "Content-Type: application/x-www-form-urlencoded\r\n";
$header .= "Content-Length: " . strlen($req) . "\r\n\r\n";
$fp = fsockopen ('ssl://www.sandbox.paypal.com', 443, $errno, $errstr, 30);
$raw_post = file_get_contents("php://input");
$post_array = $this->decodePayPalIPN($raw_post);
log_message('error', "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
$log1 = var_export($post_array, true);
log_message('error', $log1);
log_message('error', "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
log_message('error', "sender_email = ".$post_array['sender_email']);
if(isset($post_array['sender_email'])) {
$sender_email = $post_array['sender_email'];
}
if(isset($post_array['status'])) {
$status = $post_array['status'];
}
if(isset($post_array['payment_request_date'])) {
$payment_request_date = $post_array['payment_request_date'];
}
if(isset($post_array['transaction'][0]['receiver'])) {
$receiver0 = $post_array['transaction'][0]['receiver'];
}
if(isset($post_array['transaction'][1]['receiver'])) {
$receiver1 = $post_array['transaction'][1]['receiver'];
}
if(isset($post_array['transaction'][0]['id'])) {
$id0 = $post_array['transaction'][0]['id'];
}
if(isset($post_array['transaction'][1]['id'])) {
$id1 = $post_array['transaction'][1]['id'];
}
if(isset($post_array['transaction'][0]['invoiceId'])) {
$invoiceId0 = $post_array['transaction'][0]['invoiceId'];
}
if(isset($post_array['transaction'][1]['invoiceId'])) {
$invoiceId1 = $post_array['transaction'][1]['invoiceId'];
}
if(isset($post_array['transaction'][0]['amount'])) {
$amount0 = $post_array['transaction'][0]['amount'];
}
if(isset($post_array['transaction'][1]['amount'])) {
$amount1 = $post_array['transaction'][1]['amount'];
}
if(isset($post_array['transaction'][0]['status'])) {
$status0 = $post_array['transaction'][0]['status'];
}
if(isset($post_array['transaction'][1]['status'])) {
$status1 = $post_array['transaction'][1]['status'];
}
if(isset($post_array['transaction'][0]['id_for_sender_txn'])) {
$id_for_sender_txn0 = $post_array['transaction'][0]['id_for_sender_txn'];
}
if(isset($post_array['transaction'][1]['id_for_sender_txn'])) {
$id_for_sender_txn1 = $post_array['transaction'][1]['id_for_sender_txn'];
}
if(isset($post_array['transaction'][0]['status_for_sender_txn'])) {
$status_for_sender_txn0 = $post_array['transaction'][0]['status_for_sender_txn'];
}
if(isset($post_array['transaction'][1]['status_for_sender_txn'])) {
$status_for_sender_txn1 = $post_array['transaction'][1]['status_for_sender_txn'];
}
if(isset($post_array['transaction'][1]['pending_reason'])) {
$pending_reason0 = $post_array['transaction'][1]['pending_reason'];
}
if(isset($post_array['transaction'][1]['pending_reason'])) {
$pending_reason1 = $post_array['transaction'][1]['pending_reason'];
}
if (!$fp) {
log_message('error', 'Problem with !$fp');
// HTTP ERROR
} else {
$counter = 0;
fputs ($fp, $header . $req);
$res = '';
while (!feof($fp)) {
$res .= fgets ($fp, 1024);
log_message('error', "res = $res");
if (strcmp ($res, "VERIFIED") == 0) {
log_message('error', 'we verified');
if($status0 == "Completed") {
log_message('error', 'we completed');
$this->load->model('customer_model');
$results = $this->customer_model->get_invoice_info($invoiceId0);
if($results != false) {
log_message('error', 'results is NOT false');
foreach($results as $row) {
if($row->amount_verified != 1) {
log_message('error', 'row->amount_verified is NOT equal to 1');
log_message('error', "row->amount = ".$row->amount);
if($row->amount == $amount0) {
//log_message('error', 'row->amount is equal to amount0');
if($this->customer_model->verify_amount($invoiceId0)) {
$subject = 'Successful transaction';
$message = 'There was a successful transaction. View the log for details /public_html/application/logs';
$this->_send_email($subject, $message);
}
} else {
//log_message('error', 'we in the else');
//log_message('error', 'invoiceId0 = '.$invoiceId0);
if($this->customer_model->update_amount_and_verify($invoiceId0, $row->amount)) {
//log_message('error', 'we inside update_amount_and_verify');
$subject = 'Successful transaction';
$message = 'There was a successful transaction. View the log for details /public_html/application/logs';
$this->_send_email($subject, $message);
}
}
}
}
} else {
$subject = 'Results Equal False';
$message = 'View the log for details /public_html/application/logs';
$this->_send_email($subject, $message);
}
} else {
$subject = 'Status NOT Complete!';
$message = 'View the log for details /public_html/application/logs';
$this->_send_email($subject, $message);
}
log_message('error', "sender_email = $sender_email");
log_message('error', "payment_request_date = $payment_request_date");
log_message('error', "status = $status");
log_message('error', "receiver0 = $receiver0");
log_message('error', "receiver1 = $receiver1");
log_message('error', "id0 = $id0");
log_message('error', "id1 = $id1");
log_message('error', "invoiceId0 = $invoiceId0");
log_message('error', "invoiceId1 = $invoiceId1");
log_message('error', "amount0 = $amount0");
log_message('error', "amount1 = $amount1");
log_message('error', "status0 = $status0");
log_message('error', "status1 = $status1");
log_message('error', "id_for_sender_txn0 = $id_for_sender_txn0");
log_message('error', "id_for_sender_txn1 = $id_for_sender_txn1");
log_message('error', "status_for_sender_txn0 = $status_for_sender_txn0");
log_message('error', "status_for_sender_txn1 = $status_for_sender_txn1");
log_message('error', "pending_reason0 = $pending_reason0");
log_message('error', "pending_reason1 = $pending_reason1");
// check 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 payment
$counter++;
}
else if (strcmp ($res, "INVALID") == 0) {
log_message('error', 'WE INVALIDDDDDDDDDDDDDDDDDD');
$test = var_export($res, true);
$test = str_replace(array("\r","\n"), '', $test);
log_message('error', $test);
log_message('error', "Problem with IPN. res = $test");
}
}
fclose ($fp);
}
}
function decodePayPalIPN($raw_post)
{
//log_message('error', "testing");
if (empty($raw_post)) {
return array();
} # else:
$post = array();
$pairs = explode('&', $raw_post);
foreach ($pairs as $pair) {
list($key, $value) = explode('=', $pair, 2);
$key = urldecode($key);
$value = urldecode($value);
# This is look for a key as simple as 'return_url' or as complex as 'somekey[x].property'
preg_match('/(\w+)(?:\[(\d+)\])?(?:\.(\w+))?/', $key, $key_parts);
switch (count($key_parts)) {
case 4:
# Original key format: somekey[x].property
# Converting to $post[somekey][x][property]
if (!isset($post[$key_parts[1]])) {
$post[$key_parts[1]] = array($key_parts[2] => array($key_parts[3] => $value));
} else if (!isset($post[$key_parts[1]][$key_parts[2]])) {
$post[$key_parts[1]][$key_parts[2]] = array($key_parts[3] => $value);
} else {
$post[$key_parts[1]][$key_parts[2]][$key_parts[3]] = $value;
}
break;
case 3:
# Original key format: somekey[x]
# Converting to $post[somkey][x]
if (!isset($post[$key_parts[1]])) {
$post[$key_parts[1]] = array();
}
$post[$key_parts[1]][$key_parts[2]] = $value;
break;
default:
# No special format
$post[$key] = $value;
break;
}#switch
}#foreach
return $post;
}#decodePayPalIPN()
private function _send_email($subject, $message) {
//log_message('error', 'we in send_email');
$this->load->library('email');
$this->email->from('[email protected]', 'Title');
$this->email->to('[email protected]');
$this->email->subject($subject);
$this->email->message($message);
$this->email->send();
//log_message('error', 'email error = '.$this->email->print_debugger());
}
}
If you are now testing live transactions your code is still showing for sandbox -
$header .= "Host: www.sandbox.paypal.com\r\n"; // this line is needed for sandbox, but may not be needed for prod.
...
$fp = fsockopen ('ssl://www.sandbox.paypal.com', 443, $errno, $errstr, 30);
Make sure that you change to -
// $header .= "Host: www.sandbox.paypal.com\r\n"; line removed, not needed
...
$fp = fsockopen ('ssl://www.paypal.com', 443, $errno, $errstr, 30);