Mostrar precios en moneda local y cobrar en la moneda base en WooCommerce
Muchas tiendas quieren mostrar los precios en moneda local pero cobrar en la moneda base: los visitantes navegan en euros, rupias o dólares, mientras que todos los pagos pasan por una sola cuenta de pasarela en una sola moneda. WooCommerce puede hacerlo, con una regla que determina todas las configuraciones siguientes: la moneda que se muestra en la página de finalización de compra es la moneda en la que se cobra al cliente. Esta guía cubre las tres maneras de organizarlo con FOX, los efectos secundarios de cada una y el caso contrario, en el que los clientes pagan en la moneda que han seleccionado.
Un pedido, una moneda
Un pedido de WooCommerce guarda una sola moneda. Cualquiera que sea la moneda activa cuando se crea el pedido, se escribe en él, y la pasarela de pago recibe el total como un número en esa moneda. FOX convierte los precios para mostrarlos y decide qué moneda está activa en la finalización de compra; no convierte el importe en su camino hacia el banco. Por eso "mostrar USD y cobrar INR sin avisar" no puede funcionar: la pasarela tomaría 30 USD como 30 INR. En cambio, la propia finalización de compra tiene que cambiar a la moneda en la que cobras, y el cliente ve el importe real antes de pagar, lo que además evita disputas por una moneda inesperada en el extracto de la tarjeta.
El cambio se controla con Es múltiple permitido (Is multiple allowed) en la pestaña Avanzado (Advanced) de los ajustes de FOX (WooCommerce → Ajustes → Moneda).
Mostrar precios en moneda local pero cobrar en la moneda base
Cuando la moneda en la que cobras es la moneda base de WooCommerce, no hace falta código. Establece Es múltiple permitido (Is multiple allowed) en No y guarda; una instalación nueva de FOX empieza con Sí (Yes). Entonces:
- la tienda, las páginas de producto y el carrito muestran la moneda del visitante, elegida mediante el selector o mediante tus reglas GeoIP;
- en la página de finalización de compra, FOX restablece la moneda a la moneda base, de modo que los totales, el pedido y el pago están todos en la moneda base;
- todos los pedidos se guardan en la moneda base, lo que mantiene los informes y la contabilidad en una sola moneda.
Los clientes merecen saberlo antes de llegar al paso del pago. Dos opciones integradas en la pestaña Opciones (Options) muestran el importe local junto al real: Mostrar monto aproximado (Show approximate amount) añade un valor (Approx. ...) a los totales del carrito y de la finalización de compra, y Mostrar aprox. precio (Show approx. price) hace lo mismo en las páginas de la tienda y de producto. Ambas usan la moneda del país del visitante de la pestaña GeoIP, así que necesitan reglas GeoIP, y ambas se calculan a partir de los tipos de cambio, no de precios fijos. El texto se puede cambiar con el filtro woocs_get_approximate_amount_text. Un aviso sencillo en la página clásica del carrito también ayuda:
/*
* Cart notice when the shop is shown in a currency that is not charged.
* Child theme functions.php or a code snippets plugin.
*/
add_action('woocommerce_before_cart', function () {
global $WOOCS;
if (!isset($WOOCS) || $WOOCS->current_currency === $WOOCS->default_currency) {
return;
}
wc_print_notice(
sprintf(
'Prices in %s are shown for information. Your order will be charged in %s.',
esc_html($WOOCS->current_currency),
esc_html($WOOCS->default_currency)
),
'notice'
);
});
El efecto secundario: la tienda se queda en la moneda base después de la finalización de compra
FOX recuerda la última moneda de cada visitante, y el restablecimiento en la página de finalización de compra es un cambio de moneda como cualquier otro. Un visitante que abre la finalización de compra y vuelve a la tienda ve la moneda base, y las reglas GeoIP no devuelven la moneda local, porque solo se aplican en la primera visita. El fragmento de la sección siguiente recuerda la moneda del visitante antes de la finalización de compra y la restablece después. Con Es múltiple permitido (Is multiple allowed) = No, úsalo con tu moneda base en las dos líneas de ajustes: la finalización de compra se comporta como antes, y el visitante recupera su moneda cuando sale de ella.
Forzar una moneda de pago que no sea la moneda base
Cuando la pasarela acepta una moneda distinta de la moneda base, o solo algunas de tus monedas, establece Es múltiple permitido (Is multiple allowed) en Sí (Yes) y fuerza la moneda de pago con código. Con No, el restablecimiento a la moneda base se impondría al código. El fragmento siguiente fuerza la moneda de pago solo para las monedas que la pasarela no puede cobrar, y devuelve al visitante su propia moneda en la siguiente página fuera de la finalización de compra:
/*
* Charge only in currencies the payment gateway accepts.
* Requires FOX: Advanced tab, Is multiple allowed = Yes.
* Child theme functions.php or a code snippets plugin.
*/
add_action('template_redirect', function () {
if (!class_exists('WOOCS') || !function_exists('WC')) {
return;
}
global $WOOCS;
$accepted = array('USD', 'EUR'); // currencies the gateway can charge
$fallback = 'USD'; // checkout currency for all other currencies
// Custom checkout page: is_checkout() || is_page('your-checkout-slug')
if (is_checkout()) {
if (!in_array($WOOCS->current_currency, $accepted, true)) {
$WOOCS->storage->set_val('woocs_before_checkout', $WOOCS->current_currency);
$WOOCS->set_currency($fallback);
if (WC()->cart) {
WC()->cart->calculate_totals();
}
}
return;
}
// Outside checkout: restore the currency the visitor had before
$previous = $WOOCS->storage->get_val('woocs_before_checkout');
if (!empty($previous)) {
$WOOCS->storage->set_val('woocs_before_checkout', '');
$WOOCS->set_currency($previous);
}
}, 1);
Para forzar una sola moneda para todos, enumera solo esa moneda en $accepted y úsala como $fallback. Puntos que comprobar:
- Páginas de finalización de compra personalizadas.
is_checkout()es verdadero en la página establecida como finalización de compra en WooCommerce → Ajustes → Avanzado y en las páginas que contienen el shortcode de finalización de compra. Una finalización de compra creada con un plugin de embudos o de checkout puede no ser ninguna de las dos; añade la condiciónis_page()del comentario. - Pago por reglas de GeoIP (Checkout by GeoIP rules) debe estar desactivado. Esta opción de la pestaña Avanzado (Advanced) cambia la finalización de compra a la moneda del país del visitante y anula la moneda forzada.
- Páginas de la tienda en caché. La restauración se ejecuta cuando WordPress genera una página, así que, tras una caché de página, ocurre en la primera página que no se sirve desde la caché.
Las versiones más sencillas de una línea de este código, en nuestra FAQ forzar una moneda en la página de finalización de compra, fuerzan la moneda sin la restauración.
Cambiar la moneda según el método de pago
FOX no puede reaccionar por sí mismo a un clic en un método de pago: en la finalización de compra clásica, elegir un método no recarga nada. Los dos fragmentos siguientes hacen que WooCommerce actualice el resumen del pedido cuando cambia el método y que cambie la moneda en esa actualización. Funcionan con la finalización de compra del shortcode [woocommerce_checkout], no con el bloque de finalización de compra, y necesitan Es múltiple permitido (Is multiple allowed) = Sí (Yes). El ID de un método de pago es el valor de su botón de opción en la página de finalización de compra, por ejemplo bacs para la transferencia bancaria directa.
/*
* Classic checkout: change currency when a payment method is chosen.
* Child theme functions.php.
*/
add_action('woocommerce_checkout_update_order_review', function ($post_data) {
if (!class_exists('WOOCS')) {
return;
}
global $WOOCS;
parse_str($post_data, $data);
$currency_by_method = array(
'bacs' => 'EUR', // payment method ID => currency it charges in
'stripe' => 'USD',
);
$method = isset($data['payment_method']) ? $data['payment_method'] : '';
if (isset($currency_by_method[$method]) && $WOOCS->current_currency !== $currency_by_method[$method]) {
if (!$WOOCS->storage->get_val('woocs_before_checkout')) {
$WOOCS->storage->set_val('woocs_before_checkout', $WOOCS->current_currency);
}
$WOOCS->set_currency($currency_by_method[$method]);
}
});
add_action('wp_footer', function () {
if (!is_checkout()) {
return;
}
?>
<script>
jQuery(function ($) {
$(document.body).on('payment_method_selected', function () {
$(document.body).trigger('update_checkout');
});
});
</script>
<?php
});
Lo inverso viene integrado y no necesita código: la pestaña Pagos (Payments) oculta o muestra cada pasarela para las monedas elegidas (Reglas de pagos (Payments rules) y Comportamiento de pagos (Payments behavior)), de modo que una pasarela solo se ofrece en las monedas que puede cobrar. Consulta cómo ocultar una pasarela de pago según la moneda.
Dejar que los clientes paguen en la moneda que han seleccionado
La configuración opuesta es Es múltiple permitido (Is multiple allowed) = Sí (Yes) sin ningún código de forzado. La finalización de compra mantiene la moneda del visitante, el pedido se guarda en ella junto con el tipo de cambio de ese momento, y se le pide a la pasarela que cobre en esa moneda. Tu código puede leer el ajuste como $WOOCS->is_multiple_allowed.
La finalización de compra o el carrito vuelven a la moneda base
- Es múltiple permitido (Is multiple allowed) sigue en No. Es la causa en la mayoría de los casos; la moneda vuelve a cambiar después de la finalización de compra explica el comportamiento predeterminado.
- Pago por reglas de GeoIP (Checkout by GeoIP rules) está activado y el país del visitante pertenece a otra moneda.
- El código del tema o de un fragmento llama a
$WOOCS->set_currency()en la página de finalización de compra. Búscalo, incluidas las versiones antiguas de los fragmentos anteriores. - Desactivar en páginas (Disable on pages) en la pestaña Opciones (Options) desactiva FOX para la raíz del sitio. WooCommerce envía las actualizaciones de la finalización de compra a la dirección raíz (
/?wc-ajax=update_order_review), así que el resumen del pedido se recalcula sin FOX y muestra la moneda base un instante después de cargar la página. - La página del carrito o de finalización de compra está en caché, por lo que muestra la moneda de quien la cargó primero. Excluye ambas de toda caché.
La pasarela debe aceptar todas las monedas de pago
FOX entrega a la pasarela la moneda del pedido; que el pago se complete depende de la cuenta de la pasarela. PayPal y Stripe aceptan muchas monedas de presentación, pero cada uno tiene su propia lista, y un pago recibido en otra moneda lo convierte el proveedor con su propio tipo de cambio y sus comisiones. Revisa las listas, para PayPal en monedas aceptadas por PayPal, y usa la pestaña Pagos (Payments) para que una moneda nunca llegue a una pasarela que no pueda cobrarla. Una pasarela de una sola moneda, habitual en los proveedores locales, debe usar una de las configuraciones de forzado anteriores.
Probar un pago en moneda extranjera de forma segura
FOX no tiene un modo de prueba de pagos propio; usa el entorno de pruebas o el modo de prueba de la pasarela. Haz un pedido de prueba en cada moneda que aceptes y compara después tres lugares: la Moneda de la orden (Order currency) en el cuadro de FOX de la pantalla del pedido, el importe en el panel de pruebas de la pasarela y el correo electrónico del pedido. Los tres deben mostrar la misma moneda y el mismo importe.
Qué suponen los pedidos en varias monedas para el back office
Los pedidos, los reembolsos y los correos de los pedidos están en la moneda del cliente, y los informes de WooCommerce no los convierten por sí solos a una única moneda. Cada pedido conserva su Tipo de cambio de orden (Order currency rate), en el que se basan las guías sobre analítica multimoneda y dónde se guarda la moneda del pedido. Cambiar Es múltiple permitido (Is multiple allowed) más adelante no convierte los pedidos existentes; un pedido concreto se puede convertir con Cambiar moneda de orden (Change order currency) y Volver a calcular el pedido (Recalculate order) en el cuadro de FOX de la pantalla del pedido, lo que cambia el registro del pedido, no el pago ya cobrado.
Qué configuración elegir
| Tu situación | Configuración |
|---|---|
| La pasarela cobra solo en la moneda base | Es múltiple permitido (Is multiple allowed) = No, importes aproximados activados, fragmento de restauración opcional |
| La pasarela cobra en una moneda que no es la base | Sí (Yes) + fragmento de forzado con una sola moneda aceptada |
| La pasarela acepta algunas de tus monedas | Sí (Yes) + fragmento de forzado con la lista de monedas aceptadas |
| Pasarelas distintas para monedas distintas | Sí (Yes) + reglas de la pestaña Pagos (Payments), o el fragmento por método de pago |
| Se puede cobrar en todas las monedas | Sí (Yes), sin código |
Si la finalización de compra sigue mostrando una moneda que no esperabas, prueba con un tema predeterminado y solo WooCommerce y FOX activos, y luego abre un tema en el foro de soporte de FOX con tu ajuste de Es múltiple permitido (Is multiple allowed), el tipo de finalización de compra (shortcode o bloque) y cualquier código de moneda que uses, y lo revisaremos.