_eventData = $data; return $this; } /** * Event request data getter * @param string $key * @return array|string */ public function getEventData($key = null) { if (null === $key) { return $this->_eventData; } return isset($this->_eventData[$key]) ? $this->_eventData[$key] : null; } /** * Get singleton of Checkout Session Model * * @return Mage_Checkout_Model_Session */ protected function _getCheckout() { return Mage::getSingleton('checkout/session'); } /** * Process status notification from Monebookers server * * @return String */ public function processStatusEvent() { try { $params = $this->_validateEventData(); $msg = ''; switch($params['status']) { case self::MONEYBOOKERS_STATUS_FAIL: //fail $msg = Mage::helper('moneybookers')->__('Payment failed.'); $this->_processCancel($msg); break; case self::MONEYBOOKERS_STATUS_CANCEL: //cancel $msg = Mage::helper('moneybookers')->__('Payment was canceled.'); $this->_processCancel($msg); break; case self::MONEYBOOKERS_STATUS_PENDING: //pending $msg = Mage::helper('moneybookers')->__('Pending bank transfer created.'); $this->_processSale($params['status'], $msg); break; case self::MONEYBOOKERS_STATUS_SUCCESS: //ok $msg = Mage::helper('moneybookers')->__('The amount has been authorized and captured by Moneybookers.'); $this->_processSale($params['status'], $msg); break; } return $msg; } catch (Mage_Core_Exception $e) { return $e->getMessage(); } catch(Exception $e) { Mage::logException($e); } return; } /** * Process cancelation */ public function cancelEvent() { try { $this->_validateEventData(false); $this->_processCancel('Payment was canceled.'); return Mage::helper('moneybookers')->__('The order has been canceled.'); } catch (Mage_Core_Exception $e) { return $e->getMessage(); } catch(Exception $e) { Mage::logException($e); } return ''; } /** * Validate request and return QuoteId * Can throw Mage_Core_Exception and Exception * * @return int */ public function successEvent(){ $this->_validateEventData(false); return $this->_order->getQuoteId(); } /** * Processed order cancelation * @param string $msg Order history message */ protected function _processCancel($msg) { $this->_order->cancel(); $this->_order->addStatusToHistory(Mage_Sales_Model_Order::STATE_CANCELED, $msg); $this->_order->save(); } /** * Processes payment confirmation, creates invoice if necessary, updates order status, * sends order confirmation to customer * * @param string $status * @param string $msg Order history message */ protected function _processSale($status, $msg) { switch ($status) { case self::MONEYBOOKERS_STATUS_SUCCESS: $this->_createInvoice(); $this->_order->setState(Mage_Sales_Model_Order::STATE_PROCESSING, true, $msg); // save transaction ID $this->_order->getPayment()->setLastTransId($this->getEventData('mb_transaction_id')); // send new order email $this->_order->queueNewOrderEmail(); $this->_order->setEmailSent(true); break; case self::MONEYBOOKERS_STATUS_PENDING: $this->_order->setState(Mage_Sales_Model_Order::STATE_PENDING_PAYMENT, true, $msg); // save transaction ID $this->_order->getPayment()->setLastTransId($this->getEventData('mb_transaction_id')); break; } $this->_order->save(); } /** * Builds invoice for order */ protected function _createInvoice() { if (!$this->_order->canInvoice()) { return; } $invoice = $this->_order->prepareInvoice(); $invoice->register()->capture(); $this->_order->addRelatedObject($invoice); } /** * Checking returned parameters * Thorws Mage_Core_Exception if error * @param bool $fullCheck Whether to make additional validations such as payment status, transaction signature etc. * * @return array $params request params */ protected function _validateEventData($fullCheck = true) { // get request variables $params = $this->_eventData; if (empty($params)) { Mage::throwException('Request does not contain any elements.'); } // check order ID if (empty($params['transaction_id']) || ($fullCheck == false && $this->_getCheckout()->getMoneybookersRealOrderId() != $params['transaction_id']) ) { Mage::throwException('Missing or invalid order ID.'); } // load order for further validation $this->_order = Mage::getModel('sales/order')->loadByIncrementId($params['transaction_id']); if (!$this->_order->getId()) { Mage::throwException('Order not found.'); } if (0 !== strpos($this->_order->getPayment()->getMethodInstance()->getCode(), 'moneybookers_')) { Mage::throwException('Unknown payment method.'); } // make additional validation if ($fullCheck) { // check payment status if (empty($params['status'])) { Mage::throwException('Unknown payment status.'); } // check transaction signature if (empty($params['md5sig'])) { Mage::throwException('Invalid transaction signature.'); } $checkParams = array('merchant_id', 'transaction_id', 'secret', 'mb_amount', 'mb_currency', 'status'); $md5String = ''; foreach ($checkParams as $key) { if ($key == 'merchant_id') { $md5String .= Mage::getStoreConfig(Phoenix_Moneybookers_Helper_Data::XML_PATH_CUSTOMER_ID, $this->_order->getStoreId() ); } elseif ($key == 'secret') { $secretKey = Mage::getStoreConfig( Phoenix_Moneybookers_Helper_Data::XML_PATH_SECRET_KEY, $this->_order->getStoreId() ); if (empty($secretKey)) { Mage::throwException('Secret key is empty.'); } $md5String .= strtoupper(md5($secretKey)); } elseif (isset($params[$key])) { $md5String .= $params[$key]; } } $md5String = strtoupper(md5($md5String)); if ($md5String != $params['md5sig']) { Mage::throwException('Hash is not valid.'); } // check transaction amount if currency matches if ($this->_order->getOrderCurrencyCode() == $params['mb_currency']) { if (round($this->_order->getGrandTotal(), 2) != $params['mb_amount']) { Mage::throwException('Transaction amount does not match.'); } } } return $params; } }