Commerce Currency Resolver

Multi-currency enhancement module for Drupal Commerce 3 that provides flexible currency resolution and automatic price conversion.

commerce_currency_resolver
1,073 sites
28
drupal.org

Install

Drupal 11, 10 v2.0.1
composer require 'drupal/commerce_currency_resolver:^2.0'

Overview

Commerce Currency Resolver is a comprehensive enhancement for handling multi-currency functionality in Drupal Commerce 3. While Commerce 3 supports multiple currencies out of the box, this module extends that capability by providing flexible methods to resolve the active currency and automatically calculate or convert prices across different currencies.

The module supports multiple currency resolution strategies including store-based (default Commerce behavior), cookie-based user selection, language-based mapping, and geolocation-based detection via GeoIP or Smart IP modules. When combined with the Commerce Exchanger module, it enables automatic price conversion using real-time exchange rates from various external providers.

The module handles currency conversion not only for product prices but also for promotions, fees, custom adjustments, taxes, and shipping rates, ensuring consistent currency handling throughout the entire order lifecycle. It includes proper cache context support for personalized content rendering and works seamlessly with Dynamic Page Cache.

Features

  • Multiple currency resolution strategies: store-based (default), cookie-based user selection, language-based mapping, and geolocation via GeoIP or Smart IP
  • Three price handling modes: dedicated price fields per currency, automatic conversion via exchange rates, or combo mode combining both approaches
  • Automatic currency conversion for order items, promotions, fees, custom adjustments, and shipping rates during order processing
  • Currency selector block that allows visitors to manually choose their preferred currency stored in a cookie
  • Language-to-currency mapping with admin UI to assign currencies to each site language
  • Country-to-currency mapping via geolocation services (GeoIP or Smart IP) with flexible matrix configuration
  • Override of Commerce core promotion offers (OrderFixedAmountOff, OrderItemFixedAmountOff) to support multi-currency amounts
  • Override of Commerce Fee plugins (OrderFixedAmount, OrderItemFixedAmount) for multi-currency fee calculations
  • Override of Commerce Shipping flat rate methods for automatic currency conversion of shipping rates
  • Custom cache context (currency_resolver) for proper caching of currency-dependent content
  • Order processor that detects currency mismatches and triggers order recalculation when needed
  • Event subscriber that monitors order loads and refreshes currency when the user's resolved currency differs from the order currency
  • Configurable field prefix pattern for creating dedicated price fields per currency (e.g., field_price_eur, field_price_usd)
  • Integration with Commerce VADO for discount price compatibility

Use Cases

International e-commerce with multiple currencies

An online store selling products internationally with prices displayed in customer's local currency. Use the GeoIP or Smart IP submodule to automatically detect visitor location and display prices in their local currency. Enable the Exchanger submodule for automatic price conversion from your base currency.

Multilingual site with currency per language

A website with multiple language versions where each language should use a specific currency (e.g., English site uses USD, German site uses EUR). Enable the Language submodule and configure language-to-currency mapping. Prices will automatically switch when users change languages.

User-selectable currency preference

Allow visitors to manually choose their preferred currency regardless of their location or language. Enable the Cookie submodule and place the currency selector block in your theme. Users can select their preferred currency which persists across sessions via cookie.

Dedicated prices per currency with fallback

Products have specific prices set for major currencies but should automatically convert for other currencies. Use combo mode with dedicated price fields (e.g., field_price_eur, field_price_usd) for main currencies. When a field is empty, the Exchanger submodule automatically calculates the price from your base currency.

Fully automatic multi-currency store

Manage products in a single base currency with all other currencies calculated automatically. Enable the Exchanger submodule and set currency source to 'Automatic conversion'. All prices, promotions, fees, and shipping rates will be automatically converted using your configured exchange rate provider.

Shipping with multi-currency support

Offer shipping rates that automatically adjust to the customer's currency. Enable both the Exchanger and Shipping submodules. Your flat rate shipping methods will automatically convert rates, or you can configure specific amounts per currency in the shipping method settings.

Tips

  • For best caching performance, use the 'currency_resolver' cache context on any render arrays that depend on the current currency.
  • The cookie name for currency selection can be customized via settings.php using Settings::set('commerce_currency_cookie', 'your_cookie_name').
  • When adding order items programmatically, use the commerce_currency_resolver.price_resolver service to resolve the correct price before creating the order item.
  • Currency resolver priorities determine precedence: Cookie (1000) > GeoIP/Smart IP (900) > Language (800) > Store (default). Higher priority resolvers are checked first.
  • For reverse proxy setups with the Cookie submodule, the currency can be passed via X-header (X_COMMERCE_CURRENCY by default) instead of reading the cookie directly.
  • Use the 'fields' configuration in promotions, fees, and shipping methods to set specific amounts per currency. Empty fields will fall back to automatic conversion.
  • The CURRENCY_RESOLVER_SKIP_REFRESH flag can be set on order data to prevent automatic currency refresh for specific orders.
  • The CURRENCY_RESOLVER_FORCE_REFRESH flag can be used to force currency refresh on orders programmatically, even for orders that wouldn't normally trigger refresh.

Technical Details

Admin Pages 4
Currency resolver /admin/commerce/config/commerce_currency_resolver/settings

Main configuration page for Commerce Currency Resolver. Configure how currencies are resolved and how prices are calculated for different currencies.

Language mapping /admin/commerce/config/commerce_currency_resolver/language

Map site languages to currencies. When enabled, the currency will be resolved based on the current user's language. Requires the Language submodule.

GeoIP mapping /admin/commerce/config/commerce_currency_resolver/geoip

Map countries to currencies using GeoIP geolocation. When enabled, the currency will be resolved based on the visitor's detected country. Requires the GeoIP submodule.

Smart IP mapping /admin/commerce/config/commerce_currency_resolver/smart_ip

Map countries to currencies using Smart IP geolocation. Functionally identical to GeoIP mapping but uses the Smart IP module for geolocation. Requires the Smart IP submodule.

Permissions 1
Administer currency settings

Allows users to configure all Currency Resolver settings including main configuration, language mapping, and geolocation mapping.

Hooks 5
hook_commerce_promotion_offer_info_alter

Alters promotion offer plugin definitions to replace core OrderFixedAmountOff and OrderItemFixedAmountOff with currency-aware versions.

hook_commerce_fee_info_alter

Alters fee plugin definitions to replace core OrderFixedAmount and OrderItemFixedAmount with currency-aware versions.

hook_commerce_condition_info_alter

Alters condition plugin definitions to replace core OrderTotalPrice with a currency-aware version.

hook_commerce_shipping_method_info_alter

Alters shipping method plugin definitions to replace flat_rate and flat_rate_per_item with currency-aware versions.

hook_entity_view_alter

Adds currency_resolver cache context to commerce product and product variation entities to ensure proper caching.

Troubleshooting 7
Prices are not changing when currency changes

Ensure you have enabled one of the currency resolver submodules (Cookie, Language, GeoIP, or Smart IP). The base module only adds price field support. Also verify that the Internal Dynamic Page Cache module is enabled and the Page Cache module is disabled.

Page Cache module causing currency issues

The Page Cache module does not support personalized content. Disable it and use only the Internal Dynamic Page Cache module, which is designed for dynamic content like currency-dependent prices.

Exchange rate conversion not working

Ensure you have installed and configured Commerce Exchanger, enabled the commerce_currency_resolver_exchanger submodule, created at least one exchange rate provider, and selected it in the Currency Resolver settings.

Currency field not being detected

Verify that your currency-specific price fields follow the naming pattern configured in settings. Default is 'field_price_[currency_code]' in lowercase (e.g., field_price_eur for Euro). Ensure the field exists on your product variation type.

Order shows wrong currency after checkout

Orders in 'draft' state are automatically refreshed when currency changes. Once an order moves to a non-draft state (e.g., completed), the currency is locked. This is expected behavior to preserve historical order data.

Shipping rates showing wrong currency

Enable the commerce_currency_resolver_shipping submodule if you need shipping rates to be converted. Also ensure the Exchanger submodule is enabled. Alternatively, use the 'Order currency' condition on shipping methods to provide rates in specific currencies.

Promotions not applying correctly with multiple currencies

Enable the Exchanger submodule which overrides promotion offer plugins to support multi-currency amounts. You can then configure specific amounts per currency in promotion settings, or let them be auto-calculated.

Security Notes 3
  • Currency values from cookies and headers should not be trusted blindly. The module validates currency codes against enabled currencies before use.
  • Exchange rate providers may have rate limits. Monitor your usage to avoid service interruptions.
  • Geolocation-based currency resolution relies on IP addresses which can be spoofed or masked by VPNs. Consider this when making security-sensitive business decisions based on detected location.