I have a bit of a dilemma with a Magento website I am building. I have two websites with a store each set up in order to enable multiple currencies checkout for each site. So th
After I searched for an answer to this and stumbled across the same question being asked since 2009 without a definite solution, I finally had to look into the deep end of the code myself - and voila, I have a working solution. Here a detailed guide for anyone who wants to set up Magento with
The main problem with this combination is that with the default Magento structure you can only ever do one or the other, not the two combined.
So lets set Magento up for multiple currencies first.
In your .htaccess file add this at the top (replace the appropriate website domains and code you entered when setting up the websites (here http://website-us.local with base_us and http://website-uk.local with code base_uk)
SetEnvIf Host website-us.local MAGE_RUN_CODE=base_us SetEnvIf Host website-us.local MAGE_RUN_TYPE=website SetEnvIf Host ^website-us.local MAGE_RUN_CODE=base_us SetEnvIf Host ^website-us.local MAGE_RUN_TYPE=website
SetEnvIf Host website-uk.local MAGE_RUN_CODE=base_uk SetEnvIf Host website-uk.local MAGE_RUN_TYPE=website SetEnvIf Host ^website-uk.local MAGE_RUN_CODE=base_uk SetEnvIf Host ^website-uk.local MAGE_RUN_TYPE=website
Overwrite the method convertPrice in Mage/Core/Model/Store and change the method convertPrice - this will ensure that the prices are always displayed in the correct conversion AND the correct currency sign.
/**
* Convert price from default currency to current currency
*
* @param double $price
* @param boolean $format Format price to currency format
* @param boolean $includeContainer Enclose into <span class="price"><span>
* @return double
*/
public function convertPrice($price, $format = false, $includeContainer = true)
{
$categories = Mage::getModel('catalog/category')->getCollection();
$categ_ids=$categories->getAllIds();
$baseCurrencyCode = Mage::app()->getBaseCurrencyCode();
$allowedCurrencies = Mage::getModel('directory/currency')->getConfigAllowCurrencies();
$currencyRates = Mage::getModel('directory/currency')->getCurrencyRates($baseCurrencyCode,array_values($allowedCurrencies));
if ($this->getCurrentCurrency() && $this->getBaseCurrency()) {
$value = $this->getBaseCurrency()->convert($price, $this->getCurrentCurrency());
} else {
$value = $price;
}
if($this->getCurrentCurrencyCode() != $baseCurrencyCode)
{
$value = $price * $currencyRates[$this->getCurrentCurrencyCode()];
}
if ($this->getCurrentCurrency() && $format) {
$value = $this->formatPrice($value, $includeContainer);
}
return $value;
}
}
But of course we also want to share the users data, cart and login throughout the websites we just set up.
While in default config scope set System - Configuration - Customer Configuration - Account Sharing Options - Share Customer Accounts to Global
Overwrite magento/app/code/core/Mage/Checkout/Model/Session.php and replace this method:
protected function _getQuoteIdKey() { return 'quote_id'; //return 'quote_id_' . $websites[1]; }
Overwrite magento/app/code/core/Mage/Sales/Model/Quote.php and change the method getSharedStoreIds to:
public function getSharedStoreIds() { $ids = $this->_getData('shared_store_ids'); if (is_null($ids) || !is_array($ids)) { $arrStoreIds = array(); foreach(Mage::getModel('core/website')->getCollection() as $website) { $arrStoreIds = array_merge($arrStoreIds,$website->getStoreIds()); } return $arrStoreIds; /*if ($website = $this->getWebsite()) { return $website->getStoreIds(); } var_dump($this->getStore()->getWebsite()->getStoreIds());exit(); return $this->getStore()->getWebsite()->getStoreIds(); */ } return $ids; }
Overwrite magento/app/code/core/Mage/Customers/Model/Customer.php and change again the method getSharedWebsiteIds() to:
public function getSharedWebsiteIds() { $ids = $this->_getData('shared_website_ids'); if ($ids === null) { $ids = array(); if ((bool)$this->getSharingConfig()->isWebsiteScope()) { $ids[] = $this->getWebsiteId(); } else { foreach (Mage::app()->getWebsites() as $website) { $ids[] = $website->getId(); } } $this->setData('shared_website_ids', $ids); } return $ids; }
If you use the wishlist option you should do the same for the method in magento/app/code/core/Mage/Wishlist/Model/Wishlist.php and change getSharedWebsiteIds so it not only loads the store ids from the current website but from all of them
Now we also have to implement a currency (website) switch on the frontend stores and pass the correct session ids inbetween so magento knows what stores to look for. I imitated the currency switch here and added the following dropdown to
magento/app/design/frontend/default/yourtheme/template/directory/currency.phtml
This loads all websites and applies the current Session Id as a query string so magento knows on any domain which session to use.
<?php
/**
* Currency switcher
*
* @see Mage_Directory_Block_Currency
*/
?>
<div class="top-currency">
<?php
$websites = Mage::getModel('core/website')->getCollection();
$this_session_id = Mage::getSingleton('core/session', array('name' => 'frontend'))->getSessionId();
?>
<select id="website-changer" onChange="document.location=this.options[selectedIndex].value">
<?php
foreach($websites as $website):
$default_store = $website->getDefaultStore();
$website_currency = $default_store->getBaseCurrency()->getCurrencyCode();
$url_obj = new Mage_Core_Model_Url();
$default_store_path = $url_obj->getBaseUrl(array('_store'=> $default_store->getCode()));
$default_store_path .= Mage::getSingleton('core/url')->escape(ltrim(Mage::app()->getRequest()->getRequestString(), '/'));
$default_store_path = explode('?', $default_store_path);
$default_store_path = $default_store_path[0] . '?SID=' . $this_session_id;
?>
<option <? if(strstr($default_store_path,Mage::getBaseUrl())):?>selected="selected"<?endif; ?> value="<?=$default_store_path ?>">
<?=$website_currency?>
</option>
<?endforeach;?>
</select>
</div>
This query string will only be applied the first time you switch but magento will remember the session id after that stored in a cookie.
magento/app/code/core/Mage/Core/Model/Session/Abstract/Varien.php
and
replace this
// potential custom logic for session id (ex. switching between hosts)
$this->setSessionId();
with
// potential custom logic for session id (ex. switching between hosts)
/* Amend to ensure shopping carts are shared between websites */
if (isset($_COOKIE['lastsid']))
{
session_decode(file_get_contents(Mage::getBaseDir('session').'/sess_'.$_COOKIE['lastsid']));
setcookie ('lastsid', '', time() - 3600);
}
if (isset($_GET['SID']))
{
$this->setSessionId($_GET['SID']);
session_decode(file_get_contents(Mage::getBaseDir('session') . '/sess_' . $_GET['SID']));
setcookie('lastsid', $_GET['SID']);
$_COOKIE['lastsid'] = $_GET['SID'];
}
else
{
$this->setSessionId();
}
/* Amend end */
This should now display multiple currencies, charge in multiple currencies across mutliple websites and on top of this share logins and shopping carts. This solution is a collection of knowledge I found on the interwebs combined with a few bits and pieces I figured out myself, so thanks for anyone who gave advice!