CodeIgniter Forums

Full Version: PayPal IPN Response and Table Updates
You're currently viewing a stripped down version of our content. View the full version with proper formatting.

El Forum

[eluser]johnnyletrois[/eluser]
Hi,

I'm trying to get the final piece of my backend running, and I'm having a problem. After making a payment, the database is not updating at all.

There appears to be a disconnect between the IPN listener and the updateTableData model. I've tested the IPN listener from the PayPal Sandbox and it is working fine. I have also confirmed that payment status is being returned as "Completed" so that is also fine.

======================================
Payment controller IPN listener
-----------------------------------------------------------
Code:
function paypal_ipn()
    {
        if($_REQUEST['payment_status'] == 'Completed')
        {
        $custom              = $_REQUEST['custom'];
        $data                = array();
        $list                = array();
        $data                = explode('@', $custom);
      
        $list_id             = $data[0];
        $reservation_id      = $data[1];
        $email_id            = $data[2];
      
        $price               = $_REQUEST['mc_gross'];
      
        $result              = $this->Common_model->getTableData( 'reservation',array('id' => $list_id) )->row();
        $checkin             = $result->checkin;
        $checkout            = $result->checkout;
      
        $admin_email         = $this->dx_auth->get_site_sadmin();
        $admin_name          = $this->dx_auth->get_site_title();
      
        $query               = $this->Users_model->get_user_by_id($result->userto);
     $hotelier_name       = $query->row()->username;
        $hotelier_email      = $query->row()->email;
      
        $list['payed_date']  = date('d-m-Y H:i:s');
        $list['is_payed']    = 1;
      
         //Notification
            $email_name = 'admin_payment';
            $splVars = array("{site_name}" => $this->dx_auth->get_site_title(), "{username}" => ucfirst($hotelier_name), "{list_title}" => get_list_by_id($list_id)->title, "{payed_date}}" => $list['payed_date'], "{pay_id}" => $email_id, "{checkin}" => $checkin, "{checkout}" => $checkout, "{payed_price}" => $price);
            //Send Mail
            $this->Email_model->sendMail($hotelier_email,$admin_email,ucfirst($admin_name),$email_name,$splVars);
      
        $condition = array("id" => $reservation_id);
        $this->Common_model->updateTableData('reservation', NULL, $condition, $list);
        }
    }
My first thought was that the $list array is being passed from the controller to the model and the model is looking for the $updateData array so I changed the controller to

Code:
$updateData    =    $list;

but that did nothing.

==============================================
Model common_model
--------------------------------------------------------------------------------------------
Code:
function updateTableData($table='',$id=0, $conditions=array(), $updateData=array())
     {
         if(is_array($conditions) and count($conditions)>0)      
             $this->db->where($conditions);
        else  
            $this->db->where('id', $id);
         $this->db->update($table, $updateData);
        
     }//End of updateTableData Function

I'm banging my head against my desk trying to get this to work. Thanks for looking.

-John

El Forum

[eluser]TheFuzzy0ne[/eluser]
Just an observation: You have an extra closing curly brace.
Code:
"{payed_date}}"

Have you confirmed that the email is actually sending and not timing out?

You should be able to debug that yourself really. You have log_message() at your disposal.

Make sure logging is enabled, and you should be able to see what's going on.

You should also be able to emulate the $_REQUEST array to store the data you want, so you can test different conditions. For example:
Code:
function test_ipn()
{
    ini_set('display_errors', '1');
    error_reporting(E_ALL);

    $_REQUEST = array(
        'payment_status' => 'Completed',
        /* ...Add more data here... */
    );

    $this->paypal_ipn();
}

You can now test your method from your address bar, without having to go via PayPal each time. You can also use print_r, echo and var_dump() to see what's going on. Smile

El Forum

[eluser]johnnyletrois[/eluser]
Thanks for putting me on the right track. Doing some debugging, it appears
Code:
$result  = $this->Common_model->getTableData('reservation', array('id' => $list_id))->row();
is returning
Code:
array(0) { }
even though
Code:
$list_id = $data[0];
is returning
Code:
string(1) "7"
when I defined 7 as the first result in my custom string.

I'm still stuck after that so I appreciate your help.

El Forum

[eluser]TheFuzzy0ne[/eluser]
Is the email getting sent?

El Forum

[eluser]johnnyletrois[/eluser]
The problem is
Code:
$result  = $this->Common_model->getTableData('reservation', array('id' => $list_id))->row();
is returning
Code:
array(0) { }

If i manually put an assign a value to $result then everything works fine (DB is updated, email is sent). But getTableData is not returning anything in this instance although it works elsewhere.

El Forum

[eluser]TheFuzzy0ne[/eluser]
How about you post the code for that function. It's kinda hard to spot the problem without seeing the code. Smile

El Forum

[eluser]johnnyletrois[/eluser]
[quote author="TheFuzzy0ne" date="1365588186"]How about you post the code for that function. It's kinda hard to spot the problem without seeing the code. Smile[/quote]

It's from the first post:

Code:
function paypal_ipn()
    {
        if($_REQUEST['payment_status'] == 'Completed')
        {
        $custom              = $_REQUEST['custom'];
        $data                = array();
        $list                = array();
        $data                = explode('@', $custom);
      
        $list_id             = $data[0];
        $reservation_id      = $data[1];
        $email_id            = $data[2];
      
        $price               = $_REQUEST['mc_gross'];
      
        $result              = $this->Common_model->getTableData( 'reservation',array('id' => $list_id) )->row();
        $checkin             = $result->checkin;
        $checkout            = $result->checkout;
      
        $admin_email         = $this->dx_auth->get_site_sadmin();
        $admin_name          = $this->dx_auth->get_site_title();
      
        $query               = $this->Users_model->get_user_by_id($result->userto);
     $hotelier_name       = $query->row()->username;
        $hotelier_email      = $query->row()->email;
      
        $list['payed_date']  = date('d-m-Y H:i:s');
        $list['is_payed']    = 1;
      
         //Notification
            $email_name = 'admin_payment';
            $splVars = array("{site_name}" => $this->dx_auth->get_site_title(), "{username}" => ucfirst($hotelier_name), "{list_title}" => get_list_by_id($list_id)->title, "{payed_date}}" => $list['payed_date'], "{pay_id}" => $email_id, "{checkin}" => $checkin, "{checkout}" => $checkout, "{payed_price}" => $price);
            //Send Mail
            $this->Email_model->sendMail($hotelier_email,$admin_email,ucfirst($admin_name),$email_name,$splVars);
      
        $condition = array("id" => $reservation_id);
        $this->Common_model->updateTableData('reservation', NULL, $condition, $list);
        }
    }

El Forum

[eluser]TheFuzzy0ne[/eluser]
I meant for getTableData(), since that's the one that's not working as expected.

My suggestion is this:

1) Add this line to the top of your ipn() method:
Code:
function paypal_ipn()
{
    log_message('debug', serialize($_REQUEST));

2) Create a transaction to get the serialised $_REQUEST array logged.

3) Duplicate your ipn() method (perhaps call it ipn2()).

4) Change the first line of the method body to:
Code:
$request_str = 'Whatever serialised string was dumped to your log file';
$_REQUEST = unserialize($request_str);

5) Now you can call your new method directly from your browser's address bar and debug it as normal, using the data from the IPN server.

Hope this helps.