Idioma

Contactar

Plugin de WooCommerce · desde 2014 · aka WOOCS

FOX

Un plugin de WooCommerce que muestra los precios en la divisa que elige el visitante y, opcionalmente, puede cobrar en ella.

Primera versión
Instalaciones activas
50.000+
Valoración
4.4 / 5 (250)Leer reseñas
  • PHP
  • API de hooks de WordPress
  • Filtros de producto, carrito, envío y pedido de WooCommerce
  • WooCommerce HPOS (OrderUtil, WC_Order CRUD)
  • Tablas de consulta de WooCommerce Analytics
  • Transients, sesiones PHP, Memcached, Redis
  • Planificador basado en opciones
  • WP REST API
  • jQuery, fetch API, localStorage
  • Feeds de tasas SimpleXML / JSON
Ver en wordpress.org wordpress.org

Sobre mí

FOX convierte los importes que genera WooCommerce a la divisa que selecciona el visitante, y puede permitir que el cliente pague en esa divisa. WooCommerce solo conoce una divisa de tienda, así que el plugin funciona interceptando los getters de precios de producto, las tarifas de envío, los cupones, los totales del carrito, el renderizado de pedidos y los correos, y convirtiendo cada importe una sola vez con una tasa guardada.

La dificultad es que un mismo precio recorre muchas rutas de código de WooCommerce: algunas están en caché, otras se ejecutan en peticiones en segundo plano y otras en wp-admin. Cada ruta tiene que ver la divisa correcta. La tienda usa la divisa del visitante, los correos y el editor de pedidos usan la divisa del pedido, y las exportaciones, el marcado para buscadores y las analíticas usan la divisa base. La edición premium mantiene además la REST API de WooCommerce y los payloads de webhooks en la divisa base.

Alrededor de ese núcleo están la importación de tasas desde 15 fuentes con su propio planificador y límites de coherencia, el almacenamiento de la divisa por visitante que funciona detrás de cachés de página completa, el redondeo y los formatos numéricos por divisa, los precios manuales por divisa, país y rol de usuario, y el recálculo de pedidos guardados entre divisas tanto con HPOS como con el almacenamiento de pedidos heredado.

La edición gratuita de wordpress.org ejecuta la misma clase principal, limitada a dos divisas en get_currencies().

FOX · selector de moneda

qué se resolvió

ACTIVOdesde 2014

Conversión de precios dentro de WooCommerce

shipped · 2014

Qué aportaCada precio se convierte exactamente una vez, así que los clientes nunca ven importes duplicados o erróneos. El propietario puede fijar precios por divisa, país o rol de cliente.

Problema
WooCommerce tiene una sola divisa de tienda y lee los precios a través de muchos getters, cachés y constructores de HTML. Cada importe debe convertirse exactamente una vez, y algunos importes no deben convertirse en absoluto.
Solución

Un único conversor se engancha a los getters de precio de producto con prioridad 9999. Los precios manuales tienen preferencia sobre la conversión por tasa, y existen interruptores explícitos de omisión para los importes que ya son definitivos.

Stack
  • PHP
  • Getters de producto de WooCommerce
  • post meta
Tareas · 6
Convertir una sola vez los precios de productos simples y de variaciones, en la capa de datosEnganchar los getters de precio de producto y variación con un único conversor con prioridad 9999

En el modo en que el cliente paga en la divisa seleccionada, raw_woocommerce_price() se engancha a woocommerce_product_get_price, a los getters de precio normal y de oferta y a los getters de variaciones. Al ejecutarse en 9999, queda después de otros plugins que ajustan el precio base. En el modo solo de visualización se usa únicamente el filtro raw_woocommerce_price, de modo que los importes guardados del carrito y del pedido permanecen en la divisa base.

Casos límite que gestiona el conversor: los precios vacíos pasan sin tocarse, un padre variable consultado con display=false se omite para evitar convertir el mín./máx. dos veces, y el getter de oferta devuelve una cadena vacía cuando no hay precio de oferta guardado. Sin eso, un precio de oferta vacío convertido pasa a ser 0 y WooCommerce muestra un precio tachado.

Caché de precios de variaciones compartida entre todas las divisasAñadir la divisa actual al hash de precios de variaciones para que cada divisa tenga su propia entrada

WooCommerce guarda en caché los arrays de precios calculados de un producto variable en un transient indexado por un hash de los datos de entrada del precio. Si la divisa no forma parte de ese hash, los precios convertidos del primer visitante se sirven a todos. woocommerce_get_variation_prices_hash() añade la divisa actual.

woocommerce_variation_prices() convierte entonces cada entrada, aplica los precios fijos por variación y reordena cada array con asort(). El rango de precios se lee del primer y el último elemento, y los precios fijos por divisa pueden cambiar el orden de las variaciones respecto a la divisa base.

Precios manuales por divisa, país y rol en una sola cadena de procesoUn precio fijo por divisa es definitivo; un precio por país o rol sustituye al precio base antes de la conversión por tasa

Los precios fijos se guardan como meta de producto por campo y divisa (_woocs_regular_price_EUR, _woocs_sale_price_EUR), donde -1 significa 'sin definir, usar la tasa'. Un precio fijo en la divisa del visitante se usa tal cual. En otro caso, un precio por país sustituye al precio base y el resultado se convierte con la tasa. Los precios por país agrupan países en bloques con un precio por bloque, y el país del visitante procede de la geolocalización de WooCommerce guardada en el estado del visitante.

Los precios por rol se aplican después de ese paso. Cuando hay un precio definido para el rol del usuario, sustituye al precio elegido hasta entonces, incluido un precio fijo por divisa, y se convierte con la tasa.

Cuando el precio de oferta por país se deja vacío, get_product_geo_data() copia en él el precio normal; de lo contrario el producto sería gratis en ese país. Cuando un campo fijo de oferta está vacío, la búsqueda recurre al campo fijo de precio normal.

Un filtro de precio recibe un número, no el nombre del campo de precioComparar el valor con los precios normal y de oferta guardados y, si no coincide, recurrir a una memoria de la petición

Los precios fijos se guardan por campo, pero woocommerce_product_get_price solo pasa un número. get_price_type() compara el valor entrante con los precios normal y de oferta en bruto del producto, leídos en contexto 'edit'. Si ninguno coincide, mantiene un mapa estático del primer precio visto de cada producto en la petición y trata un valor posterior mayor como el precio normal.

Es una heurística, por lo que se pasan tipos de campo explícitos siempre que quien llama los conoce. Los precios por rol usan su propia copia de la misma lógica.

Mostrar el precio de un producto en todas las divisas en un solo renderizadoCambiar la divisa actual en cada entrada y reconstruir los rangos de los tipos variable y agrupado

La lista de precios opcional bajo un producto se construye dentro de woocommerce_price_html(). Para cada divisa se cambia la divisa actual, el valor se formatea con los decimales y separadores de esa divisa, y después se restaura la divisa original.

El rango de un producto variable no puede calcularse como mín./máx. base por la tasa, porque cada variación puede tener precios fijos. _get_min_max_variation_prices() recalcula el precio de cada variación para la divisa de destino y descarta los valores cero. Los productos agrupados recorren a sus hijos y tratan de la misma manera a los hijos variables.

Permitir que otro código marque un importe como definitivo o convierta sus propios importesFiltro woocs_skip_conversion, una bandera interna de bloqueo y filtros públicos de conversión y conversión inversa

woocs_skip_conversion es lo primero que comprueba el conversor: una integración que ya fijó el precio de un artículo en la divisa activa devuelve true y el importe pasa sin tocarse. La bandera de petición woocs_block_price_hook desactiva la conversión para una sección de código, y se usa, por ejemplo, mientras se construyen los payloads de webhooks.

Para la dirección opuesta, woocs_convert_price y woocs_back_convert_price permiten a plugins de terceros convertir sus propios importes en divisa base, y convert_from_to_currency() convierte entre dos divisas cualesquiera de la tienda a través de la base: value / rate_from * rate_to.

Redondeo, decimales y formatos numéricos

shipped · 2016

Qué aportaLos precios se muestran con los decimales y separadores correctos para cada divisa, y los importes escritos por el personal o enviados a la pasarela de pago siguen siendo correctos.

Problema
Las divisas difieren en decimales y separadores, y WooCommerce los lee de opciones globales compartidas por la visualización, el análisis de importes escritos y el cálculo de impuestos.
Solución

Los valores por divisa se inyectan mediante filtros de opciones, y se desactivan en los contextos en que WooCommerce analiza entradas o redondea en la divisa base.

Stack
  • PHP
  • Filtros de opciones de WordPress
  • Funciones de formato de WooCommerce
Tareas · 5
Decimales por divisa a través de una única opción global de WooCommerceFiltrar pre_option_woocommerce_price_num_decimals con los decimales de la divisa activa

WooCommerce lee el número de decimales de una única opción. FOX responde a esa opción con el ajuste de la divisa actual, y el conversor redondea con number_format() a la misma precisión, de modo que el valor guardado del carrito y el valor mostrado coinciden.

JPY y TWD están fijados en el código como divisas sin céntimos, el administrador puede añadir más, y el filtro woocs_precision_on_calc permite a un sitio sobrescribir la precisión por divisa.

Importes en divisa base redondeados a los decimales de la divisa del visitanteDevolver los decimales base mientras se añade una tarifa de envío y para los arrays de variaciones en bruto

Las tarifas de envío se calculan en la divisa base y se convierten después en woocommerce_package_rates. Si antes se redondearan a los decimales de la divisa del visitante (por ejemplo 0 para JPY), el valor base perdería precisión antes de la conversión. woocs_fix_decimals() devuelve los decimales base cuando add_rate está en la pila de llamadas.

Lo mismo se aplica a los arrays de precios de variaciones: woocs_fix_variation_decimal() los formatea con los decimales base antes de que el conversor los recorra.

Los separadores por divisa corrompen los importes escritos en el editor de pedidosDetectar las pantallas de pedidos y sus llamadas AJAX y mantener allí los separadores de la tienda

Los separadores decimal y de miles se filtran por divisa (seis esquemas en get_decimal_sep() y get_thousand_sep()). En el editor de pedidos de wp-admin, los campos de entrada de WooCommerce, su validación JS y wc_format_decimal() asumen el separador de la tienda, de modo que una coma como separador decimal allí cambiaría los importes guardados. Por eso los separadores por divisa se desactivan en el editor de pedidos.

woocs_is_admin_order_edit_context() reconoce por nombre las acciones AJAX del editor de pedidos, otras llamadas AJAX por el referer (página wc-orders, tipo de contenido shop_order, ID de pedido), y las pantallas de HPOS y heredadas. La parte de la petición se guarda en una variable estática; la comprobación de pantalla se reevalúa porque get_current_screen() está vacío al principio de la petición. Los importes de reembolso escritos con coma se normalizan antes de que WooCommerce los valide.

La pasarela rechaza importes fraccionarios en divisas sin decimalesReescribir como enteros los campos de importe e impuestos de PayPal Standard para divisas sin céntimos

apply_conversion() se ejecuta en woocommerce_paypal_args y reformatea con 0 decimales todos los campos amount_* y tax_cart cuando la divisa actual no tiene céntimos. enable_custom_currency() amplía la lista blanca de divisas de PayPal de WooCommerce para que la pasarela siga disponible cuando el visitante paga en una divisa distinta de la base.

Tasas cripto diminutas impresas en notación científicaFormatear las tasas con 15 cifras significativas y recortar los ceros finales

Una tasa como monedas por USD puede estar muy por debajo de 0.0001, y la conversión de float a cadena de PHP produce notación exponencial que el formulario de administración y el correo de tasas no pueden usar. rate_to_string() calcula el número de decimales a partir del log10 del valor, lo limita a 20 y elimina los ceros finales.

Divisa por visitante en sitios con caché

shipped · 2016

Qué aportaCada visitante conserva la divisa que eligió, incluso en sitios con caché o redes compartidas, y el minicarrito y el envío se actualizan cuando cambia.

Problema
La divisa seleccionada es un estado por visitante, pero las cachés de página completa sirven el mismo HTML a todos, y muchos hostings rompen las sesiones PHP o colocan a muchos visitantes detrás de una misma IP.
Solución

El almacenamiento de la divisa es intercambiable entre seis backends. En sitios con caché, los precios se renderizan como marcadores y se redibujan por AJAX con una clave de almacenamiento por navegador.

Stack
  • Sesiones PHP
  • Transients
  • Memcached
  • Redis
  • localStorage
  • fetch API
  • jQuery AJAX
Tareas · 6
Hostings donde las sesiones PHP no sobreviven entre peticionesUna interfaz de almacenamiento sobre sesión, transient, sesión propia en base de datos, Memcached, Redis y cookie

WOOCS_STORAGE expone set_val/get_val/is_isset y cambia según el backend configurado. El almacenamiento en transients se indexa por un hash de la IP del cliente, con preferencia por CF-Connecting-IP detrás de Cloudflare porque Cloudflare sobrescribe cualquier valor aportado por el cliente. También se admiten Memcached y Redis.

WOOCS_SESSION reutiliza la tabla woocommerce_sessions con una cookie firmada con HMAC, lee a través de la caché de objetos y escribe en shutdown solo cuando los datos han cambiado.

Los visitantes detrás de una IP compartida ven la divisa de los demásIndexar el almacenamiento en transients por un ID aleatorio por navegador guardado en localStorage

Con almacenamiento en transients y modo caché activados, front.js crea una vez un ID aleatorio (crypto.randomUUID cuando está disponible) y lo envía con cada petición. El servidor lo sanea con sanitize_key() y lo convierte en hash para la clave del transient, de modo que los usuarios de un NAT de oficina o de un operador móvil tienen cubos separados. El ID se genera en minúsculas a propósito: sanitize_key() pasa a minúsculas, y un ID con mayúsculas y minúsculas daría un hash que apuntaría a otro cubo.

En este modo el transient vive 30 días en lugar de 1, porque la clave es estable por navegador. Si localStorage está bloqueado, el código recurre en silencio a la clave por IP.

Los bloques y las peticiones de Store API evitan jQuery y pierden la claveEnvolver window.fetch en el momento de la carga y añadir la clave como cabecera en las llamadas del mismo origen

Las peticiones de jQuery reciben la clave mediante un manejador ajaxSend, pero WooCommerce Blocks, la Store API y PayPal Payments usan fetch() y arrancan antes de DOM ready. El wrapper se instala en el nivel superior. La clave va en una cabecera X-WOOCS-SK y no en un argumento de consulta, porque un argumento de consulta por visitante dividiría la caché de página por visitante. Las llamadas de origen cruzado se dejan intactas, ya que una cabecera personalizada dispara un preflight de CORS que puede romper los SDK de pago.

Del lado de PHP, las peticiones wp-json a las rutas de carrito, tienda y lote mantienen el plugin cargado para que el carrito y el checkout de bloques se rendericen en la divisa del visitante.

La caché de página sirve precios renderizados para otro visitanteEnvolver cada precio en un marcador y redibujar todos los marcadores en una sola petición AJAX

woocommerce_price_html() envuelve cada precio en un span con el ID del producto y un ID de redibujado único. En una página en caché, front.js recopila los marcadores y los envía a woocs_get_products_price_html; el JSON de variaciones del formulario de añadir al carrito y los shortcodes de precio personalizados se refrescan de la misma manera. Un estilo de precarga puede ocultar los precios obsoletos hasta que llegue la respuesta.

El servidor devuelve una respuesta vacía cuando la divisa en que se renderizó la página en caché ya es igual a la guardada del visitante, de modo que esa visualización de página no cuesta ningún renderizado. Solo renderiza get_price_html() para productos publicados y visibles.

El minicarrito y el envío siguen en la divisa anterior tras un cambioAñadir la divisa al hash del carrito de WooCommerce y forzar un refresco de fragmentos

WooCommerce guarda los fragmentos del carrito en sessionStorage indexados por el hash del carrito, y el hash depende solo del contenido del carrito. FOX filtra woocommerce_cart_hash a md5(cart + currency), de modo que un cambio invalida los fragmentos guardados y se recalcula el envío.

Cuando la divisa llega en la URL en una página en caché, front.js primero la replica en el cubo de la clave del navegador y solo entonces dispara wc_fragment_refresh; de lo contrario, el refresco leería un cubo vacío y recurriría a la divisa base.

Los códigos de divisa llegan desde la URL, AJAX, REST y almacenamiento obsoletoAceptar solo los códigos de la lista de la tienda; las divisas ocultas, solo para quienes gestionan pedidos

set_currency() guarda solo las divisas habilitadas, y el valor guardado se vuelve a comprobar en cada petición, de modo que una divisa eliminada por el administrador recurre a la base. get_woocommerce_currency() nunca devuelve a WooCommerce un código desconocido, porque WooCommerce lo escribiría en el pedido.

Las divisas marcadas como privadas no se pueden seleccionar mediante ?currency= ni mediante el cambio por AJAX. El valor de petición woocs_in_order_currency acepta una divisa privada solo para usuarios con edit_shop_orders.

Carrito, envío, cupones y pago

shipped · 2015

Qué aportaLos costes de envío, los mínimos de envío gratuito y los cupones funcionan correctamente en la divisa del cliente, y el checkout cobra solo en las divisas que la tienda acepta.

Problema
Los costes de envío, los importes de cupones y los umbrales se guardan en la divisa base, pero se comparan con totales del carrito que ya están convertidos.
Solución

Cada importe se convierte donde WooCommerce lo consume, y cada comprobación de umbral se hace en una sola divisa convirtiendo de nuevo el lado del carrito.

Stack
  • API de envío de WooCommerce
  • WC_Coupon
  • WC_Tax
  • Filtros de pasarelas de pago
Tareas · 5
Costes de envío e impuestos de envío en la divisa seleccionadaConvertir el coste y el array de impuestos de cada tarifa en package_rates, o usar un coste fijo por divisa

woocommerce_package_rates() multiplica el coste y cada entrada de impuestos por la tasa y redondea a los decimales de la divisa. Un coste fijo de tarifa plana por divisa se guarda dentro de la opción de ajustes de instancia del propio método de envío. Cuando se usa un coste fijo, escalar el impuesto anterior sería incorrecto, así que el impuesto se recalcula con WC_Tax::calc_shipping_tax().

Las fórmulas de tarifa plana usan un coste del carrito que ya está convertidoDividir el argumento [cost] por la tasa, porque la tarifa resultante se convierte después

Un coste de tarifa plana como '[cost] * 0.1' recibe el coste del carrito en la divisa del visitante, y la tarifa de envío resultante se convierte de nuevo en woocommerce_package_rates. woocommerce_fix_shipping_calc() divide antes el argumento de coste por la tasa, de modo que la conversión se hace una sola vez.

Mínimo de envío gratuito comparado entre dos divisasReimplementar la comprobación de disponibilidad y convertir de nuevo a la base el subtotal y los descuentos

El método de envío gratuito compara el subtotal mostrado con min_amount. Cuando el cliente paga en la divisa seleccionada, el subtotal del carrito está en esa divisa, así que la comprobación se reimplementa: el subtotal se convierte de nuevo con la tasa actual, el descuento y el impuesto del descuento también, se respetan los ajustes ignore_discounts y de visualización de impuestos, y los requisitos de cupón/either/both se evalúan como en WooCommerce.

Si hay un mínimo fijo por divisa, también se convierte de nuevo, de modo que ambos lados de la comparación están en la divisa base.

Cupones de importe fijo y límites de gasto guardados en divisa baseConvertir el importe y el gasto mín./máx. cuando se carga el objeto del cupón, omitiendo los cupones de porcentaje

woocommerce_coupon_loaded() convierte el importe del cupón (no para los tipos percent y percent_product) y el gasto mínimo y máximo, y los vuelve a escribir con los setters del cupón, de modo que toda la validación de WooCommerce se ejecuta en una sola divisa. Los importes y límites fijos de cupón por divisa, guardados como meta del cupón, sustituyen a los valores convertidos.

El checkout debe cobrar en una divisa que la tienda acepteForzar la divisa base en cada punto de entrada del checkout en el modo solo de visualización; filtrar las pasarelas

En el modo solo de visualización, la divisa se restablece a la base en la página de checkout, en checkout_process, en el checkout de bloques y en las actualizaciones de la revisión del pedido. En el modo de pago en la divisa seleccionada, la petición de checkout lee la divisa guardada de forma explícita y, opcionalmente, la divisa se fuerza según el país del visitante. Un pedido pendiente que se paga más tarde desde su enlace de pago se cambia a la divisa propia del pedido.

Las pasarelas de pago pueden ocultarse o mostrarse por divisa, ya que muchas pasarelas admiten solo algunas divisas.

Tasas de cambio: fuentes, planificación, salvaguardas

en el producto

Qué aportaLas tasas de cambio se actualizan según el calendario desde muchas fuentes. Una tasa fallida o absurda se rechaza en lugar de cambiar los precios de toda la tienda, y se puede añadir un margen.

Problema
Las tasas llegan de muchas API con bases y formatos distintos, deben actualizarse según un calendario en sitios donde WP-Cron no es fiable, y una mala respuesta no debe cambiar los precios de toda la tienda.
Solución

Una clase proveedora por fuente normaliza a 'unidades por 1 base', un planificador basado en opciones se ejecuta en peticiones normales, una consulta fallida nunca escribe cero ni un texto de error como tasa, y las tasas nuevas pueden limitarse a topes por divisa.

Stack
  • PHP
  • wp_remote_get
  • SimpleXML
  • API JSON
  • Opciones de WordPress
Tareas · 6
Quince fuentes de tasas con bases y formatos de payload distintosRateProvider abstracta con URL y parser por fuente, cargada por convención de nombres de clase

RateProvider::getRate() construye la URL, la consulta con un timeout y delega en parseResponse(). Los feeds de bancos centrales cotizan frente a su propia divisa, así que los parsers calculan tasas cruzadas: el BCE tiene como base EUR, y el feed del Banco de Rusia incluye además un Nominal (tasa por 10 o 100 unidades) que hay que dividir.

get_rate_provider() asigna el nombre de la fuente configurada a un archivo de clase. Los sitios pueden añadir sus propias fuentes mediante los filtros woocs_add_custom_rate y woocs_add_aggregator_processor.

La API de precios cripto trata cualquier ticker, incluido CAD, como una monedaRechazar los códigos fiat antes de la petición e invertir USD por moneda en monedas por USD

La fuente Pulse Verity devuelve un precio en USD para cualquier símbolo, así que un código fiat recibiría sin avisar el precio de un token no relacionado. El proveedor comprueba primero una lista ISO 4217 fijada en el código, porque los plugins de pago cripto añaden monedas a la lista de divisas de WooCommerce y no se puede confiar en esa lista. Funciona solo con base USD, envía la clave de API como cabecera Bearer, informa del código de error propio de la API ante cualquier respuesta que no sea 2xx (clave incorrecta, restricción del plan, límite de peticiones) y rechaza precios cero o no numéricos. El precio en USD por moneda devuelto se invierte en monedas por 1 USD.

Actualizaciones de tasas en sitios donde WP-Cron no es fiable o el tráfico es constantePlanificador propio en una sola opción, comprobado en peticiones normales; adjuntar nunca mueve una ejecución pendiente

PN_WP_CRON_WOOCS guarda inicio, siguiente, intervalo y última ejecución por hook en una sola opción y se comprueba desde init, admin_init y rest_api_init. Como se llama en cada petición, attach() debe ser idempotente: con un intervalo sin cambios deja next intacto, y ante un cambio de intervalo recalcula next a partir de la última ejecución, limitado a ahora más un intervalo. Los tres hooks se registran con 0 argumentos aceptados, porque rest_api_init pasa el objeto WP_REST_Server, que de otro modo acabaría en el parámetro $reset y reiniciaría el calendario en cada petición REST.

process() adelanta la siguiente ejecución antes de llamar al hook, captura y registra las excepciones que este lanza, y ejecuta cada hook como máximo una vez por petición. El calendario actualizado se guarda en la opción después de ejecutarse los hooks.

Una respuesta de API fallida o absurda no debe cambiar los precios de toda la tiendaSustituir una tasa solo por un número positivo y limitar las tasas nuevas a un suelo y un techo por divisa

rate_auto_update() consulta cada divisa en su propio bloque try y sustituye una tasa solo por un número positivo, de modo que una divisa o una fuente que falla no detiene a las demás y nunca escribe cero ni un texto de error como tasa. get_rate() pasa cada tasa numérica por ExchangeRateLimiter, que la limita a un suelo y un techo opcionales por divisa. Tras guardar, la acción woocs_sheduler_rates_updated permite a otro código reaccionar.

Cambiar la divisa base invalida todas las tasas guardadasMarcar la nueva base y volver a consultar todas las tasas frente a ella en la misma petición

Todas las tasas se guardan como unidades por 1 base, así que una base nueva hace que todos los números sean erróneos a la vez. save_etalon() guarda la nueva bandera de base, cambia default_currency en memoria y llama a get_rate() para cada una de las demás divisas antes de responder a la pantalla de administración, de modo que el formulario se rellena con valores coherentes.

Las tiendas añaden un margen sobre las tasas de mercadoAplicar un recargo fijo o porcentual por divisa en un único filtro sobre la lista de divisas

El recargo se guarda junto a la tasa como importe fijo o porcentaje y se aplica en un filtro woocs_currency_data_manipulation con prioridad 1, de modo que todo consumidor de get_currencies() ve la tasa con recargo. get_currencies(true) omite los filtros cuando se necesita el valor en bruto.

Pedidos, correos e informes tras la venta

en el producto

Qué aportaCada pedido conserva la divisa y la tasa con las que se pagó, de modo que los correos, las facturas, las ediciones de pedidos y los informes de ventas muestran los importes correctos.

Problema
Un pedido se guarda en la divisa en que se pagó, mientras que las pantallas de administración, los correos, las facturas, las analíticas y las ediciones posteriores se ejecutan con alguna otra divisa actual.
Solución

La tasa del checkout se guarda en el pedido, la divisa del pedido se fuerza donde quiera que se renderice el pedido, y las filas de analíticas se convierten de nuevo a la base.

Stack
  • WC_Order CRUD
  • HPOS
  • Meta de artículos de pedido
  • Tablas de WooCommerce Analytics
  • Correos de WooCommerce
Tareas · 5
Saber más tarde con qué tasa se pagó un pedidoGuardar la tasa y la divisa base como meta del pedido mediante la API CRUD en el checkout

En el checkout y en la página de agradecimiento, la tasa, la divisa base y un marcador de 'cambiado manualmente' se escriben con $order->update_meta_data(), que funciona tanto con HPOS como con almacenamiento en posts. Si la divisa actual no está en la lista, se usa la tasa base. Las claves meta se ocultan en la visualización de artículos. Un administrador puede corregir la tasa guardada desde la pantalla del pedido, y las filas de analíticas de productos del pedido se vuelven a sincronizar.

Mover un pedido guardado a otra divisaConvertir de nuevo cada importe con la tasa guardada y aplicar después la tasa de la divisa de destino

El recálculo convierte los totales del pedido, los subtotales y totales de líneas, los arrays de impuestos por tasa, los artículos de envío y sus impuestos, los artículos de impuestos y los reembolsos. En HPOS pasa por los setters CRUD, convierte también las líneas de tarifas (fees) y de cupones, y recalcula los impuestos. En el almacenamiento heredado actualiza directamente el post meta y el meta de los artículos del pedido, incluido el descuento del carrito del pedido.

Si un sitio define woocs_order_recalculated_custom(), se llama antes de guardar con el pedido, las dos divisas y la tasa anterior, para los importes que deben mantener un valor fijo por divisa. Una acción masiva recalcula todos los pedidos a la divisa base.

Los correos, las facturas y las páginas de cuenta se renderizan en la divisa del visitanteCambiar a la divisa del pedido justo antes de renderizar cada vista de pedido o correo

La divisa actual pertenece a quien desencadenó la petición: un administrador que completa un pedido, una tarea cron o un cliente que navega en otra divisa. FOX cambia a la divisa del pedido en wc_get_template para las plantillas de correo, en la notificación de completado y en el reenvío de correos, en el renderizado de facturas en PDF, en las listas y vistas de pedidos de Mi cuenta, en la vista previa de pedidos en administración, y por cada fila de la lista de pedidos de HPOS mediante el filtro del nombre del comprador.

WooCommerce Analytics suma pedidos pagados en distintas divisasDespués de que WooCommerce escriba las filas de consulta, dividirlas por la tasa guardada del pedido

WooCommerce Analytics copia los importes de los pedidos tal cual a sus propias tablas de consulta, de modo que los ingresos mezclarían divisas. WOOCS_analytics se engancha a woocommerce_analytics_update_product, _tax y _coupon, lee la fila que WooCommerce acaba de escribir, divide cada importe por la tasa guardada del pedido (o la tasa actual si no hay ninguna) y redondea a los decimales base. Los informes heredados de WooCommerce se adaptan de la misma manera convirtiendo de nuevo cada pedido.

Editar un pedido en wp-admin usa la divisa del administradorEjecutar el AJAX del editor de pedidos en la divisa del pedido y aplicar precios fijos a los artículos añadidos

wp-admin se ejecuta normalmente en la divisa base. Para las acciones AJAX del editor de pedidos (añadir artículo, guardar artículos, recalcular impuestos), la divisa actual se establece en la del pedido, para los usuarios que pueden editar pedidos. Cuando se añade manualmente un producto con precio fijo en esa divisa, el subtotal y el total del artículo se fijan a partir del precio fijo y se recalculan los totales del pedido. Cuando se añade un cupón en el editor, la divisa actual cambia a la del pedido.

Contextos que deben permanecer en divisa base

en el producto

Qué aportaLos buscadores, las exportaciones, las sincronizaciones y las pantallas de administración ven los precios base de la tienda, de modo que los datos guardados y los servicios conectados se mantienen coherentes.

Problema
Los consumidores automáticos leen los precios a través de los mismos hooks que los compradores. Una sincronización, un webhook o un rastreador pueden llevar la sesión de un visitante y recibir números convertidos.
Solución

Las peticiones se clasifican antes de que el plugin se cargue, y la divisa base se fuerza alrededor de operaciones concretas de WooCommerce.

Stack
  • WP REST API
  • Webhooks de WooCommerce
  • Action Scheduler
  • Marcado schema.org
Tareas · 6
La REST API de WooCommerce debe responder en la divisa base en cualquier servidor web (premium)Detectar las rutas /wc/vN/ en REQUEST_URI o rest_route y no cargar el plugin

Los sistemas POS y ERP sincronizan precios a través de la REST API de WooCommerce, y una petición puede llevar la sesión de un visitante que seleccionó otra divisa. La variable de servidor SCRIPT_URI que usa la protección REST general existe en Apache pero no en nginx, así que la ruta también se analiza a partir de REQUEST_URI con rest_get_url_prefix(), o de ?rest_route=, y el plugin termina antes de crear su objeto para cualquier ruta wc/vN. La Store API y el espacio de nombres propio de FOX no se ven afectados.

woocs_validate_currency() responde con la divisa de la tienda cuando el objeto del plugin no existe en la petición. Edición premium.

Los payloads de webhooks deben construirse en la divisa base (premium)Cambiar a la base solo mientras se construye el payload, para el envío asíncrono y para el envío síncrono en shutdown

El envío asíncrono se ejecuta mediante Action Scheduler: la divisa base se activa con prioridad 1 de woocommerce_deliver_webhook_async y se desactiva en 999. El envío síncrono es más difícil: desde WooCommerce 4.4 los webhooks se ponen en cola y se envían en shutdown, así que FOX activa la divisa base dentro del filtro woocommerce_webhook_deliver_async solo cuando se le llama en shutdown con un WC_Webhook y async=false, y la desactiva en woocommerce_webhook_payload, justo después de build_payload().

El envío puede ejecutarse en una petición que lleva las cookies de un visitante y, por tanto, la divisa de ese visitante. Se conmutan tanto la bandera de conversión como current_currency, porque los precios fijos por divisa leen current_currency directamente. Edición premium.

Los buscadores indexan precios y divisas convertidosRestablecer a la base los bots conocidos y reescribir las ofertas de schema.org a la divisa base

Los rastreadores pueden llegar con una divisa en la URL. Los user agents de bots conocidos se restablecen a la divisa base en wp_head salvo que el administrador lo desactive. De forma independiente, structured_data_product_offer() establece priceCurrency en la base y divide las entradas price, lowPrice, highPrice y priceSpecification por la tasa, de modo que el marcado del producto sea coherente con la divisa de la tienda.

Las exportaciones, las pantallas de producto de administración y los editores masivos deben ver los valores base guardadosRestablecer a la base para las exportaciones y la carga de variaciones en administración; omitir la carga en algunos AJAX

La exportación CSV de productos restablece la divisa antes de su consulta, de modo que los precios exportados son valores base que pueden importarse de vuelta. La carga de variaciones en el editor de productos y todas las páginas de wp-admin que no son AJAX se ejecutan en la divisa base. El plugin no se carga para las acciones AJAX del editor masivo BEAR, para la carga de artículos de pedido, para las peticiones REST cuya URL contiene /refunds o paypal (PayPal Payments), ni para los reembolsos en backend salvo que un plugin conocido lo necesite, porque esas peticiones escriben importes guardados.

Los front ends headless necesitan precios en una divisa dada por peticiónEndpoints REST que cambian de divisa durante una llamada y la restauran después

woocs/v3 expone la lista de divisas, el precio de un producto y un lote de precios de productos. El callback establece la divisa solicitada solo si existe en la tienda, calcula los precios con la misma precedencia que el conversor principal (fijo, país, rol, luego tasa), devuelve valores en bruto por variación con mín. y máx. o HTML, y restaura la divisa anterior.

Un importador de pedidos de Etsy guardaba pedidos en AUD con la divisa que GeoIP había elegido para la peticiónParchear el importador para restablecer FOX a la divisa base de la tienda antes de que escriba un pedido

La divisa base de la tienda era AUD. Durante la petición de importación, GeoIP había cambiado la divisa actual a USD, y el importador escribía la divisa actual en cada pedido. Se añadió una llamada a $WOOCS->reset_currency(), protegida con class_exists('WOOCS'), en dos puntos del código de pedidos del importador, de modo que los pedidos se escriben en la divisa base. Es un parche al importador de terceros y hay que volver a aplicarlo tras actualizar ese plugin. El cliente confirmó que funcionó.

Cifras

wordpress.org
  • Instalaciones activas 50.000+ contador de wordpress.org.
  • Reseñas 250 Media de 4.4 sobre 5.
  • Años de soporte 12 Desde 20 de septiembre de 2014, última actualización 12 de octubre de 2026.