<?php

/**
 *
 * @category MultiSafepay
 * @package  MultiSafepay_Msp
 */
require_once(Mage::getBaseDir('lib') . DS . 'multisafepay' . DS . 'MultiSafepay.combined.php');

class MultiSafepay_Msp_Model_Payment extends Varien_Object
{
    protected $_config;
    protected $_gateway;
    protected $_issuer;
    protected $_mybankissuer;
    protected $_notification_url;
    protected $_cancel_url;
    protected $_return_url;
    protected $_order = null;
    public $base;
    public $api;
    public $payafterapi;
    public $pay_factor = 1;
    public $_configCode = 'msp';
    public $giftcards = array(
        'msp_webgift',
        'msp_ebon',
        'msp_babygiftcard',
        'msp_boekenbon',
        'msp_erotiekbon',
        'msp_givacard',
        'msp_parfumnl',
        'msp_parfumcadeaukaart',
        'msp_degrotespeelgoedwinkel',
        'msp_yourgift',
        'msp_wijncadeau',
        'msp_lief',
        'msp_gezondheidsbon',
        'msp_fashioncheque',
        'msp_fashiongiftcard',
        'msp_podium',
        'msp_vvvgiftcard',
        'msp_sportenfit',
        'msp_beautyandwellness',
        'msp_good4fun'
    );
    public $gateways = array(
        'msp_ideal',
        'msp_creditcard',
        'msp_dotpay',
        'msp_payafter',
        'msp_payafterdeliveryinstallments',
        'msp_einvoice',
        'msp_klarna',
        'msp_mistercash',
        'msp_visa',
        'msp_paysafecard',
        'msp_eps',
        'msp_ferbuy',
        'msp_mastercard',
        'msp_mybank',
        'msp_ing',
        'msp_cbc',
        'msp_kbc',
        'msp_belfius',
        'msp_idealqr',
        'msp_banktransfer',
        'msp_maestro',
        'msp_paypal',
        'msp_giropay',
        'msp_multisafepay',
        'msp_directebanking',
        'msp_directdebit',
        'msp_amazonpay',
        'msp_amex',
        'msp_alipayplus',
        'msp_billink',
        'msp_bizum',
        'msp_trustly',
        'msp_afterpay',
        'msp_applepay',
        'msp_directbanktransfer',
        'msp_in3',
        'msp_zinia',
    );

    /**
     * Set some vars
     */
    public function setNotificationUrl($url)
    {
        $this->_notification_url = $url;
    }

    public function setReturnUrl($url)
    {
        $this->_return_url = $url;
    }

    public function setCancelUrl($url)
    {
        $this->_cancel_url = $url;
    }

    public function setGateway($gateway)
    {
        $this->_gateway = $gateway;
    }

    public function setMyBankIssuer($mybankissuer)
    {
        $this->_mybankissuer = $mybankissuer;
    }

    public function setIssuer($issuer)
    {
        $this->_issuer = $issuer;
    }

    /**
     * Set the config object
     */
    public function setConfigObject($config)
    {
        $this->_config = $config;
        return $this;
    }

    function getConfigData($name)
    {
        if (isset($this->_config[$name])) {
            return $this->_config[$name];
        }

        return false;
    }

    /**
     * Returns an instance of the Base
     */
    public function getBase($id = null)
    {
        if ($this->base) {
            if ($id) {
                $this->base->setLogId($id);
                $this->base->setLockId($id);
            }

            return $this->base;
        }

        $this->base = Mage::getSingleton("msp/base");
        $this->base->setConfigObject($this->_config);
        $this->base->setLogId($id);
        $this->base->setLockId($id);

        return $this->base;
    }

    /**
     * Returns an instance of the Api
     */
    public function getApi($id = null)
    {
        if ($this->api) {
            if ($id) {
                $this->getBase($id);
            }

            return $this->api;
        }

        $base = $this->getBase($id);
        $this->api = $base->getApi();

        return $this->api;
    }

    /**
     * Returns an instance of the payafter Api
     */
    public function getPayAfterApi($id = null, $order = null)
    {
        if ($this->api) {
            if ($id) {
                $this->getBase($id);
            }
            return $this->api;
        }

        $base = $this->getBase($id);
        $this->api = $base->getPayAfterApi($order);

        return $this->api;
    }

    // Get API based on new gateway specific configuration (added for coupons as they now use their own account settings)
    public function getGatewaysApi($id = null, $order = null, $gateway_code = null)
    {
        if ($this->api) {
            if ($id) {
                $this->getBase($id);
            }
            return $this->api;
        }

        $base = $this->getBase($id);
        // Gateway code is like msp_payafter
        $this->api = $base->getGatewaysApi($order, $gateway_code);

        return $this->api;
    }

    /**
     * Get the current order object
     */
    public function getOrder()
    {
        if ($this->_order == null) {
            $orderIncrementId = $this->getCheckout()->getLastRealOrderId();
            $this->_order = Mage::getModel('sales/order')->loadByIncrementId($orderIncrementId);
        }

        return $this->_order;
    }

    /**
     * Get the checkout order object
     */
    public function getCheckout()
    {
        return Mage::getSingleton("checkout/session");
    }

    /**
     * Get the gateway list
     */
    public function getGateways()
    {
        $billing = $this->getCheckout()->getQuote()->getBillingAddress();
        if ($billing) {
            $country = $billing->getCountry();
        } else {
            $country = "NL";
        }

        $api = $this->api;
        $api->customer['country'] = $country;

        // Get the gateways
        $gateways = $api->getGateways();

        if ($api->error) {
            // Let's not crash on a error with the gateway request
            return array();
        }

        return $gateways;
    }

    /**
     * Function that will use the fastcheckout xml data to process connect transactions.
     * For now this will only be used for pay after delivery.
     */
    public function startPayAfterTransaction()
    {
        $session = Mage::getSingleton('customer/session');

        /**
         * We will check if the quote total is the same as the order total.
         * Throw an exception if these amounts are not the same to avoid an transaction amount mismatch!
         */
        $orderId = $this->getCheckout()->getLastRealOrderId();
        $order = $this->getOrder();
        $quote = Mage::getModel('sales/quote')->load($order->getQuoteId());

        $gateway_data = $quote->getPayment()->getData();
        $gateway = strtoupper(str_replace("msp_", '', $gateway_data['method']));

        $quote_base_grand_total = $quote->getBaseGrandTotal();
        $order_base_grand_total = $order->getBaseGrandTotal();

        $quote_grand_total = $quote->getGrandTotal();
        $order_grand_total = $order->getGrandTotal();

        if ($quote_base_grand_total == $order_base_grand_total) {
            $checked_amount = $order_base_grand_total;
            $checked_amount_current = $order_grand_total;
        } else {
            Mage::throwException(Mage::helper("msp")->__("The cart total is not the same as the order total! Creation of the transaction is halted."));
        }

        // Currency check
        $isAllowConvert = Mage::getStoreConfigFlag('msp/settings/allow_convert_currency');
        $currencies = explode(',', Mage::getStoreConfig('msp_gateways/' . strtolower($gateway_data['method']) . '/allowed_currency', Mage::app()->getStore()->getId()));
        $canUseCurrentCurrency = in_array(Mage::app()->getStore()->getCurrentCurrencyCode(), $currencies);

        $currentCurrencyCode = Mage::app()->getStore()->getCurrentCurrencyCode();
        $baseCurrencyCode = Mage::app()->getBaseCurrencyCode();

        if ($order->getGlobalCurrencyCode() == 'EUR' && Mage::getStoreConfigFlag('msp/settings/allow_convert_currency')) {
            $amount = $order_base_grand_total;
            $currencyCode = 'EUR';
        } elseif ($canUseCurrentCurrency) {
            $amount = $checked_amount_current;
            $currencyCode = $currentCurrencyCode;
        } elseif ($isAllowConvert) {
            $targetCurrencyCode = MultiSafepay_Msp_Helper_Data::CONVERT_TO_CURRENCY_CODE;

            $amount = $this->_convertCurrency($checked_amount_current, $currentCurrencyCode, $targetCurrencyCode);
            $currencyCode = MultiSafepay_Msp_Helper_Data::CONVERT_TO_CURRENCY_CODE;
        } else {
            $amount = $checked_amount;
            $currencyCode = $baseCurrencyCode;
        }

        $amount = intval((string) (round($amount * 100)));
        $amount = round($amount * $this->pay_factor);

        $storename = Mage::app()->getStore()->getName();
        $billing = $this->getOrder()->getBillingAddress();
        $shipping = $this->getOrder()->getShippingAddress();

        $items = "<ul>\n";
        foreach ($this->getOrder()->getAllVisibleItems() as $item) {
            $items .= "<li>" . ($item->getQtyOrdered() * 1) . " x : " . $item->getName() . "</li>\n";
        }
        $items .= "</ul>\n";

        $payment_method_code = $order->getPayment()->getMethodInstance()->getCode();
        $isTestMode = $this->_isTestPayAfterDelivery($payment_method_code);

        $suffix = '';
        if ($isTestMode) {
            $suffix = '_test';
        }

        // Build request
        $this->api = new MultiSafepay();
        $this->api->plugin_name = 'Magento';
        $this->api->version = Mage::getConfig()->getNode('modules/MultiSafepay_Msp/version');
        $this->api->use_shipping_notification = false;
        $this->api->merchant['api_key'] = ($this->getConfigData('api_key_pad' . $suffix) !== false) ? $this->getConfigData('api_key_pad' . $suffix) : $this->getConfigData('api_key');
        $this->api->plugin['shop'] = 'Magento';
        $this->api->plugin['shop_version'] = Mage::getVersion();
        $this->api->plugin['plugin_version'] = $this->api->version;
        $this->api->plugin['partner'] = '';
        $this->api->plugin['shop_root_url'] = '';

        $this->api->test = $isTestMode;
        $this->api->merchant['notification_url'] = $this->_notification_url . "?type=initial";
        $this->api->merchant['cancel_url'] = $this->_cancel_url;
        $this->api->merchant['redirect_url'] = $this->_return_url;
        $this->api->second_chance['send_email'] = (bool)Mage::getStoreConfig('msp_gateways/msp_' . strtolower($this->_gateway) . '/second_chance');

        $this->api->parseCustomerAddress($billing->getStreet(1));

        if ($this->api->customer['housenumber'] == '') {
            $this->api->customer['housenumber'] = $billing->getStreet(2);
            $this->api->customer['address1'] = $billing->getStreet(1);
        }

        if ($billing->getStreet(3) != '') {
            $this->api->customer['housenumber'] .= ' ' . $billing->getStreet(3);
        }

        $this->api->customer['locale'] = Mage::app()->getLocale()->getLocaleCode(); // Mage::app()->getLocale()->getDefaultLocale();
        $this->api->customer['firstname'] = $billing->getFirstname();
        $this->api->customer['lastname'] = $billing->getLastname();
        $this->api->customer['zipcode'] = $billing->getPostcode();
        $this->api->customer['city'] = $billing->getCity();
        $this->api->customer['state'] = $billing->getState();
        $this->api->customer['country'] = $billing->getCountry();
        $this->api->customer['phone'] = $billing->getTelephone();
        $this->api->customer['email'] = $this->getOrder()->getCustomerEmail();

        if (isset($_SERVER['HTTP_REFERER'])) {
            $this->api->customer['referrer'] = $_SERVER['HTTP_REFERER'];
        }
        if (isset($_SERVER['HTTP_USER_AGENT'])) {
            $this->api->customer['user_agent'] = $_SERVER['HTTP_USER_AGENT'];
        }

        $this->api->customer['ipaddress'] = $_SERVER['REMOTE_ADDR'];

        if (is_object($shipping)) {
            $this->api->parseDeliveryAddress($shipping->getStreet(1));

            if ($this->api->delivery['housenumber'] == '') {
                $this->api->delivery['housenumber'] = $shipping->getStreet(2);
                $this->api->delivery['address1'] = $shipping->getStreet(1);
            }

            if ($shipping->getStreet(3) != '') {
                $this->api->delivery['housenumber'] .= ' ' . $shipping->getStreet(3);
            }

            $this->api->delivery['firstname'] = $shipping->getFirstname();
            $this->api->delivery['lastname'] = $shipping->getLastname();
            $this->api->delivery['address2'] = $shipping->getStreet(2);
            $this->api->delivery['zipcode'] = $shipping->getPostcode();
            $this->api->delivery['city'] = $shipping->getCity();
            $this->api->delivery['state'] = $shipping->getState();
            $this->api->delivery['country'] = $shipping->getCountry();
            $this->api->delivery['phone'] = $shipping->getTelephone();
            $this->api->delivery['email'] = $this->getOrder()->getCustomerEmail();
        }

        if ($gateway == 'AFTERPAY' || $gateway == 'IN3' || $gateway == 'ZINIA') {
            $this->getPakjeGemak($order);
        }

        $this->api->gatewayinfo['email'] = $this->getOrder()->getCustomerEmail();
        $this->api->gatewayinfo['phone'] = $billing->getTelephone();

        if (isset($_GET['gender'])) {
            $this->api->customer['gender'] = $_GET['gender'];
            $this->api->gatewayinfo['gender'] = $_GET['gender'];
        } else {
            $this->api->customer['gender'] = ''; // Not available
            $this->api->gatewayinfo['gender'] = ''; // Not available
        }

        if (isset($_GET['salutation'])) {
            $this->api->gatewayinfo['salutation'] = $_GET['salutation'];
        } else {
            $this->api->gatewayinfo['salutation'] = ''; // Not available
        }

        $decoded_phonenumber = urldecode($_GET['phonenumber']);
        if (!empty($decoded_phonenumber)) {
            $this->api->gatewayinfo['phone'] = $decoded_phonenumber;
            $this->api->customer['phone'] = $decoded_phonenumber;
        } else {
            $this->api->gatewayinfo['phone'] = ''; // Not available
        }

        if (isset($_GET['accountnumber'])) {
            $this->api->gatewayinfo['bankaccount'] = $_GET['accountnumber'];
            $this->api->customer['bankaccount'] = $_GET['accountnumber'];
        } else {
            $this->api->gatewayinfo['bankaccount'] = ''; // Not available
        }

        if (isset($_SERVER['HTTP_REFERER'])) {
            $this->api->gatewayinfo['referrer'] = $_SERVER['HTTP_REFERER'];
        }
        if (isset($_SERVER['HTTP_USER_AGENT'])) {
            $this->api->gatewayinfo['user_agent'] = $_SERVER['HTTP_USER_AGENT'];
        }

        if (isset($_GET['birthday'])) {
            $birthday = str_replace('/', '-', $_GET['birthday']);
            $this->api->gatewayinfo['birthday'] = $birthday;
            $this->api->customer['birthday'] = $birthday;
        } else {
            $this->api->gatewayinfo['birthday'] = ''; // Not available
        }

        if (((string)$this->_gateway === 'PAYAFTER') && ((string)$this->api->gatewayinfo['bankaccount'] !== '') && ((string)$this->api->customer['birthday'] !== '')) {
            $this->api->transaction['special'] = true;
        }

        // Check if the customer has a birthday and phone number
        $hasBirthdayAndPhone = !empty($this->api->customer['birthday']) && !empty($this->api->customer['phone']);

        // ZINIA needs a salutation (gender) as a mandatory field to
        // be a direct transaction, however, IN3 does not need this.
        $isSpecialCondition = array(
            'ZINIA' => !empty($this->api->gatewayinfo['salutation']),
            'IN3' => true
        );

        if ($hasBirthdayAndPhone && !empty($isSpecialCondition[$this->_gateway])) {
            $this->api->transaction['special'] = true;
        }

        if (in_array($this->_gateway, array("EINVOICE"))) {
            $this->api->transaction['special'] = true;
        }

        $this->api->transaction['id'] = $orderId;
        $this->api->transaction['amount'] = $amount;
        $this->api->transaction['currency'] = $currencyCode;
        $this->api->transaction['var1'] = $session->getSessionId();
        $this->api->transaction['var2'] = Mage::helper('customer')->getCustomer()->getId();
        $this->api->transaction['var3'] = Mage::app()->getStore()->getStoreId();
        $this->api->transaction['description'] = Mage::helper("msp")->__("Order") . ' #' . $orderId . Mage::helper("msp")->__("@") . $storename;
        $this->api->transaction['gateway'] = $this->_gateway;
        $this->api->transaction['issuer'] = $this->_issuer;
        $this->api->transaction['items'] = $items;
        $this->api->transaction['daysactive'] = ($this->getConfigData('pad_daysactive') !== false) ? $this->getConfigData('pad_daysactive') : $this->getConfigData('daysactive');
        $this->api->transaction['secondsactive'] = ($this->getConfigData('pad_seconds_active') !== false) ? $this->getConfigData('pad_seconds_active') : $this->getConfigData('seconds_active');

        $this->api->setDefaultTaxZones();

        $this->getItems($this->getOrder(), $currencyCode);

        $discountAmount = $this->getOrder()->getData('base_discount_amount');
        $discountAmount = $this->_convertCurrency($discountAmount, $baseCurrencyCode, $currencyCode);
        $discountAmountFinal = number_format($discountAmount, 4, '.', '');

        // Add discount line item
        if ($discountAmountFinal != 0) {
            $c_item = new MspItem('Discount', 'Discount', 1, $discountAmountFinal, 'KG', 0);
            $c_item->SetMerchantItemId('Discount');
            $c_item->SetTaxTableSelector('BTW0');
            $this->api->cart->AddItem($c_item);
        }

        $taxClass = Mage::getStoreConfig('msp_gateways/msp_' . strtolower($this->_gateway) . '/fee_tax_class');

        if ($taxClass == 0) {
            $this->_rate = 1;
        }

        $taxCalculationModel = Mage::getSingleton('tax/calculation');
        $request = $taxCalculationModel->getRateRequest(
            $quote->getShippingAddress(),
            $quote->getBillingAddress(),
            $quote->getCustomerTaxClassId(),
            Mage::app()->getStore()->getId()
        );
        $request->setStore(Mage::app()->getStore())->setProductClassId($taxClass);

        $rate = $taxCalculationModel->getRate($request);
        $bigRate = 100 + $rate;
        $feeRate = $rate / 100;

        if ($feeRate == 0) {
            $feeRate = '0.00';
        }

        $table = new MspAlternateTaxTable();
        $table->name = 'FEE';
        $rule = new MspAlternateTaxRule($feeRate);
        $table->AddAlternateTaxRules($rule);
        $this->api->cart->AddAlternateTaxTables($table);

        $total_fee = 0;
        $fee = Mage::getStoreConfig('msp_gateways/msp_' . strtolower($this->_gateway) . '/fee_amount');
        $fee_array = explode(':', $fee);

        // Fee is not configured
        if ($fee_array[0] != '') {
            $fixed_fee = str_replace(',', '.', $fee_array[0]);

            // Check for configured percentage value
            if (!empty($fee_array[1])) {
                $fee_array[1] = str_replace(',', '.', $fee_array[1]);
                $serviceCostPercentage = str_replace('%', '', $fee_array[1]);
                // if the service cost is added, then first remove it before calculating the fee
                if ($quote->getBaseServicecost()) {
                    $fee_percentage = ($quote->getBaseGrandTotal() - $quote->getBaseServicecost()) * ($serviceCostPercentage / 100);
                } else {
                    $fee_percentage = $quote->getBaseGrandTotal() * ($serviceCostPercentage / 100);
                }
                $total_fee += $fee_percentage;
            }
            $total_fee += $fixed_fee;
            $fee = $total_fee;
            $tax = ($fee / $bigRate) * $rate;
            $fee = $fee - $tax;

            // Add pay after delivery fee if enabled
            if (Mage::getStoreConfig('msp_gateways/msp_' . strtolower($this->_gateway) . '/fee')) {
                $fee_description = Mage::helper('msp')->getFeeLabel($payment_method_code);
                $c_item = new MspItem($fee_description, $fee_description, 1, $fee, 'KG', 0); // Todo adjust the amount to cents, and round it up.
                $c_item->SetMerchantItemId('payment-fee');
                $c_item->SetTaxTableSelector('FEE');
                $this->api->cart->AddItem($c_item);
            }
        }

        // Add none taxtable
        $table = new MspAlternateTaxTable();
        $table->name = 'none';
        $rule = new MspAlternateTaxRule('0.00');
        $table->AddAlternateTaxRules($rule);
        $this->api->cart->AddAlternateTaxTables($table);

        // Add shipping line item
        $title = $this->getOrder()->getShippingDescription();

        // Code below added to recalculate excluding tax for the shipping cost.
        // Older Magento installations round differently, causing a 1 cent mismatch.
        // This is why we recalculate it.
        $diff = $this->getOrder()->getShippingInclTax() - $this->getOrder()->getShippingAmount();

        if ($this->getOrder()->getShippingAmount() > 0) {
            $cost = ($diff / $this->getOrder()->getShippingAmount()) * 100;
        } else {
            $cost = $diff * 100;
        }

        $shipping_percentage = 1 + round($cost, 0) / 100;
        $shippin_exc_tac_calculated = $this->getOrder()->getShippingInclTax() / $shipping_percentage;
        $percentage = round($cost, 0) / 100;
        $price = number_format($this->_convertCurrency($shippin_exc_tac_calculated, $currentCurrencyCode, $currencyCode), 10, '.', '');
        // End code

        $table = new MspAlternateTaxTable();
        $table->name = $percentage;
        $rule = new MspAlternateTaxRule($percentage);
        $table->AddAlternateTaxRules($rule);
        $this->api->cart->AddAlternateTaxTables($table);

        $c_item = new MspItem($title, 'Shipping', 1, $price, 'KG', 0);
        $c_item->SetMerchantItemId('msp-shipping');
        $c_item->SetTaxTableSelector($percentage);
        $this->api->cart->AddItem($c_item);
        // End shipping line item

        // Add support for Fooman Surcharge
        if ($order->getFoomanSurchargeAmount() != 0) {
            $taxPercentage = round($order->getBaseFoomanSurchargeTaxAmount() / $order->getBaseFoomanSurchargeAmount(), 2);

            $surchargeFinalAmount = number_format($order->getBaseFoomanSurchargeAmount(), 4, '.', '');
            $surchargeDescription = $order->getFoomanSurchargeDescription();

            $table = new MspAlternateTaxTable();
            $table->name = $taxPercentage;
            $rule = new MspAlternateTaxRule($taxPercentage);
            $table->AddAlternateTaxRules($rule);
            $this->api->cart->AddAlternateTaxTables($table);

            $c_item = new MspItem($surchargeDescription, $surchargeDescription, 1, $surchargeFinalAmount, 'KG', 0);
            $c_item->SetMerchantItemId('fooman-surcharge');
            $c_item->SetTaxTableSelector($taxPercentage);

            $this->api->cart->AddItem($c_item);
        }

        // Onestepcheckout compat fix.
        // Some add a - when no phonenumber is added or the field is disabled
        if ($this->api->customer['phone'] == '-' || $this->api->gatewayinfo['phone'] == '-') {
            $this->api->customer['phone'] = '';
            $this->api->gatewayinfo['phone'] = '';
        }

        // All data available? Then request the transaction link
        $url = $this->api->startJSONCheckout();

        $this->getBase($orderId)->log($this->api->request_xml);
        $this->getBase($orderId)->log($this->api->reply_xml);

        if (!$this->api->error and $url == false) {
            $url = $this->api->merchant['redirect_url'] . '?transactionid=' . $orderId;
        }

        // Error
        if ($this->api->error) {
            $this->getBase()->log("Error %s: %s", $this->api->error_code, $this->api->error);

            // Add error status history
            $this->getOrder()->addStatusToHistory($this->getOrder()->getStatus(), Mage::helper("msp")->__("Error creating transaction") . '<br/>' . $this->api->error_code . " - " . $this->api->error);
            $this->getOrder()->save();

            // Raise error
            if ($this->api->error_code == '1024' && $this->_gateway == "PAYAFTER") {
                $errorMessage = Mage::helper("msp")->__("An error occured: ") . $this->api->error_code . /* " - " . $this->api->error . */
                    '<br />' . Mage::helper("msp")->__('We are sorry to inform you that your request for payment after delivery has been denied by Multifactor.<BR /> If you have questions about this rejection, you can checkout the FAQ on the website of Multifactor') . '<a href="http://www.multifactor.nl/contact" target="_blank">http://www.multifactor.nl/faq</a>' . Mage::helper("msp")->__('You can also contact Multifactor by calling 020-8500533 (at least 2 hours after this rejection) or by sending an email to ') . ' <a href="mailto:support@multifactor.nl">support@multifactor.nl</a>.' . Mage::helper("msp")->__('Please retry placing your order and select a different payment method.');
            } elseif ($this->_gateway == "EINVOICE" && $this->api->error_code == '1024') {
                $errorMessage = Mage::helper("msp")->__("An error occured: ") . $this->api->error_code . /* " - " . $this->api->error . */
                    '<br />' . Mage::helper("msp")->__('We are sorry to inform you that your request for E-invoicing has been denied.<BR /> Please select another payment method and try again');
            } else {
                $errorMessage = Mage::helper("msp")->__("An error occured: ") . $this->api->error_code . " - " . $this->api->error . '<br />' . Mage::helper("msp")->__("Please retry placing your order and select a different payment method.");
            }
            Mage::log($errorMessage);

            Mage::getSingleton('checkout/session')->addError($errorMessage);
            session_write_close();
            Mage::app()->getFrontController()->getResponse()->setRedirect(Mage::getUrl('checkout/cart'));
            Mage::app()->getResponse()->sendResponse();
            $newState = Mage_Sales_Model_Order::STATE_CANCELED;
            $statusMessage = Mage::helper("msp")->__("Canceled because of transaction request error");
            $newStatus = $this->getConfigData("void_status");

            // This triggers stock updates
            $order->cancel();
            $order->setState($newState, $newStatus, $statusMessage)->save();

            exit;
        }

        // Save payment link to status history
        if ($this->getConfigData("save_payment_link") || true) {
            $this->getOrder()->addStatusToHistory($this->getOrder()->getStatus(), Mage::helper("msp")->__("User redirected to MultiSafepay") . '<br/>' . Mage::helper("msp")->__("Payment link:") . '<br/>' . $url);
            $this->getOrder()->save();
        }

        $send_order_email = $this->getConfigData("new_order_mail");

        if ($this->getOrder()->getCanSendNewEmailFlag()) {
            if ($send_order_email == 'after_confirmation') {
                if (!$this->getOrder()->getEmailSent()) {
                    $this->getOrder()->sendNewOrderEmail();
                    $this->getOrder()->setEmailSent(true);
                    $this->getOrder()->save();
                }
            }
        }

        return $url;
    }

    /**
     * @return bool
     */
    protected function _isTestPayAfterDelivery($gateway)
    {
        $test   = ($this->getConfigData('test_api_pad') !== false) ? $this->getConfigData('test_api_pad'): $this->getConfigData('test_api');

        $isTest = ($test == MultiSafepay_Msp_Model_Config_Sources_Accounts::TEST_MODE);
        if ($isTest) {
            return true;
        }

        if ($ips = Mage::getStoreConfig('msp_gateways/' . $gateway . '/ip_filter_test_for_live_mode')) {
            if (in_array($_SERVER["REMOTE_ADDR"], explode(';', $ips))) {
                return true;
            }
        }

        return false;
    }

    /**
     * @return bool
     */
    protected function _isTestGiftcard($gateway)
    {
        $test   = ($this->getConfigData('test_api_pad') === false) ? $this->getConfigData('test_api'): $this->getConfigData('test_api_pad');
        $isTest = ($test == MultiSafepay_Msp_Model_Config_Sources_Accounts::TEST_MODE);
        if ($isTest) {
            return true;
        }
        return false;
    }

    protected function getTaxes()
    {
        $this->_getTaxTable($this->_getShippingTaxRules(), 'default');
        $this->_getTaxTable($this->_getTaxRules(), 'alternate');
        $this->_getTaxTable($this->_getShippingTaxRules(), 'alternate');
        // Add 'none' group?
    }

    protected function _getTaxTable($rules, $type)
    {
        if (is_array($rules)) {
            foreach ($rules as $group => $taxRates) {
                if ($type != 'default') {
                    $table = new MspAlternateTaxTable($group, 'true');
                    $shippingTaxed = 'false';
                } else {
                    $shippingTaxed = 'true';
                }

                if (is_array($taxRates)) {
                    foreach ($taxRates as $rate) {
                        if ($type != 'default') {
                            $rule = new MspAlternateTaxRule($rate['value']);
                            $rule->AddPostalArea($rate['country']);
                            $table->AddAlternateTaxRules($rule);
                        } else {
                            $rule = new MspDefaultTaxRule($rate['value'], $shippingTaxed);
                            $rule->AddPostalArea($rate['country']);
                            $this->api->cart->AddDefaultTaxRules($rule);
                        }
                    }
                } else {
                    $taxRate = $taxRates / 100;
                    if ($type != 'default') {
                        $rule = new MspAlternateTaxRule($taxRate);
                        $rule->SetWorldArea();

                        $table->AddAlternateTaxRules($rule);
                    } else {
                        $rule = new MspDefaultTaxRule($taxRate, $shippingTaxed);
                        $rule->SetWorldArea();
                        $this->api->cart->AddDefaultTaxRules($rule);
                    }
                }
                if ($type != 'default') {
                    $this->api->cart->AddAlternateTaxTables($table);
                }
            }
        } else {
            if (is_numeric($rules)) {
                $taxRate = $rules / 100;
                if ($type != 'default') {
                    $table = new MspAlternateTaxTable();
                    $rule = new MspAlternateTaxRule($taxRate);
                    $rule->SetWorldArea();
                    $table->AddAlternateTaxRules($rule);
                    $this->api->cart->AddAlternateTaxTables($table);
                    // print_r($table); // Validate this one!
                } else {
                    $rule = new MspDefaultTaxRule($taxRate, 'true');
                    $rule->SetWorldArea();
                    $this->api->cart->AddDefaultTaxRules($rule);
                }
            }
        }
    }

    protected function _getTaxRules()
    {
        $customerTaxClass = $this->_getCustomerTaxClass();
        if (Mage::helper('tax')->getTaxBasedOn() == 'origin') {
            $request = Mage::getSingleton('tax/calculation')->getRateRequest();
            return Mage::getSingleton('tax/calculation')->getRatesForAllProductTaxClasses($request->setCustomerClassId($customerTaxClass));
        } else {
            $customerRules = Mage::getSingleton('tax/calculation')->getRatesByCustomerTaxClass($customerTaxClass);
            $rules = array();
            foreach ($customerRules as $rule) {
                $rules[$rule['product_class']][] = $rule;
            }

            return $rules;
        }
    }

    protected function _getShippingTaxRules()
    {
        $customerTaxClass = $this->_getCustomerTaxClass();

        // Validate the returned data. Doesn't work with connect pad
        if ($shippingTaxClass = Mage::getStoreConfig(Mage_Tax_Model_Config::CONFIG_XML_PATH_SHIPPING_TAX_CLASS, $this->getOrder()->getStoreId())) {
            if (Mage::helper('tax')->getTaxBasedOn() == 'origin') {
                $request = Mage::getSingleton('tax/calculation')->getRateRequest();
                $request->setCustomerClassId($customerTaxClass)->setProductClassId($shippingTaxClass);
                return Mage::getSingleton('tax/calculation')->getRate($request);
            }
            $customerRules = Mage::getSingleton('tax/calculation')->getRatesByCustomerAndProductTaxClasses($customerTaxClass, $shippingTaxClass);
            $rules = array();
            foreach ($customerRules as $rule) {
                $rules[$rule['product_class']][] = $rule;
            }

            return $rules;
        }

        return array();
    }

    protected function _getCustomerTaxClass()
    {
        $customerGroup = $this->getOrder()->getCustomerGroupId();
        if (!$customerGroup) {
            $customerGroup = Mage::getStoreConfig('customer/create_account/default_group', $this->getOrder()->getStoreId());
        }

        return Mage::getModel('customer/group')->load($customerGroup)->getTaxClassId();
    }

    protected function getItems($order, $targetCurrencyCode)
    {
        $items = $order->getAllItems();

        foreach ($items as $item) {
            $product_id = $item->getProductId();
            foreach ($order->getAllItems() as $order_item) {
                $order_product_id = $order_item->getProductId();
                if ($order_product_id == $product_id) {
                    // $quantity = round($order_item->getQtyOrdered(), 2);
                    // Changed to solve bug with 1027 error because of product quantity mismatch.
                    $quantity = $item->getQtyOrdered();
                }
            }

            if ($item->getParentItem()) {
                continue;
            }
            $taxClass = ($item->getTaxPercent() == 0 ? 'none' : $item->getTaxPercent());
            $rate = $item->getTaxPercent() / 100;

            $table = new MspAlternateTaxTable();
            $table->name = $item->getTaxPercent();
            $rule = new MspAlternateTaxRule($rate);
            $table->AddAlternateTaxRules($rule);
            $this->api->cart->AddAlternateTaxTables($table);

            $weight = (float) $item->getWeight();
            $product_id = $item->getProductId();

            // Name and options
            $itemName = $item->getName();
            $options = $this->getProductOptions($item);
            if (!empty($options)) {
                $optionString = '';
                foreach ($options as $option) {
                    $optionString = $option['label'] . ": " . $option['print_value'] . ",";
                }
                $optionString = substr($optionString, 0, -1);

                $itemName .= ' (';
                $itemName .= $optionString;
                $itemName .= ')';
            }

            $proddata = Mage::getModel('catalog/product')->load($product_id);
            $currentCurrencyCode = Mage::app()->getStore()->getCurrentCurrencyCode();

            // $quantity = round($item->getQtyOrdered(), 2);

            $ndata = $item->getData();

            if ($this->api->transaction['gateway'] == 'KLARNA') {
                $rounding = 10;
            } else {
                $rounding = 10;
            }

            if ($ndata['price'] != 0) {
                // Test-> Magento rounds at 2 decimals so the recalculation goes wrong with large quantities.
                /*
                    $price_with_tax = $ndata['price_incl_tax'];
                    $tax_rate = $rate;
                    $divided_value = 1 + ($tax_rate);
                    $price_without_tax = $price_with_tax / $divided_value;
                    $price = round($price_without_tax, 4);
                */

                $price = number_format($this->_convertCurrency($ndata['price'], $currentCurrencyCode, $targetCurrencyCode), $rounding, '.', '');

                $tierprices = $proddata->getTierPrice();
                if (count($tierprices) > 0) {
                    $product_tier_prices = (object) $tierprices;
                    $product_price = array();
                    foreach ($product_tier_prices as $key => $value) {
                        $value = (object) $value;
                        if ($item->getQtyOrdered() >= $value->price_qty) {
                            /*
                                $price_with_tax = $value->price;
                                $tax_rate = $rate;
                                $divided_value = 1 + ($tax_rate);
                                $price_without_tax = $price_with_tax / $divided_value;
                                $price = round($price_without_tax, 4);
                            */
                            if ($ndata['price'] < $value->price) {
                                $price = $ndata['price'];
                            } else {
                                $price = $value->price;
                            }
                        }
                        $price = number_format($this->_convertCurrency($price, $currentCurrencyCode, $targetCurrencyCode), $rounding, '.', '');
                    }
                }

                // Fix for 1027 with catalog prices including tax
                if (Mage::getStoreConfig('tax/calculation/price_includes_tax')) {
                    $price = ($item->getRowTotalInclTax() / $item->getQtyOrdered() / (1 + ($item->getTaxPercent() / 100)));
                    $price = round($price, $rounding);
                }

                // Create item
                $c_item = new MspItem($itemName, $item->getDescription(), $quantity, $price, 'KG', $item->getWeight());
                $c_item->SetMerchantItemId($item->getId());
                $c_item->SetTaxTableSelector($taxClass);
                $this->api->cart->AddItem($c_item);
            }
        }
    }

    /**
     *  Send a transaction request to MultiSafepay and return the payment_url
     */
    public function startTransaction()
    {
        $session = Mage::getSingleton('customer/session');

        /**
         * We will check if the quote total is the same as the order total.
         * Throw an exception if these amounts are not the same to avoid an transaction amount mismatch!
         */
        $orderId = $this->getCheckout()->getLastRealOrderId();
        $order = $this->getOrder();
        $quote = Mage::getModel('sales/quote')->load($order->getQuoteId());

        $order_base_grand_total = $order->getBaseGrandTotal();
        $order_grand_total = $order->getGrandTotal();

        $checked_amount = $order_base_grand_total;
        $checked_amount_current = $order_grand_total;

        $gateway_data = $quote->getPayment()->getData();

        if (in_array($gateway_data['method'], $this->gateways)) {
            $this->_configCode = 'msp_gateways';
        } elseif (in_array($gateway_data['method'], $this->giftcards)) {
            $this->_configCode = 'msp_giftcards';
        }

        // Currency check
        $isAllowConvert = Mage::getStoreConfigFlag('msp/settings/allow_convert_currency');

        if ($gateway_data['method'] == 'msp') {
            $currencies = explode(',', Mage::getStoreConfig('payment/msp/allowed_currency', Mage::app()->getStore()->getId()));
        } else {
            $currencies = explode(',', Mage::getStoreConfig($this->_configCode . '/' . strtolower($gateway_data['method']) . '/allowed_currency', Mage::app()->getStore()->getId()));
        }

        $canUseCurrentCurrency = in_array(Mage::app()->getStore()->getCurrentCurrencyCode(), $currencies);

        if ($order->getGlobalCurrencyCode() == 'EUR' && Mage::getStoreConfigFlag('msp/settings/allow_convert_currency')) {
            $amount = $order_base_grand_total;
            $currencyCode = 'EUR';
        } elseif ($canUseCurrentCurrency) {
            $amount = $checked_amount_current;
            $currencyCode = Mage::app()->getStore()->getCurrentCurrencyCode();
        } elseif ($isAllowConvert) {
            $currentCurrencyCode = Mage::app()->getStore()->getCurrentCurrencyCode();
            $targetCurrencyCode = MultiSafepay_Msp_Helper_Data::CONVERT_TO_CURRENCY_CODE;

            $amount = $this->_convertCurrency($checked_amount_current, $currentCurrencyCode, $targetCurrencyCode);
            $currencyCode = MultiSafepay_Msp_Helper_Data::CONVERT_TO_CURRENCY_CODE;
        } else {
            $amount = $checked_amount;
            $currencyCode = Mage::app()->getBaseCurrencyCode();
        }

        $amount = intval((string) (round($amount * 100)));
        $amount = round($amount * $this->pay_factor);

        $storename = Mage::app()->getStore()->getName();
        $billing = $this->getOrder()->getBillingAddress();
        $shipping = $this->getOrder()->getShippingAddress();

        // Generate items list
        $items = "<ul>\n";
        foreach ($this->getOrder()->getAllVisibleItems() as $item) {
            $items .= "<li>" . ($item->getQtyOrdered() * 1) . " x : " . $item->getName() . "</li>\n";
        }
        $items .= "</ul>\n";

        // Build request
        // If selected gateway was ebon or giftcard then use those account config
        if ($gateway_data['method'] == 'msp_ebon' ||
                $gateway_data['method'] == 'msp_webgift' ||
                $gateway_data['method'] == 'msp_babygiftcard' ||
                $gateway_data['method'] == 'msp_boekenbon' ||
                $gateway_data['method'] == 'msp_degrotespeelgoedwinkel' ||
                $gateway_data['method'] == 'msp_erotiekbon' ||
                $gateway_data['method'] == 'msp_givacard' ||
                $gateway_data['method'] == 'msp_fashioncheque' ||
                $gateway_data['method'] == 'msp_fashiongiftcard' ||
                $gateway_data['method'] == 'msp_gezondheidsbon' ||
                $gateway_data['method'] == 'msp_lief' ||
                $gateway_data['method'] == 'msp_parfumcadeaukaart' ||
                $gateway_data['method'] == 'msp_parfumnl' ||
                $gateway_data['method'] == 'msp_wijncadeau' ||
                $gateway_data['method'] == 'msp_podium' ||
                $gateway_data['method'] == 'msp_vvvgiftcard' ||
                $gateway_data['method'] == 'msp_sportenfit' ||
                $gateway_data['method'] == 'msp_beautyandwellness' ||
                $gateway_data['method'] == 'msp_yourgift' ||
                $gateway_data['method'] == 'msp_good4fun'
        ) {
            $api = $this->getGatewaysApi(null, $order, $gateway_data['method']);
        } else {
            $api = $this->getApi();
        }

        $api->merchant['notification_url'] = $this->_notification_url . "?type=initial";
        $api->merchant['cancel_url'] = $this->_cancel_url;
        $api->merchant['redirect_url'] = $this->_return_url;
        $api->second_chance['send_email'] = (bool)Mage::getStoreConfig('msp_gateways/msp_' . strtolower($this->_gateway) . '/second_chance');
        $api->customer['locale'] = Mage::app()->getLocale()->getLocaleCode(); //Mage::app()->getLocale()->getDefaultLocale();

        if (is_object($billing)) {
            $this->api->parseCustomerAddress($billing->getStreet(1));

            if ($this->api->customer['housenumber'] == '') {
                $this->api->customer['housenumber'] = $billing->getStreet(2);
                $this->api->customer['address1'] = $billing->getStreet(1);
            }

            if ($billing->getStreet(3) != '') {
                $this->api->customer['housenumber'] .= ' ' . $billing->getStreet(3);
            }

            $api->customer['firstname'] = $billing->getFirstname();
            $api->customer['lastname'] = $billing->getLastname();
            $api->customer['zipcode'] = $billing->getPostcode();
            $api->customer['city'] = $billing->getCity();
            $api->customer['state'] = $billing->getState();
            $api->customer['country'] = $billing->getCountry();
            $api->customer['phone'] = $billing->getTelephone();
        }
        $api->customer['email'] = $this->getOrder()->getCustomerEmail();
        if (isset($_SERVER['HTTP_REFERER'])) {
            $api->customer['referrer'] = $_SERVER['HTTP_REFERER'];
        }
        if (isset($_SERVER['HTTP_USER_AGENT'])) {
            $api->customer['user_agent'] = $_SERVER['HTTP_USER_AGENT'];
        }

        // Add shipping details, used for PayPal
        if (is_object($shipping)) {
            $api->parseDeliveryAddress($shipping->getStreet(1));

            if ($api->delivery['housenumber'] == '') {
                $api->delivery['housenumber'] = $shipping->getStreet(2);
                $api->delivery['address1'] = $shipping->getStreet(1);
            }

            if ($shipping->getStreet(3) != '') {
                $this->api->delivery['housenumber'] .= ' ' . $shipping->getStreet(3);
            }

            $api->delivery['firstname'] = $shipping->getFirstname();
            $api->delivery['lastname'] = $shipping->getLastname();
            $api->delivery['address2'] = $shipping->getStreet(2);
            $api->delivery['zipcode'] = $shipping->getPostcode();
            $api->delivery['city'] = $shipping->getCity();
            $api->delivery['state'] = $shipping->getState();
            $api->delivery['country'] = $shipping->getCountry();
            $api->delivery['phone'] = $shipping->getTelephone();
            $api->delivery['email'] = $this->getOrder()->getCustomerEmail();
        }

        $api->transaction['id'] = $orderId;
        $api->transaction['amount'] = $amount;
        $api->transaction['currency'] = $currencyCode;
        $api->transaction['var1'] = $session->getSessionId();
        $api->transaction['var2'] = Mage::helper('customer')->getCustomer()->getId();
        $api->transaction['var3'] = Mage::app()->getStore()->getStoreId();
        $api->transaction['description'] = Mage::helper("msp")->__("Order") . ' #' . $orderId . Mage::helper("msp")->__("@") . $storename;
        $api->transaction['items'] = $items;
        $api->transaction['gateway'] = $this->_gateway;
        $api->transaction['daysactive'] = $this->getConfigData("daysactive");
        $api->transaction['secondsactive'] = $this->getConfigData("seconds_active");
        if ($api->transaction['gateway'] == '') {
            $api->transaction['gateway'] = $this->_gateway;
        }

        $mybank_issuer = '';
        $session = Mage::getSingleton('checkout/session');
        $payment_data = $session->getData('payment_additional');

        if (is_object($payment_data)) {
            $iss_mybank = $payment_data->msp_mybank_issuer;

            if (!empty($iss_mybank)) {
                $mybank_issuer = $iss_mybank;
            } elseif ($this->_gateway == "CREDITCARD") {
                $api->transaction['gateway'] = $payment_data->msp_creditcard_cc;
            }

            // Start tokenization
            $tokenization = Mage::getStoreConfigFlag('msp/settings/enable_tokenization');

            if ($tokenization && Mage::getSingleton('customer/session')->isLoggedIn()) {
                $customerID = Mage::helper('customer')->getCustomer()->getId();
                $recurring_hash = $payment_data->recurring_hash;
                if (isset($recurring_hash) && $recurring_hash != "") {
                    $mspHelper = Mage::helper('msp/data');
                    $recurring = $mspHelper->getTokenizationByRecurringHash($recurring_hash);
                    if ($recurring->getCustomerId() !== $customerID) {
                        $recurring = null;
                    }
                } elseif (!is_null($customerID) && $payment_data->cc_save === 'true') {
                    $cc_name = $payment_data->cc_name;
                    $cc_name = (isset($cc_name)) ? $cc_name : null;

                    $model = Mage::getModel('msp/tokenization');
                    $mspHelper = Mage::helper('msp/data');

                    $model->setData('customer_id', $customerID);
                    $model->setData('recurring_hash', $mspHelper->uniqueHash());
                    $model->setData('order_id', $orderId);
                    $model->setData('cc_type', $this->_gateway);
                    $model->setData('cc_name', $cc_name);
                    $model->save();
                }
            }
        }

        if ($this->_gateway == 'IDEAL') {
            $api->transaction['gateway'] = 'IDEAL';
            $api->merchant['redirect_url'] = $this->_return_url;
            $url = $api->startJSONTransaction('direct');
        } elseif ($this->_gateway == 'BIZUM') {
                $api->transaction['gateway'] = 'BIZUM';
                $api->merchant['redirect_url'] = $this->_return_url;
                $url = $api->startJSONTransaction('direct');
        } elseif ($this->_gateway == 'MYBANK' && $mybank_issuer) {
            $api->transaction['issuer'] = $mybank_issuer;
            $api->transaction['gateway'] = 'MYBANK';
            $api->merchant['redirect_url'] = $this->_return_url;
            $api->extravars = $mybank_issuer;
            $url = $api->startJSONTransaction('direct');
        } elseif ($this->_gateway == 'BANKTRANS' && Mage::getStoreConfig('msp_gateways/msp_banktransfer/direct_transfer')) {
            $api->startJSONTransaction('direct');

            if (!$api->error) {
                Mage::getSingleton('checkout/session')->getQuote()->setIsActive(false);
                Mage::getSingleton('checkout/session')->getQuote()->save();
            }

            $url = Mage::getUrl("checkout/onepage/success/", array("_secure" => true));
        } elseif (in_array($this->_gateway, array('INGHOME', 'CBC', 'KBC', 'TRUSTLY'))) {
            $url = $api->startJSONTransaction('direct');
        } elseif (isset($recurring) && in_array($this->_gateway, array('VISA', 'MASTERCARD', 'AMEX'))) {
            $api->recurring_id = $mspHelper->decrypt($recurring->recurring_id);
            $api->startJSONTransaction('direct');

            if (!$api->error) {
                Mage::getSingleton('checkout/session')->getQuote()->setIsActive(false);
                Mage::getSingleton('checkout/session')->getQuote()->save();
            }

            $url = Mage::getUrl("checkout/onepage/success/", array("_secure" => true));
        } else {
            $url = $api->startJSONTransaction('redirect');
        }

        $this->getBase($orderId)->log($api->request_xml);
        $this->getBase($orderId)->log($api->reply_xml);

        // Error
        if ($api->error) {
            $this->getBase()->log("Error %s: %s", $api->error_code, $api->error);

            // Add error status history
            $this->getOrder()->addStatusToHistory($this->getOrder()->getStatus(), Mage::helper("msp")->__("Error creating transaction") . '<br/>' . $api->error_code . " - " . $api->error);

            if ($orderId = !'') {
                $this->getOrder()->save();
                // Raise error
                $errorMessage = Mage::helper("msp")->__("An error occured: ") . $api->error_code . " - " . $api->error . '<br />' . Mage::helper("msp")->__("Please retry placing your order and select a different payment method.");
                Mage::log($errorMessage);

                Mage::getSingleton('checkout/session')->addError($errorMessage);
                session_write_close();
                Mage::app()->getFrontController()->getResponse()->setRedirect(Mage::getUrl('checkout/cart'));
                Mage::app()->getResponse()->sendResponse();
            } else {
                $errorMessage = Mage::helper("msp")->__("An error occured: ") . '<br />' . Mage::helper("msp")->__("Please retry placing your order and select a different payment method.");
                Mage::log($errorMessage);

                Mage::getSingleton('checkout/session')->addError($errorMessage);
                session_write_close();
                Mage::app()->getFrontController()->getResponse()->setRedirect(Mage::getUrl('checkout/cart'));
                Mage::app()->getResponse()->sendResponse();
            }
            if ($order->getState() != Mage_Sales_Model_Order::STATE_PROCESSING && !$order->hasInvoices()) {
                $newState = Mage_Sales_Model_Order::STATE_CANCELED;
                $statusMessage = Mage::helper("msp")->__("Canceleld because of transaction request error");
                $newStatus = $this->getConfigData("void_status");

                $order->cancel(); // this triggers stock updates
                $order->setState($newState, $newStatus, $statusMessage)->save();
            }
            exit;
        }

        // Save payment link to status history
        if ($this->getConfigData("save_payment_link") || true) {
            $this->getOrder()->addStatusToHistory($this->getOrder()->getStatus(), Mage::helper("msp")->__("User redirected to MultiSafepay") . '<br/>' . Mage::helper("msp")->__("Payment link:") . '<br/>' . $url);
            $this->getOrder()->save();
        }

        $send_order_email = $this->getConfigData("new_order_mail");
        if ($this->getOrder()->getCanSendNewEmailFlag()) {
            if ($send_order_email == 'after_confirmation') {
                if (!$this->getOrder()->getEmailSent()) {
                    $this->getOrder()->sendNewOrderEmail();
                    $this->getOrder()->setEmailSent(true);
                    $this->getOrder()->save();
                }
            }
        }

        return $url;
    }

    public function notification($orderId, $initial = false)
    {
        // Get the order
        /** @var $order Mage_Sales_Model_Order */
        $order = Mage::getSingleton('sales/order')->loadByIncrementId($orderId);

        $base = $this->getBase($orderId);

        // Check lock
        if ($base->isLocked()) {
            $base->preventLockDelete();

            if ($initial) {
                return false;
            } else {
                return false;
            }
        }

        // Lock
        $base->lock();

        $orderexist = $order->getIncrementId();

        if ($orderexist) {
            $payment_method_code = $order->getPayment()->getMethodInstance()->getCode();
        } else {
            $orderId = $_GET['transactionid'];
            $payment_method_code = '';
        }

        // Get the status
        if (in_array($payment_method_code, array('msp_payafter', 'msp_klarna', 'msp_einvoice'))) {
            $api = $this->getPayAfterApi($orderId, $order);
        } elseif ($payment_method_code == 'msp_ebon' ||
                $payment_method_code == 'msp_webgift' ||
                $payment_method_code == 'msp_babygiftcard' ||
                $payment_method_code == 'msp_boekenbon' ||
                $payment_method_code == 'msp_degrotespeelgoedwinkel' ||
                $payment_method_code == 'msp_erotiekbon' ||
                $payment_method_code == 'msp_givacard' ||
                $payment_method_code == 'msp_fashioncheque' ||
                $payment_method_code == 'msp_fashiongiftcard' ||
                $payment_method_code == 'msp_gezondheidsbon' ||
                $payment_method_code == 'msp_lief' ||
                $payment_method_code == 'msp_parfumcadeaukaart' ||
                $payment_method_code == 'msp_parfumnl' ||
                $payment_method_code == 'msp_podium' ||
                $payment_method_code == 'msp_vvvgiftcard' ||
                $payment_method_code == 'msp_sportenfit' ||
                $payment_method_code == 'msp_beautyandwellness' ||
                $payment_method_code == 'msp_wijncadeau' ||
                $payment_method_code == 'msp_yourgift' ||
                $payment_method_code == 'msp_good4fun'
        ) {
            $api = $this->getGatewaysApi(null, $order, $payment_method_code);
        } else {
            $api = $this->getApi($orderId);
        }

        $api->transaction['id'] = $orderId;
        $status = $api->getJSONStatus();

        // Log the transaction status requests and responses
        $this->getBase($orderId)->log($this->api->request_xml);
        $this->getBase($orderId)->log($this->api->reply_xml);

        /** @var $helper MultiSafepay_Msp_Helper_Data */
        $helper = Mage::helper('msp');
        /** @var $quote Mage_Sales_Model_Quote */
        $quote = Mage::getSingleton('sales/quote')->load($order->getQuoteId());
        $isRestored = $helper->restoreCart($quote, $status);
        $base->log("Quote was restored: " . ($isRestored ? 'TRUE' : 'FALSE'));

        if ($api->error) {
            $base->unlock();
            Mage::throwException(Mage::helper("msp")->__("An error occured: ") . $api->error_code . " - " . $api->error);
            echo 'Error : ' . $api->error_code . " - " . $api->error;
            exit();
        }

        // Determine status
        $status = strtolower($status);

        // Update order status in Magento
        $ret = false;
        if ($orderexist) {
            $ret = $base->updateStatus($order, $status, $api->details);
        }

        // Unlock
        $base->unlock();

        return $ret;
    }

    /**
     * @param float  $amount
     * @param string $currentCurrencyCode
     * @param string $targetCurrencyCode
     * @return float
     */
    protected function _convertCurrency($amount, $currentCurrencyCode, $targetCurrencyCode)
    {
        if ($currentCurrencyCode == $targetCurrencyCode) {
            return $amount;
        }

        $currentCurrency = Mage::getModel('directory/currency')->load($currentCurrencyCode);
        $rateCurrentToTarget = $currentCurrency->getAnyRate($targetCurrencyCode);

        if ($rateCurrentToTarget === false) {
            Mage::throwException(Mage::helper("msp")->__("Imposible convert %s to %s", $currentCurrencyCode, $targetCurrencyCode));
        }

        // Disabled check, fixes PLGMAG-10. Magento seems to not to update USD->EUR rate in db, resulting in wrong conversions.
        // Now we calculate the rate manually and and don't trust Magento stored rate.
        // if (strlen((string) $rateCurrentToTarget) < 12) {
        $revertCheckingCode = Mage::getModel('directory/currency')->load($targetCurrencyCode);
        $revertCheckingRate = $revertCheckingCode->getAnyRate($currentCurrencyCode);
        $rateCurrentToTarget = 1 / $revertCheckingRate;
        //}

        return round($amount * $rateCurrentToTarget, 2);
    }

    /**
     * @param Mage_Sales_Model_Order $order
     * @return bool
     */
    protected function getPakjeGemak(Mage_Sales_Model_Order $order)
    {
        if (Mage::helper('core')->isModuleEnabled('TIG_PostNL')) {
            $postnl_helper = Mage::helper('postnl');
            $pakje_gemak = $postnl_helper->getPakjeGemakAddressForOrder($order);

            if ($pakje_gemak) {
                $this->api->parseDeliveryAddress($pakje_gemak->getStreetFull());

                if ($this->api->delivery['housenumber'] == '') {
                    $this->api->delivery['housenumber'] = $pakje_gemak->getStreet2();
                    $this->api->delivery['address1'] = $pakje_gemak->getStreet1();
                }

                if ($pakje_gemak->getStreet3() != '') {
                    $this->api->delivery['housenumber'] .= $pakje_gemak->getStreet3();
                }

                $this->api->delivery['address2'] = '';
                $this->api->delivery['company'] = $pakje_gemak->getCompany();
                $this->api->delivery['zipcode'] = $pakje_gemak->getPostcode();
                $this->api->delivery['city'] = $pakje_gemak->getCity();
                $this->api->delivery['country'] = $pakje_gemak->getCountryId();
                $this->api->delivery['phone'] = $pakje_gemak->getTelephone();
                $this->api->delivery['email'] = $this->getOrder()->getCustomerEmail();

                return true;
            }
        }
        return false;
    }

    /**
     * Only return whole quantity values when quantity is a whole number
     *
     * @param $item
     * @return mixed
     */
    protected function getQtyFormatted($item)
    {
        $quantity = $item->getQtyOrdered();
        if (fmod($quantity, 1) === 0.0) {
            return $quantity * 1;
        }
        return $quantity;
    }


}
