Table of Contents

Multi-Currency Support in FoxyCart

How Multi-Currency Functionality works in FoxyCart

FoxyCart includes multi-currency in a couple ways - both changing the currency of the whole cart and dynamically converting a price from one currency to another.

There are two parameters that you can use to handle transactions in different currencies: template_set and price.

template_set: session wide locale setting

The template set paramater is passed through as a session-wide variable, as the code of the respective template set as specified in the administration, such as &template_set=fr. The template set is not product specific, but changes the currency (and also possibly language) for the customer's entire cart for that session. View the template set page for details on adding and using the sets for your store.

By default, new customers will see a cart in your store's default locale, as set in the DEFAULT template set (or alternatively from the “store locale” setting on the store's setting page).

You can specify a template set with a normal call to your store's /cart endpoint. Note that changing the template_set to one with a different locale than the cart is currently set to will empty the cart. You can however add products in the same request that you change the template_set, and they'll be added appropriately.

price: per product with currency code appended

The currency for a specific product can also be set by appending the 3-character ISO currency code, eg: &price=15.99usd

If a product is added in a currency that does not match the current locale of the cart (for example, with a store that is set to USD, and a product is added to the cart as price=50mxn), the products price will be dynamically converted to the cart currency. If no currency code is appended to a product's price, it will be assumed as the store's default currency, and dynamically converted from that to the current currency of the cart.

Dynamic price conversions currently require that a store have at least two different template sets with differing locales be configured. The rate used in the conversion is requested from openexchangerates.org.

Product Option Modifiers

If modifying the price of a product using a product option modifier, you should append the currency code to the price, otherwise it will be assumed to be in the store's default currency. For example:

<input type="checkbox" name="gift_wrapping" value="Yes{p+15CAD}" />

Payment Gateway Settings

If your gateway supports multiple currencies on a single account, great! You're all set. If you need one set of credentials (username/password/ID/transaction key/etc) per currency, you can enter them like this:

{"USD": "x39gA5Me2K", "GBP": "9s77FvP6ts"}

A few things to note:

MultiCurrency and Discounts

Product discounts, category discounts, and coupon codes can all handle multi-currency functionality with some different syntax. Please make sure you familiarize yourself with how coupons and discounts work before continuing.

For multi-currency discounts, you can use syntax like this:

&discount_quantity_amount=bogo 100{"discount_type": "repeat", "USD": "2-10", "MXN": "2-150"}

A few things to note. First, the syntax must be valid JSON, so that means double quotes around all the values. Second (and because of the double quotes), you must URL encode this string, or you must wrap the whole thing in single quotes instead of double quotes. Otherwise the double quotes will get in the way of your valid HTML.

For a form input it'll look very similar:

<form action="https://foxycart-demo.foxycart.com/cart">
	<input type="hidden" name="name" value="975mxn bogo 2">
	<input type="hidden" name="price" value="975MXN">
	<input type="hidden" name="code" value="abc130">
	<!-- Note that we're using single quotes on the next value,
		 because form inputs don't handle URL encoding -->
	<input type="hidden" name="discount_quantity_amount" 
		value='bogo 100{"discount_type": "repeat", "USD": "2-10", "MXN": "2-150"}'>
	<input type="submit">
</form>

This syntax is the same for category discounts and for coupons, except you'll put the JSON right in the coupon or discount details input. This allows setting custom discounts per currency. If a currency is not included, the discount will not apply. This is to prevent discounts from applying that could have significantly wrong values after the conversion math is done.

Some Examples of MultiCurrency Usage

Let's assume your store's default template set's locale is en_US, so it will be using the USD $. A customer sees a price in Mexican pesos (MXN). The customer adds the product to the cart, and the values in MXN will convert to USD:

<a href="https://foxycart-demo.foxycart.com/cart?name=$50 MXN Product without template set&price=50mxn&code=a33938">
	$50 MXN, no template set
</a>

Let's say you wanted to add that product to the cart in MXN Pesos, instead of having it convert to the default (or current) currency. You'd simply create a template set that specifies the Mexican locale, and pass in the template_set value as it's code, like below. Note that this would clear the cart's contents if the cart was previously in a different currency.

<a href="https://foxycart-demo.foxycart.com/cart?name=$50 MXN Product with template set&price=50mxn&code=a33938&template_set=mx">
	$50 MXN, es_MX locale template set
</a>

At this point, if you added a product in a different currency (or without a currency code in the price value), the price would be converted to MXN Pesos.

One common use case would be to set the currency on pageload, perhaps if the customer clicks a link or lands on a specific subdomain. To create a link that sets the template_set silently (ie. it sets the FoxyCart session but doesn't take them to the cart), it'd look like this (with a callback):

<a id="locale-mxn" href="javascript:;">Set locale to MXN in the background</a>
<script>
	document.getElementById('locale-mxn').onclick = function(){
		FC.client.request('https://'+FC.settings.storedomain+'/cart?template_set=mx')
		.done(function(data){
			console.log(data.locale_info.int_curr_symbol);
		});
	};
</script>