Integrating with our Currency Switcher is quite straightforward, and it involves calling two filters provided by our plugins. One filter provides access to the automatic conversion function, while the other returns a list of the enabled currencies. By using filters, the integration will be transparent: when the Currency Switcher is not installed, your plugin will works as it does normally (no currency conversion will be performed, the values passed to the filters will be returned as normal). Thanks to this architecture, you won't have to add conditions to check if the plugin is installed, or call specific currency conversion functions.
The integration with our plugin can be implemented in two ways:
- A basic integration introduces automatic conversion of all currency prices, using exchange rates.
- An advanced integration, with per-currency pricing, requires more work, as you have to add new fields to allow customers to enter prices in multiple currencies, but it will give your users greater flexibility.
Important - How to check Currency Switcher instance was loaded
As long as you use the filters provided by the Currency Switcher, you should not need to add checks to determine if the plugin was loaded. For example, passing a value for conversion would require the following call:
$converted_amount = apply_filters('wc_aelia_cs_convert', $amount, $from_currency, $to_currency);
This call will work whether the Currency Switcher is active or not. When the plugin is not active, the filter will have no effect, and you will receive the same value you passed to it.
If you still need to check if the Currency Switcher is active, for some specific reason, you can do so by checking the content of the global $GLOBALS['woocommerce-aelia-currencyswitcher']. That variable contains the instance of the Aelia Currency Switcher. If it's not empty, then the Currency Switcher has been loaded.
If your plugin introduces new product types (e.g. Bundles, Subscriptions, Gift Cards), the Currency Switcher will invoke a filter that allows you to specify a callback function, where you can perform the conversion of the product prices. The flow is the following:
- The Currency Switcher is going to process a product and determines its type (simple, variable, grouped, bundle, subscription, gift card, etc).
- Our plugin calls filter wc_aelia_currencyswitcher_product_convert_callback, passing the product to be converted to it and expecting a callable in return.
- If a callable is returned, the Currency Switcher passes the product to it, so that it can be processed, and takes not further action. If no callback is returned, our plugin attempts to perform the conversion itself. In such case, when a custom product is detected, the Currency Switcher raises a warning, indicating that it cannot process custom product type (this is because a custom product has its own internal pricing logic, of which our Currency Switcher cannot be aware).
Sample plugins, with processing of custom products
1.2. Plugins that do not introduce custom products
If your plugin does not introduce new product types, you won't need to register a callback. In such case, you will simply have to invoke the conversion functions where you normally load your costs/fees.
Sample plugins, with processing of product fees
The free Product Fees plugin, which was released in 2015 by WooThemes, was designed to be single-currency. We extended it to demonstrate how easy is to allow merchants to set fees in multiple currencies, and to load them dynamically, while still keeping 100% compatibility with single-currency sites. Our changes have not been integrated in the official releases, you can find them in our forked repository: https://github.com/aelia-co/WooCommerce-Product-Fees.
Please note that we modified the Product Fees when it was released, to provide a proof of concept. The official plugin has been updated several times since we first changed it, therefore you should just use our code as a reference.
2. Basic integration
Code example: http://pastebin.com/ASBhBJ0w
A basic integration with our Currency Switcher requires a couple of lines of code. The integration can be summarised as follows: when customers enter a price (e.g. 10 USD, where "USD" is the shop base currency), you simply have to pass the amount to the conversion functions before using it, and the Currency Switcher will take care of the calculations.
Generally, any amount that was entered in shop's base currency has to be passed to the Currency Switcher for conversion, before being processed further by your plugin. The modification consists in adding one single step (in bold, below) to the logic you have now:
- A price is entered in base currency in the backend.
- When you need to use the price, load it from the database.
- Pass the price to the currency conversion filter.
- Use the price as you do now.
You can find the code to invoke the currency conversion logic here, ready to copy/paste in your plugin: http://pastebin.com/ASBhBJ0w.
3. Advanced integration - Per-currency pricing (optional, but recommended)
Code example: http://pastebin.com/AJs6jTkX
Out of the box, the Currency Switcher handles prices of products and shipping in multiple currencies (see screenshot). That is, instead of setting a product price to 100 USD and having EUR, GBP and so calculated automatically, it's possible to enter a price for each currency, such as 100 USD, 200 EUR, 300 GBP (example figures). Conversion rates are ignored, and the manually entered prices are used instead.
To provide a more comprehensive set of features, you might be interested in considering the possibility of adding such feature to your plugin as well. For example, you could allow customers to enter prices as follows:
- USD: 100 (regular), 90 (sale)
- EUR: 95 (regular), 85 (sale)
- GBP: 90 (regular), 80 (sale)
This, of course, is an example that refers to a generic product. The same logic would apply to your custom pricing fields.
Per-currency pricing is one of the most requested features for all multi-currency plugins, and, although it would require some more changes, it should be fairly straightforward to implement. Here's the summary of the changes:
- Instead of one set of amount fields (regular price, sale price, etc), display one set per currency. The Currency Switcher can give you the list of enabled currencies with one line of code.
- Validate, save and load all the prices. For example, instead of $prices[regular][amount] and $prices[sale][amount], you could have
- $prices[USD][regular][amount]- $prices[USD][sale][amount]
- $prices[GBP ][sale][amount]
And so on. Showing the prices on the Admin UI, storing and retrieving them will be up to you, and you can use any logic you like, remaining independent from our Currency Switcher implementation. When you will save the prices, you will just have to associate the two values to the appropriate currency. For example, the prices could be stored as an array:
// Array of product prices
'USD' => array(
'regular' => 100,
'sale' => 90,
'EUR' => array(
'regular' => 90,
'sale' => 80,
'GBP' => array(
'regular' => 80,
'sale' => 70,
- The conversion method described in the Basic Integration section requires a minimal modification to support extra prices. You can find an example here: http://pastebin.com/AJs6jTkX (note the additional $prices_per_currency argument). The call to the conversion method should pass the array of currency amounts as well (ref. #3 above), so that the method can pick them up automatically. When an amount is not passed for a currency (e.g. if the AUD price is left empty, like in the example), then the automatic conversion will take place.
Both the above integrations will allow for a loose coupling with the Currency Switcher. As anticipated, everything in your plugin will work fine whether our Currency Switcher is installed or not:
- When our plugin is installed, you will have to handle prices for each of the available currencies (e.g. USD, EUR, GBP).
- When our plugin is not installed, the enabled_currencies() method will still return an array of currencies, which only contains one currency (the base one). All conversion functions will return you the same value you pass to them (i.e. no conversion will occur).