Doble conversión de moneda en WooCommerce: precios del carrito demasiado altos
La doble conversión de moneda en WooCommerce se manifiesta siempre igual: la página de producto dice CAD 218 y el carrito dice CAD 304. El precio se multiplicó dos veces por el tipo de cambio. FOX convierte un precio una sola vez, así que una segunda conversión siempre implica un segundo actor en la cadena: otro plugin, el tema, código personalizado o un ajuste que infla la tasa. Esta guía explica cómo se produce la segunda conversión, cómo distinguirla de una simple tasa errónea, cómo encontrar el plugin responsable y cómo corrigen los desarrolladores su propio código.
Cómo acaba un precio convertido dos veces
Con Es múltiple permitido (Is multiple allowed) en Sí (Yes) (pestaña Avanzado (Advanced) de WooCommerce → Ajustes → Moneda), los clientes pagan en la moneda que han seleccionado, así que FOX convierte el precio del producto en el origen: cada vez que cualquier código llama a $product->get_price(), recibe el importe en la moneda seleccionada. Eso es correcto mientras el código solo lea precios.
El problema empieza con los plugins que leen un precio, lo modifican y lo vuelven a escribir. Los plugins de opciones y complementos de producto, descuentos dinámicos, precios B2B y mayoristas, reservas, suscripciones, stock multialmacén y similares suelen hacerlo en el carrito: llaman a get_price(), que ya devuelve 218 CAD para un producto con precio de 157 USD, añaden su parte y guardan el resultado con set_price(). WooCommerce conserva el número que recibe como precio de ese artículo del carrito. Cuando el carrito vuelve a leer el precio, FOX convierte 218 como si fuera USD, y el carrito muestra 304. La página de producto nunca pasa por este paso, por eso sigue siendo correcta.
Las otras vías que llevan al mismo resultado:
- Dos conversores de moneda. La función multimoneda propia de WooCommerce (parte de WooPayments), un tema con un selector de moneda integrado o un segundo plugin de monedas convierten también el precio. Solo uno de ellos puede estar activo.
- Funciones de precio del tema. Un tema que construye por su cuenta las cadenas de precio, por ejemplo para los rangos de productos variables, puede aplicar de nuevo un valor ya convertido.
- Tu propio código, que establece precios del carrito o convierte importes que FOX ya convirtió.
Con Es múltiple permitido (Is multiple allowed) en No, los precios se mantienen internamente en la moneda base y FOX convierte solo lo que se muestra. Por eso una doble conversión que desaparece en ese modo apunta directamente a un plugin que vuelve a escribir los precios.
¿Doble conversión o tasa errónea? Comprueba la proporción
Divide el precio erróneo entre el correcto y compara el resultado con la tasa de la moneda en la pestaña Divisas (Currencies).
| Lo que ves | A qué apunta |
|---|---|
| Página de producto correcta, carrito o finalizar compra demasiado altos; erróneo ÷ correcto es igual a la tasa | Doble conversión por un plugin, el tema o código personalizado |
| Erróneo solo en algunos productos (variables, con opciones, reservables) | El plugin que gestiona esos productos |
| Todas las páginas demasiado altas en una moneda, incluida la página de producto | La tasa o el valor de interés de esa moneda, no una doble conversión |
| Precios correctos en el sitio, pero el correo del pedido o la página de pago los multiplican de nuevo | La conversión de moneda propia de una pasarela de pago |
El síntoma contrario, un precio que no cambia en absoluto cuando el visitante cambia de moneda, tiene otras causas; consulta el selector de moneda no cambia los precios.
Descarta primero los ajustes
- Interés. El campo situado después del
+en la columna Tasa +% (Rate+%) añade una cantidad a la tasa. Un número simple se suma tal cual: en una tienda con precios en rupias pakistaníes,5convierte la tasa USD de 0,0036 en 5,0036, lo que hace que todos los precios de esa moneda sean unas 1400 veces más altos. Para un porcentaje, escríbelo con el signo, por ejemplo3%. - La propia tasa. Pulsa el botón de actualizar junto a la tasa y compárala con una referencia. Si el agregador devuelve valores absurdos, cámbialo; consulta los tipos de cambio no se actualizan.
- La moneda base. La fila marcada como base debe tener tasa 1 y ningún interés, y los precios de los productos deben introducirse en esa moneda. Una tienda cuyos precios están en USD mientras la base de FOX es EUR se desvía en un factor constante en todas las monedas.
Encuentra el plugin que vuelve a convertir
Trabaja en una copia de pruebas del sitio, no en la tienda en producción, y usa un producto y una moneda que no sea la base en todas las pruebas.
- Anota el precio en la página de producto y en el carrito en esa moneda.
- Pon Es múltiple permitido (Is multiple allowed) en No, guarda, vacía el carrito y vuelve a añadir el producto. Si ahora el carrito es correcto, un plugin está volviendo a escribir los precios. Vuelve a poner Sí (Yes) para los pasos siguientes.
- Desactiva todos los plugins excepto WooCommerce y FOX y cambia a un tema por defecto como Storefront. Vacía el carrito y prueba. El carrito ya debería coincidir con la página de producto.
- Reactiva los plugins uno a uno, empezando por todo lo que toque precios: opciones de producto, descuentos, mayoristas, reservas, suscripciones, inventario. Vacía el carrito y vuelve a añadir el producto después de cada uno: algunos plugins guardan su precio en el artículo del carrito cuando se añade.
- Cuando el carrito falle, el plugin que acabas de activar es el culpable. Vuelve a activar el tema al final para comprobarlo también.
Las cachés de página y el almacenamiento del navegador pueden mostrar un carrito antiguo. Límpialos, o prueba en una ventana privada, antes de sacar conclusiones de cada paso.
Solución: adaptaciones, ajustes y código
El culpable es un plugin de terceros
Muchos plugins de precios populares ya tienen una adaptación; busca el tuyo en la lista de compatibilidad y aplica el código publicado. Si no está allí, FOX Labs acepta solicitudes de adaptación para plugins muy utilizados. Hay otras dos opciones: comprueba si el plugin tiene un ajuste para tiendas multimoneda o una conversión propia que puedas desactivar, o pon Es múltiple permitido (Is multiple allowed) en No, de modo que los clientes vean los precios en su moneda y paguen en la moneda base; mostrar precios locales cobrando en la moneda base explica qué cambia para los clientes.
El culpable es tu propio código
La regla es sencilla: get_price() te da la moneda seleccionada, set_price() debe recibir la moneda base. Convierte el resultado de vuelta con el filtro woocs_back_convert_price antes de guardarlo:
/*
* Custom cart prices on a FOX shop with "Is multiple allowed" = Yes.
* Child theme functions.php or a code snippets plugin.
*/
add_action('woocommerce_before_calculate_totals', function ($cart) {
if (is_admin() && !wp_doing_ajax()) {
return;
}
if (did_action('woocommerce_before_calculate_totals') >= 2) {
return; // run once per request, or the change is applied again
}
foreach ($cart->get_cart() as $cart_item) {
$product = $cart_item['data'];
$price = (float) $product->get_price(); // already in the selected currency
$price = $price * 1.10; // your logic, for example +10 %
// back to the base currency, so FOX converts it only once;
// with "Is multiple allowed" = No the value passes through unchanged
$product->set_price(apply_filters('woocs_back_convert_price', $price, true));
}
}, 20);
Al ser un filtro, el código sigue funcionando si se desactiva FOX: el valor pasa sin modificarse. Los importes fijos de tu lógica (una tarifa de 5,00, un recargo) son importes en moneda base; añádelos después de convertir de vuelta, no antes.
Si tu código calcula un precio que ya es final en la moneda seleccionada, por ejemplo a partir de su propia tabla de precios por moneda, indica a FOX que no lo toque con woocs_skip_conversion. FOX llama a este filtro antes de convertir el precio de un producto; devolver true deja ese precio como está:
/*
* Mark cart products whose price you set in the selected currency,
* for example inside woocommerce_before_calculate_totals:
* $product->set_price($final_price);
* $product->update_meta_data('_price_is_final', 'yes'); // kept in memory, the product is not saved
*/
add_filter('woocs_skip_conversion', function ($skip, $price, $product) {
if ($product instanceof WC_Product && $product->get_meta('_price_is_final') === 'yes') {
return true;
}
return $skip;
}, 10, 3);
El filtro recibe el producto solo con Es múltiple permitido (Is multiple allowed) en Sí (Yes), que es el modo en el que se produce este problema.
Si el carrito sigue mal
- Prueba siempre con un carrito nuevo. Un artículo antiguo del carrito puede llevar un precio que un plugin guardó al añadirlo.
- Comprueba que solo hay un conversor de moneda activo, incluidos el multimoneda propio de WooCommerce y los selectores de moneda integrados en el tema.
- Si el carrito es correcto y solo el total de finalizar compra o el pedido es erróneo, revisa los plugins de tarifas, envío y pago, que añaden sus propios importes al total.
- Compara con la breve lista de comprobación de precio convertido dos veces en la página de finalizar compra si el problema aparece solo al finalizar la compra.
Si el aislamiento señala a un plugin que aún no tiene adaptación, publica su nombre, su versión y el tipo de producto que falla en el foro de soporte de FOX.