FOX - WooCommerce Currency Switcher Professional

WooCommerce PayPal Currency Not Supported: How to Keep Selling

"WooCommerce PayPal currency not supported" comes in several forms: the PayPal button disappears when a visitor switches to their local currency, the payment fails with CURRENCY_NOT_SUPPORTED or error 10605, or PayPal Payments answers 422 UNPROCESSABLE_ENTITY. In each case PayPal was asked to charge a currency it will not take for your account. A currency switcher can show any currency, but it cannot change what PayPal accepts, so the fix is to decide which currency reaches PayPal. Below are the checks to make first, three ways to keep selling, and the separate CANNOT_MIX_CURRENCIES error.

Why PayPal refuses a currency

PayPal works with a fixed list of currencies, shorter than the list you can add to WooCommerce. Some currencies on it are in-country only: MYR, for example, is accepted only by PayPal accounts registered in Malaysia. Whether a currency works therefore depends on the currency and on the country of the receiving account. The list is in PayPal currency codes, with notes in accepted PayPal currencies.

On the shop side, a WooCommerce order has one currency, and the gateway is asked to charge the order total in that currency. FOX decides which currency is active when the order is created. It does not convert the amount on its way to PayPal and has no setting for "show MYR, charge USD" inside one order; the general rule is explained in show prices in local currency, charge in base currency. So every working setup makes the checkout itself run in a currency PayPal accepts.

Check these before changing anything

  • The currency code is a real ISO code. PayPal matches the three-letter code exactly: EUR, not EURO. A wrong code in the FOX currency row hides the PayPal button for that currency. A custom currency code can never be charged by PayPal. If PayPal fails even for USD or EUR, clear the code field in the FOX row, type it again by hand and save: a pasted code can carry invisible characters.
  • The error also happens with a supported currency. Then the currency is not the cause. Test logged out with caching and JavaScript optimization switched off; pages served from a cache and delayed scripts are behind many "currency" errors, see currency switcher stuck loading after JS optimization.
  • No filter that "adds" the currency to PayPal. Code that extends woocommerce_paypal_supported_currencies only makes the button appear. The order is still created in that currency and PayPal still refuses it at the payment step. Remove such code.
  • Only one plugin sets the currency. A second multi-currency module (in a toolkit plugin or a payments plugin) changes the currency at payment time behind FOX's back. FOX shows a notice on the WooCommerce settings screens when WooPayments has its own multi-currency option switched on. Keep one of them.

Three ways to keep selling when PayPal cannot take a currency

1. Offer PayPal only in currencies it can charge

No code is needed. In the Advanced tab of the FOX settings switch Payments rules on and save; a Payments tab appears. In the row of your PayPal gateway select the currencies PayPal cannot take, with Payments behavior set to Is hidden (or select the ones it can take with Is shown). FOX applies the rule on the checkout page and on the payment page of an existing order. Visitors keep seeing their local currency everywhere and pay with another gateway, or switch to a PayPal currency themselves. More on the rules in how to hide a payment gateway by currency.

2. Switch to a PayPal currency on the checkout page

Visitors browse in their own currency, and when they open the checkout FOX switches the currencies PayPal cannot take to one it can. The order is created in that currency, so PayPal accepts it. This needs Is multiple allowed = Yes in the Advanced tab, and Checkout by GeoIP rules switched off, because that option sets the checkout currency by country and would override the switch. Every target currency must also be in your FOX currency list; set_currency() falls back to the base currency for a code the shop does not have.

/*
 * FOX + PayPal: on the checkout page, switch currencies PayPal cannot
 * charge to one it can. Child theme functions.php or a code snippets plugin.
 */
function myshop_paypal_currency_map() {
    return array(
        // currency PayPal cannot charge => currency to charge instead
        'AED' => 'USD',
        'MAD' => 'EUR',
    );
}

function myshop_switch_to_paypal_currency() {
    global $WOOCS;
    if ( ! is_object( $WOOCS ) ) {
        return false;
    }
    $map = myshop_paypal_currency_map();
    if ( ! isset( $map[ $WOOCS->current_currency ] ) ) {
        return false;
    }
    $WOOCS->set_currency( $map[ $WOOCS->current_currency ] );
    return true;
}

// Checkout page load; the payment page of an existing order keeps its currency
add_action( 'template_redirect', function () {
    if ( ! function_exists( 'is_checkout' ) || ! is_checkout()
        || is_checkout_pay_page() || is_order_received_page() ) {
        return;
    }
    if ( myshop_switch_to_paypal_currency() && WC()->cart ) {
        WC()->cart->calculate_totals();
    }
}, 1 );

// Checkout refreshes after address or shipping changes, after FOX's own handler
add_action( 'woocommerce_checkout_update_order_review', 'myshop_switch_to_paypal_currency', 10000 );

Know the side effects before you use it. The switch applies to every gateway on the checkout, not only to PayPal. The customer sees the totals change currency when the checkout opens, so say so in a line of text on the checkout page. And the visitor stays in the new currency after leaving the checkout; the longer snippet in the article on showing local prices and charging the base currency, linked above, restores the previous currency if you need that.

3. Charge everything in a PayPal-supported base currency

If your WooCommerce base currency is one PayPal accepts, set Is multiple allowed to No. Visitors see converted prices, and the checkout, the order and the payment are in the base currency. Show approximate amount in the Options tab adds the local equivalent, in the currency of the visitor's country from the GeoIP rules, to the cart and checkout totals. If the base currency itself is not on PayPal's list, this option cannot work: use option 2 with Yes, or option 1.

PayPal Payments specifics

  • The buttons keep the currency of the page load. The PayPal script is loaded with the currency active when the page was built. If the currency changes later on the same page, for example by country at checkout, the buttons still work with the old one and fail with an error such as "Expected currency from order api call to be USD, got EUR". Avoid changing the currency on the checkout page after it has loaded, or make sure the page reloads.
  • With Is multiple allowed = No, FOX hands the PayPal Payments script the base currency, so the buttons match the base-currency checkout.
  • Buttons outside the checkout. Smart buttons on product pages, the cart and the mini cart create the PayPal order before the customer reaches the checkout. The checkout switch of option 2 does not apply to them, so they still send the unsupported currency, and with option 3 they cause the mixed-currency error described below. With either option, show the PayPal buttons only on the checkout page in the button location settings of PayPal Payments.
  • Pay Later is offered only for certain countries and their currencies. With other currencies PayPal's own script reports errors in the browser console; switch the Pay Later messages off if most of your customers pay in other currencies.
  • Refunds from the order screen are made in the order's currency, and FOX stays out of that request. The exception is a shop with the Professional extension of PDF Invoices & Packing Slips, Smart Coupons or Advanced Coupons active; there add_filter( 'woocs_disable_backend_refund_calculation', '__return_true' ); keeps FOX out. FOX reads this filter while it loads, before the theme, so put the line in a must-use plugin (a PHP file in wp-content/mu-plugins starting with <?php), not in functions.php.

CANNOT_MIX_CURRENCIES: orders fail after a currency switch

PayPal Payments reports 422 UNPROCESSABLE_ENTITY with CANNOT_MIX_CURRENCIES when one payment is built from two currencies: the PayPal order was created in one, and the shop then sends amounts or confirms the payment in another. It typically appears only for customers who switched currency, and only some of the time. Three causes account for it.

Cached pages carry another currency

A page with PayPal buttons loads the PayPal script with the currency of that page. If the page came from a page cache, that is the currency of whoever was cached first, while the visitor's cart is in their own. Exclude from every cache the checkout, the cart and any product page that shows PayPal buttons, and keep FOX's cache handling on for the rest of the shop, as described in why a currency switcher and a page cache fight each other.

The payment request looks like a new visitor

The PayPal buttons talk to your site through background requests. FOX finds the visitor's currency in its storage: a cookie with PHP Session and FOX Session, the IP address with Transient, or a browser key with Transient and the cache option on. A request that arrives without that identity is treated like a first visit, so the welcome currency or the GeoIP rules decide its currency, and the PayPal order can be built in a currency the cart does not use. That happens when:

  • the browser key is not attached because an optimizer delays FOX's front.js, which adds the key to the PayPal buttons' requests (fix the exclusions from the article linked in the checks above);
  • the visitor's IP address changes between page load and payment, which mobile networks do, while Currency storage is Transient without the cache option. FOX Session keeps the currency in the visitor's own cookie instead.

Is multiple allowed = No with buttons outside the checkout

In this mode the PayPal script receives the base currency, while a button on a product page or in the cart builds the order from a cart shown in the visitor's currency. Show the buttons on the checkout page only, or switch to Yes and fix the payment currency with option 2.

Checklist

  • Every currency code in FOX is a valid ISO code, retyped if in doubt.
  • Your PayPal account can receive each currency that reaches PayPal, including in-country currencies.
  • No code adds currencies through woocommerce_paypal_supported_currencies, and no second multi-currency module is active.
  • One of the three setups chosen: Payments rules, a forced checkout currency, or a supported base currency.
  • Checkout, cart and pages with PayPal buttons excluded from the page cache; FOX scripts not delayed.

If PayPal still refuses a currency it supports for your account, open a topic on the FOX support forum with the exact PayPal error, your Is multiple allowed and Currency storage settings and the PayPal plugin you use, and we will look at it.