protected function _start($log_dir, $log_file, $task) { // Tick tock tick... $this->start = microtime(TRUE) * 10000; $this->task = $task; // -------------------------------------------------------------------------- // Set log details _LOG_FILE('cron/' . $log_dir . '/' . $log_file . '-' . date('Y-m-d') . '.php'); _LOG('Starting job [' . $this->task . ']...'); _LOG(); }
protected function _notify_paypal() { // Configure log _LOG_FILE(app_setting('url', 'shop') . 'notify/paypal/ipn-' . date('Y-m-d') . '.php'); _LOG(); _LOG('- - - - - - - - - - - - - - - - - - -'); _LOG('Waking up IPN responder; handling with PayPal'); // -------------------------------------------------------------------------- // POST data? // Want to test a previous IPN message? // Paste the IPN message into the following and uncomment the following lines // $_message = ''; // $_message = str_replace( '+', '%2B', $_message ); // parse_str( $_message, $_POST ); if (!$this->data['testing'] && !$this->input->post()) { _LOG('No POST data, going back to sleep...'); _LOG('- - - - - - - - - - - - - - - - - - -'); _LOG(); return; } // -------------------------------------------------------------------------- // Are we testing? if ($this->data['testing']) { $_ipn = TRUE; _LOG(); _LOG('**TESTING**'); _LOG('**Simulating data sent from PayPal**'); _LOG(); // Check order exists $_order = $this->shop_order_model->get_by_ref($this->input->get('ref')); if (!$_order) { _LOG('Invalid order reference, aborting.'); _LOG('- - - - - - - - - - - - - - - - - - -'); _LOG(); return; } // -------------------------------------------------------------------------- $_paypal = array(); $_paypal['payment_type'] = 'instant'; $_paypal['invoice'] = $_order->ref; $_paypal['custom'] = $this->encrypt->encode(md5($_order->ref . ':' . $_order->code), APP_PRIVATE_KEY); $_paypal['txn_id'] = 'TEST:' . random_string('alpha', 6); $_paypal['txn_type'] = 'cart'; $_paypal['payment_status'] = 'Completed'; $_paypal['pending_reason'] = 'PaymentReview'; $_paypal['mc_fee'] = 0.0; } else { _LOG('Validating the IPN call'); $this->load->library('paypal'); $_ipn = $this->paypal->validate_ipn(); $_paypal = $this->input->post(); $_order = $this->shop_order_model->get_by_ref($this->input->post('invoice')); if (!$_order) { _LOG('Invalid order ID, aborting. Likely a transaction not initiated by the site.'); _LOG('- - - - - - - - - - - - - - - - - - -'); _LOG(); return; } } // -------------------------------------------------------------------------- // Did the IPN validate? if ($_ipn) { _LOG('IPN Verified with PayPal'); _LOG(); // -------------------------------------------------------------------------- // Extra verification step, check the 'custom' variable decodes appropriately _LOG('Verifying data'); _LOG(); $_verification = $this->encrypt->decode($_paypal['custom'], APP_PRIVATE_KEY); if ($_verification != md5($_order->ref . ':' . $_order->code)) { $_data = array('pp_txn_id' => $_paypal['txn_id']); $this->shop_order_model->fail($_order->id, $_data); _LOG('Order failed secondary verification, aborting.'); _LOG('- - - - - - - - - - - - - - - - - - -'); _LOG(); // -------------------------------------------------------------------------- // Inform developers send_developer_mail('An IPN request failed', 'An IPN request was made which failed secondary verification, Order: ' . $_paypal['invoice']); return; } // -------------------------------------------------------------------------- // Only bother to handle certain types // TODO: handle refunds _LOG('Checking txn_type is supported'); _LOG(); if ($_paypal['txn_type'] != 'cart') { _LOG('"' . $_paypal['txn_type'] . '" is not a supported PayPal txn_type, gracefully aborting.'); _LOG('- - - - - - - - - - - - - - - - - - -'); _LOG(); return; } // -------------------------------------------------------------------------- // Check if order has already been processed _LOG('Checking if order has already been processed'); _LOG(); if (ENVIRONMENT == 'production' && $_order->status != 'UNPAID') { _LOG('Order has already been processed, aborting.'); _LOG('- - - - - - - - - - - - - - - - - - -'); _LOG(); return; } elseif (ENVIRONMENT != 'production' && $_order->status != 'UNPAID') { _LOG('Order has already been processed, but not on production so continuing anyway.'); _LOG(); } // -------------------------------------------------------------------------- // Check the status of the payment _LOG('Checking the status of the payment'); _LOG(); switch (strtolower($_paypal['payment_status'])) { case 'completed': // Do nothing, this transaction is OK _LOG('Payment status is "completed"; continuing...'); break; // -------------------------------------------------------------------------- // -------------------------------------------------------------------------- case 'reversed': // Transaction was cancelled, mark order as FAILED _LOG('Payment was reversed, marking as failed and aborting'); $_data = array('pp_txn_id' => $_paypal['txn_id']); $this->shop_order_model->fail($_order->id, $_data); break; // -------------------------------------------------------------------------- // -------------------------------------------------------------------------- case 'pending': // Check the pending_reason, if it's 'paymentreview' then gracefully stop // processing; PayPal will send a further IPN once the payment is complete _LOG('Payment status is "pending"; check the reason.'); if (strtolower($_paypal['pending_reason']) == 'paymentreview') { // The transaction is pending review, gracefully stop proicessing, but don't cancel the order _LOG('Payment is pending review by PayPal, gracefully aborting just now.'); $this->shop_order_model->pending($_order->id); return; } else { _LOG('Unsupported payment reason "' . $_paypal['pending_reason'] . '", aborting.'); // -------------------------------------------------------------------------- $_data = array('pp_txn_id' => $_paypal['txn_id']); $this->shop_order_model->fail($_order->id, $_data); // -------------------------------------------------------------------------- // Inform developers send_developer_mail('A PayPal payment failed', '<strong>' . $_order->user->first_name . ' ' . $_order->user->last_name . ' (' . $_order->user->email . ')</strong> has just attempted to pay for order ' . $_order->ref . '. The payment failed with status "' . $_paypal['payment_status'] . '" and reason "' . $_paypal['pending_reason'] . '".'); return; } // -------------------------------------------------------------------------- return; break; // -------------------------------------------------------------------------- // -------------------------------------------------------------------------- default: // Unknown/invalid payment status _LOG('Invalid payment status'); $_data = array('pp_txn_id' => $_paypal['txn_id']); $this->shop_order_model->fail($_order->id, $_data); // -------------------------------------------------------------------------- // Inform developers send_developer_mail('A PayPal payment failed', '<strong>' . $_order->user->first_name . ' ' . $_order->user->last_name . ' (' . $_order->user->email . ')</strong> has just attempted to pay for order ' . $_order->ref . '. The payment failed with status "' . $_paypal['payment_status'] . '" and reason "' . $_paypal['pending_reason'] . '".'); return; break; } // -------------------------------------------------------------------------- // All seems good, continue with order processing _LOG('All seems well, continuing...'); _LOG(); _LOG('Setting txn_id (' . $_paypal['txn_id'] . ') and fees_deducted (' . $_paypal['mc_fee'] . ').'); _LOG(); $_data = array('pp_txn_id' => $_paypal['txn_id'], 'fees_deducted' => $_paypal['mc_fee']); $this->shop_order_model->paid($_order->id, $_data); // -------------------------------------------------------------------------- // PROCESSSSSS... $this->shop_order_model->process($_order); _LOG(); // -------------------------------------------------------------------------- // Send a receipt to the customer _LOG('Sending receipt to customer: ' . $_order->user->email); $this->shop_order_model->send_receipt($_order); _LOG(); // -------------------------------------------------------------------------- // Send a notification to the store owner(s) _LOG('Sending notification to store owner(s): ' . notification('notify_order', 'shop')); $this->shop_order_model->send_order_notification($_order); // -------------------------------------------------------------------------- if ($_order->voucher) { // Redeem the voucher, if it's there _LOG('Redeeming voucher: ' . $_order->voucher->code . ' - ' . $_order->voucher->label); $this->shop_voucher_model->redeem($_order->voucher->id, $_order); } // -------------------------------------------------------------------------- _LOG(); // -------------------------------------------------------------------------- _LOG('All done here, going back to sleep...'); _LOG('- - - - - - - - - - - - - - - - - - -'); _LOG(); if ($this->data['testing']) { echo anchor(app_setting('url', 'shop') . 'checkout/processing?ref=' . $_order->ref, 'Continue to Processing Page'); } } else { _LOG('PayPal did not verify this IPN call, aborting.'); _LOG('- - - - - - - - - - - - - - - - - - -'); _LOG(); } }