Мова

Зв'язатися

Плагін для WooCommerce · з 2014 · aka WOOCS

FOX

Плагін WooCommerce, що показує ціни у валюті, яку вибрав відвідувач, і за потреби може приймати оплату в ній.

Перший реліз
Активні встановлення
50 000+
Рейтинг
4.4 / 5 (250)Читати відгуки
  • PHP
  • WordPress hooks API
  • Фільтри товарів, кошика, доставки й замовлень WooCommerce
  • WooCommerce HPOS (OrderUtil, WC_Order CRUD)
  • Довідкові таблиці WooCommerce Analytics
  • Transients, сесії PHP, Memcached, Redis
  • Планувальник на основі опцій
  • WP REST API
  • jQuery, fetch API, localStorage
  • Потоки курсів SimpleXML / JSON

Про мене

FOX конвертує суми, які створює WooCommerce, у валюту, вибрану відвідувачем, і може дозволити клієнтові платити в цій валюті. WooCommerce знає лише одну валюту магазину, тому плагін працює, перехоплюючи геттери цін товарів, тарифи доставки, купони, підсумки кошика, відображення замовлень і листи, та конвертуючи кожну суму один раз за збереженим курсом.

Складність у тому, що одна ціна проходить через багато шляхів коду WooCommerce: деякі кешуються, деякі виконуються у фонових запитах, деякі — у wp-admin. Кожен шлях має бачити правильну валюту. Вітрина використовує валюту відвідувача, листи й редактор замовлення — валюту замовлення, а експорти, розмітка для пошукових систем і аналітика — базову валюту. Преміум-версія також тримає WooCommerce REST API і дані webhook-ів у базовій валюті.

Навколо цього ядра розміщено імпорт курсів з 15 джерел із власним планувальником і розумними межами, зберігання валюти для кожного відвідувача, що працює за повносторінкових кешів, формати округлення й чисел для кожної валюти, ручні ціни за валютою, країною та роллю користувача, а також перерахунок збережених замовлень між валютами як у HPOS, так і в застарілому сховищі замовлень.

Безкоштовна версія на wordpress.org працює на тому самому головному класі, обмеженому двома валютами в get_currencies().

FOX · перемикач валют

що розв'язано

ПРАЦЮЄз 2014

Конвертація цін усередині WooCommerce

shipped · 2014

Що це даєКожна ціна конвертується рівно один раз, тож клієнти ніколи не бачать подвоєних чи хибних сум. Власник може задавати фіксовані ціни за валютою, країною чи роллю клієнта.

Проблема
WooCommerce має одну валюту магазину й читає ціни через безліч геттерів, кешів і побудовників HTML. Кожна сума має бути конвертована рівно один раз, а деякі суми не можна конвертувати взагалі.
Рішення

Один конвертер стоїть на геттерах цін товарів із пріоритетом 9999. Ручні ціни мають перевагу над конвертацією за курсом, а для сум, які вже остаточні, існують явні перемикачі обходу.

Стек
  • PHP
  • Геттери товарів WooCommerce
  • post meta
Задачі · 6
Конвертувати ціни простих товарів і варіацій один раз, на рівні данихПідключити геттери цін товарів і варіацій одним конвертером із пріоритетом 9999

У режимі, коли клієнт платить у вибраній валюті, raw_woocommerce_price() підключається до woocommerce_product_get_price, геттерів звичайної й акційної ціни та геттерів варіацій. Пріоритет 9999 ставить його після інших плагінів, що коригують базову ціну. У режимі лише показу використовується тільки фільтр raw_woocommerce_price, тож збережені суми кошика й замовлення лишаються в базовій валюті.

Крайні випадки, які обробляє конвертер: порожні ціни проходять без змін, варіативний батько, запитаний з display=false, пропускається, щоб не конвертувати min/max двічі, а геттер акційної ціни повертає порожній рядок, коли акційної ціни не збережено. Без цього конвертована порожня акційна ціна стає 0, і WooCommerce показує закреслену ціну.

Кеш цін варіацій спільний для всіх валютДодати поточну валюту в хеш цін варіацій, щоб кожна валюта мала власний запис

WooCommerce кешує обчислені масиви цін варіативного товару в transient за ключем-хешем вхідних даних ціноутворення. Якщо валюти немає в цьому хеші, конвертовані ціни першого відвідувача віддаються всім. woocommerce_get_variation_prices_hash() додає поточну валюту.

Потім woocommerce_variation_prices() конвертує кожен запис, застосовує фіксовані ціни окремих варіацій і пересортовує кожен масив через asort(). Діапазон цін береться з першого й останнього елементів, а фіксовані ціни за валютою можуть змінити порядок варіацій порівняно з базовою валютою.

Ручні ціни за валютою, країною та роллю в одному конвеєріФіксована ціна у валюті остаточна; ціна за країною чи роллю замінює базову ціну до конвертації за курсом

Фіксовані ціни зберігаються як мета товару для кожного поля й валюти (_woocs_regular_price_EUR, _woocs_sale_price_EUR), де -1 означає «не задано, використати курс». Фіксована ціна у валюті відвідувача використовується як є. Інакше ціна за країною замінює базову, а результат конвертується за курсом. Ціни за країною групують країни в блоки з однією ціною на блок, а країна відвідувача береться з геолокації WooCommerce, збереженої в стані відвідувача.

Ціни за роллю застосовуються після цього кроку. Коли для ролі користувача задано ціну, вона замінює ціну, вибрану досі, зокрема фіксовану ціну у валюті, і конвертується за курсом.

Коли акційну ціну за країною залишено порожньою, get_product_geo_data() копіює в неї звичайну ціну, інакше товар став би безкоштовним у цій країні. Коли фіксоване поле акційної ціни порожнє, пошук повертається до фіксованого поля звичайної ціни.

Фільтр ціни отримує число, а не назву поля ціниЗіставити значення зі збереженими звичайною й акційною цінами, а потім звернутися до пам'яті запиту

Фіксовані ціни зберігаються для кожного поля, але woocommerce_product_get_price передає лише число. get_price_type() порівнює вхідне значення з сирими звичайною й акційною цінами товару, прочитаними в контексті 'edit'. Якщо жодна не збігається, вона веде статичну карту першої ціни, побаченої для кожного товару в запиті, і вважає пізніше, більше значення звичайною ціною.

Це евристика, тому явні типи полів передаються скрізь, де виклик їх знає. Ціни за роллю використовують власну копію тієї ж логіки.

Показати ціну одного товару в кожній валюті за одне відображенняПеремикати поточну валюту для кожного запису й перебудовувати діапазони для варіативних і групових типів

Необов'язковий список цін під товаром будується всередині woocommerce_price_html(). Для кожної валюти перемикається поточна валюта, значення форматується з десятковими знаками й роздільниками цієї валюти, а потім початкова валюта відновлюється.

Діапазон варіативного товару не можна обчислити як базові min/max, помножені на курс, бо окремі варіації можуть мати фіксовані ціни. _get_min_max_variation_prices() перераховує ціну кожної варіації для цільової валюти й відкидає нульові значення. Групові товари обходять своїх нащадків і так само обробляють варіативних нащадків.

Дозволити іншому коду позначати суму як остаточну або конвертувати власні сумиФільтр woocs_skip_conversion, внутрішній прапорець блокування, публічні фільтри прямої й зворотної конвертації

woocs_skip_conversion перевіряється в конвертері першим: інтеграція, що вже оцінила позицію в активній валюті, повертає true, і сума проходить без змін. Прапорець запиту woocs_block_price_hook вимикає конвертацію для ділянки коду; його використовують, наприклад, під час побудови даних webhook-ів.

Для зворотного напрямку woocs_convert_price і woocs_back_convert_price дозволяють стороннім плагінам конвертувати власні суми в базовій валюті, а convert_from_to_currency() конвертує між будь-якими двома валютами магазину через базову: value / rate_from * rate_to.

Округлення, десяткові знаки та формати чисел

shipped · 2016

Що це даєЦіни показуються з правильними десятковими знаками й роздільниками для кожної валюти, а суми, які вводить персонал або які надходять до платіжного шлюзу, лишаються коректними.

Проблема
Валюти відрізняються десятковими знаками та роздільниками, а WooCommerce читає їх із глобальних опцій, спільних для показу, розбору введених сум і податкових обчислень.
Рішення

Значення для кожної валюти підставляються через фільтри опцій і вимикаються в контекстах, де WooCommerce розбирає ввід або округлює в базовій валюті.

Стек
  • PHP
  • Фільтри опцій WordPress
  • Функції форматування WooCommerce
Задачі · 5
Десяткові знаки для кожної валюти через одну глобальну опцію WooCommerceФільтрувати pre_option_woocommerce_price_num_decimals за десятковими знаками активної валюти

WooCommerce читає кількість десяткових знаків з однієї опції. FOX відповідає на цю опцію налаштуванням поточної валюти, а конвертер округлює через number_format() до тієї ж точності, тож збережене значення кошика й показане значення збігаються.

JPY і TWD жорстко закодовані як валюти без копійок, адміністратор може додати інші, а фільтр woocs_precision_on_calc дозволяє сайту перевизначити точність для кожної валюти.

Суми в базовій валюті округлюються до десяткових знаків валюти відвідувачаПовертати базові десяткові знаки, поки додається тариф доставки, і для сирих масивів варіацій

Тарифи доставки обчислюються в базовій валюті й конвертуються пізніше в woocommerce_package_rates. Якби їх спершу округлити до десяткових знаків валюти відвідувача (наприклад, 0 для JPY), базове значення втратило б точність до конвертації. woocs_fix_decimals() повертає базові десяткові знаки, коли add_rate є у стеку викликів.

Те саме стосується масивів цін варіацій: woocs_fix_variation_decimal() форматує їх із базовими десятковими знаками до того, як над ними запуститься конвертер.

Роздільники для кожної валюти псують суми, введені в редакторі замовленняВиявляти екрани замовлень та їхні AJAX-виклики й залишати там роздільники магазину

Роздільники десяткової частини й тисяч фільтруються для кожної валюти (шість схем у get_decimal_sep() і get_thousand_sep()). У редакторі замовлення в wp-admin поля введення WooCommerce, їхня JS-валідація та wc_format_decimal() припускають роздільник магазину, тож кома як десятковий роздільник змінила б збережені суми. Тому роздільники окремих валют у редакторі замовлення вимкнено.

woocs_is_admin_order_edit_context() розпізнає AJAX-дії редактора замовлення за назвою, інші AJAX-виклики — за referer (сторінка wc-orders, тип запису shop_order, ID запису замовлення), а також екрани HPOS і застарілі. Частина запиту кешується в статичній змінній; перевірка екрана виконується повторно, бо get_current_screen() на початку запиту порожня. Суми повернень, введені з комою, нормалізуються до того, як їх перевірить WooCommerce.

Шлюз відхиляє дробові суми у валютах без десяткових знаківПереписувати поля суми й податку PayPal Standard як цілі числа для валют без копійок

apply_conversion() виконується на woocommerce_paypal_args і переформатовує кожне поле amount_* і tax_cart з 0 десяткових знаків, коли поточна валюта не має копійок. enable_custom_currency() розширює білий список валют PayPal у WooCommerce, щоб шлюз лишався доступним, коли відвідувач платить у небазовій валюті.

Крихітні курси криптовалют виводяться в науковій нотаціїФорматувати курси з 15 значущими цифрами й обрізати кінцеві нулі

Курс, наприклад кількість монет за USD, може бути значно нижчим за 0.0001, а перетворення float у рядок у PHP дає експоненціальну нотацію, яку не можуть використати ні форма адмінки, ні лист із курсом. rate_to_string() обчислює кількість десяткових знаків з log10 значення, обмежує її 20 і відкидає кінцеві нулі.

Валюта кожного відвідувача на сайтах із кешем

shipped · 2016

Що це даєКожен відвідувач зберігає вибрану валюту, навіть на сайтах із кешем чи у спільних мережах, а міні-кошик і доставка оновлюються при перемиканні.

Проблема
Вибрана валюта — це стан окремого відвідувача, але повносторінкові кеші віддають усім один HTML, а багато хостингів ламають сесії PHP або ховають багатьох відвідувачів за одним IP.
Рішення

Сховище валюти підключається з шести бекендів. На сайтах із кешем ціни виводяться як маркери й перемальовуються через AJAX за ключем сховища окремого браузера.

Стек
  • Сесії PHP
  • Transients
  • Memcached
  • Redis
  • localStorage
  • fetch API
  • jQuery AJAX
Задачі · 6
Хостинги, де сесії PHP не зберігаються між запитамиОдин інтерфейс сховища над сесією, transient, власною сесією в БД, Memcached, Redis, cookie

WOOCS_STORAGE надає set_val/get_val/is_isset і перемикається на налаштований бекенд. Сховище transient має ключ із хеша IP клієнта, а за Cloudflare перевага надається CF-Connecting-IP, бо Cloudflare перезаписує будь-яке значення, надане клієнтом. Memcached і Redis також підтримуються.

WOOCS_SESSION повторно використовує таблицю woocommerce_sessions із cookie, підписаним HMAC, читає через кеш об'єктів і записує на shutdown лише тоді, коли дані змінилися.

Відвідувачі за одним спільним IP бачать валюту одне одногоКлючувати сховище transient випадковим ідентифікатором браузера, що зберігається в localStorage

Зі сховищем transient і ввімкненим режимом кешу front.js один раз створює випадковий ідентифікатор (crypto.randomUUID, коли доступний) і надсилає його з кожним запитом. Сервер санітизує його через sanitize_key() і хешує в ключ transient, тож користувачі за офісним NAT чи мобільного оператора отримують окремі «кошики». Ідентифікатор навмисно створюється в нижньому регістрі: sanitize_key() переводить у нижній регістр, а ідентифікатор зі змішаним регістром дав би хеш іншого «кошика».

У цьому режимі transient живе 30 днів замість 1, бо ключ стабільний для браузера. Якщо localStorage заблоковано, код тихо повертається до ключа за IP.

Блоки та запити Store API оминають jQuery і втрачають ключОбгорнути window.fetch під час завантаження й додавати ключ як заголовок у викликах того самого походження

Запити jQuery отримують ключ через обробник ajaxSend, але WooCommerce Blocks, Store API і PayPal Payments використовують fetch() і стартують до DOM ready. Обгортка встановлюється на верхньому рівні. Ключ передається в заголовку X-WOOCS-SK, а не в аргументі запиту, бо аргумент запиту для кожного відвідувача розколов би кеш сторінок на кожного відвідувача. Виклики між різними походженнями не чіпаються, бо власний заголовок спричиняє CORS preflight, який може зламати платіжні SDK.

На боці PHP запити wp-json до маршрутів cart, store і batch залишають плагін завантаженим, щоб блоковий кошик і оформлення замовлення відображалися у валюті відвідувача.

Кеш сторінок віддає ціни, відображені для іншого відвідувачаОбгорнути кожну ціну в маркер і перемалювати всі маркери одним AJAX-запитом

woocommerce_price_html() обгортає кожну ціну в span з ID товару й унікальним ID перемальовування. На закешованій сторінці front.js збирає маркери й надсилає їх на woocs_get_products_price_html; JSON варіацій у формі додавання до кошика та власні шорткоди цін оновлюються так само. Стиль прелоадера може ховати застарілі ціни, доки не надійде відповідь.

Сервер повертає порожню відповідь, коли валюта, в якій відображено закешовану сторінку, вже дорівнює збереженій валюті відвідувача, тож такий перегляд сторінки не потребує відображення. get_price_html() він відображає лише для опублікованих видимих товарів.

Міні-кошик і доставка лишаються в старій валюті після перемиканняДодати валюту в хеш кошика WooCommerce і примусово оновити фрагменти

WooCommerce зберігає фрагменти кошика в sessionStorage за ключем-хешем кошика, а хеш залежить лише від вмісту кошика. FOX фільтрує woocommerce_cart_hash до md5(cart + currency), тож перемикання робить збережені фрагменти недійсними, і доставка перераховується.

Коли валюта надходить в URL на закешованій сторінці, front.js спершу дзеркалить її в «кошик» ключа браузера і лише потім запускає wc_fragment_refresh, інакше оновлення прочитало б порожній «кошик» і повернулося б до базової валюти.

Коди валют надходять з URL, AJAX, REST і застарілого сховищаПриймати лише коди зі списку магазину; приховані валюти — лише для менеджерів замовлень

set_currency() зберігає лише увімкнені валюти, а збережене значення перевіряється заново в кожному запиті, тож валюта, видалена адміністратором, повертається до базової. get_woocommerce_currency() ніколи не повертає WooCommerce невідомий код, бо WooCommerce записав би його в замовлення.

Валюти, позначені як приватні, не можна вибрати через ?currency= чи AJAX-перемикач. Значення запиту woocs_in_order_currency приймає приватну валюту лише для користувачів з edit_shop_orders.

Кошик, доставка, купони й оплата

shipped · 2015

Що це даєВартість доставки, мінімуми безкоштовної доставки й купони працюють правильно у валюті клієнта, а оформлення замовлення списує кошти лише у валютах, які приймає магазин.

Проблема
Вартість доставки, суми купонів і пороги зберігаються в базовій валюті, але порівнюються з підсумками кошика, які вже конвертовано.
Рішення

Кожна сума конвертується там, де її споживає WooCommerce, а кожна перевірка порогу виконується в одній валюті шляхом зворотної конвертації боку кошика.

Стек
  • WooCommerce shipping API
  • WC_Coupon
  • WC_Tax
  • фільтри платіжних шлюзів
Задачі · 5
Вартість доставки й податки на доставку у вибраній валютіКонвертувати вартість кожного тарифу й масив податків у package_rates або використовувати фіксовану вартість для валюти

woocommerce_package_rates() множить вартість і кожен запис податку на курс і округлює до десяткових знаків валюти. Фіксована вартість flat-rate для валюти зберігається в опції налаштувань екземпляра самого способу доставки. Коли використовується фіксована вартість, масштабувати старий податок було б хибно, тому податок перераховується через WC_Tax::calc_shipping_tax().

Формули flat-rate використовують вартість кошика, яку вже конвертованоДілити аргумент [cost] на курс, бо отриманий тариф конвертується пізніше

Вартість flat-rate на кшталт '[cost] * 0.1' отримує вартість кошика у валюті відвідувача, а отриманий тариф доставки потім знову конвертується в woocommerce_package_rates. woocommerce_fix_shipping_calc() спершу ділить аргумент cost на курс, тож конвертація відбувається один раз.

Мінімум для безкоштовної доставки порівнюється між двома валютамиРеалізувати перевірку доступності заново й конвертувати проміжну суму та знижки назад у базову

Спосіб безкоштовної доставки порівнює показану проміжну суму з min_amount. Коли клієнт платить у вибраній валюті, проміжна сума кошика виражена в ній, тож перевірку реалізовано заново: проміжна сума конвертується назад за поточним курсом, знижка й податок на знижку теж, враховуються налаштування ignore_discounts і показу податків, а вимоги coupon/either/both оцінюються як у WooCommerce.

Якщо задано фіксований мінімум для валюти, він теж конвертується назад, тож обидві частини порівняння виражені в базовій валюті.

Купони з фіксованою сумою та ліміти витрат зберігаються в базовій валютіКонвертувати суму й мінімальні/максимальні витрати під час завантаження об'єкта купона, пропускаючи відсоткові купони

woocommerce_coupon_loaded() конвертує суму купона (крім типів percent і percent_product) та мінімальні й максимальні витрати, а потім записує їх назад через сеттери купона, тож уся валідація WooCommerce виконується в одній валюті. Фіксовані суми й ліміти купонів для окремих валют, збережені як мета купона, перевизначають конвертовані значення.

Оформлення замовлення має списувати кошти у валюті, яку приймає магазинПримусово ставити базову валюту на кожному вході в оформлення у режимі лише показу; фільтрувати шлюзи

У режимі лише показу валюта скидається до базової на сторінці оформлення, на checkout_process, у блоковому оформленні й під час оновлень огляду замовлення. У режимі оплати у вибраній валюті запит оформлення явно читає збережену валюту, а за потреби валюту примусово визначає країна відвідувача. Незавершене замовлення, оплачене пізніше за своїм посиланням на оплату, перемикається на власну валюту замовлення.

Платіжні шлюзи можна ховати або показувати для кожної валюти, бо багато шлюзів підтримують лише деякі валюти.

Курси валют: джерела, розклад, запобіжники

у продукті

Що це даєКурси валют оновлюються за розкладом із багатьох джерел. Невдалий чи абсурдний курс відхиляється, а не переоцінює весь магазин, і можна додати маржу.

Проблема
Курси надходять із багатьох API з різними базами й форматами, мають оновлюватися за розкладом на сайтах, де WP-Cron ненадійний, а одна погана відповідь не повинна переоцінити магазин.
Рішення

Один клас-постачальник на джерело нормалізує до «одиниць на 1 базової», планувальник на основі опцій працює на звичайних запитах, невдале отримання ніколи не записує нуль чи текст помилки як курс, а нові курси можна обмежити межами для кожної валюти.

Стек
  • PHP
  • wp_remote_get
  • SimpleXML
  • JSON API
  • Опції WordPress
Задачі · 6
П'ятнадцять джерел курсів з різними базами й форматами данихАбстрактний RateProvider з URL і парсером для кожного джерела, що завантажується за угодою про іменування класів

RateProvider::getRate() будує URL, отримує дані з тайм-аутом і делегує parseResponse(). Потоки центральних банків котируються відносно власної валюти, тож парсери обчислюють крос-курси: ECB має базу EUR, а потік Банку Росії також містить Nominal (курс за 10 або 100 одиниць), на який треба поділити.

get_rate_provider() зіставляє налаштовану назву джерела з файлом класу. Сайти можуть додавати власні джерела через фільтри woocs_add_custom_rate і woocs_add_aggregator_processor.

API криптоцін вважає монетою будь-який тикер, зокрема CADВідхиляти фіатні коди до запиту й інвертувати USD за монету в монети за USD

Джерело Pulse Verity повертає ціну в USD для будь-якого символу, тож фіатний код мовчки отримав би ціну стороннього токена. Постачальник спершу перевіряє жорстко закодований список ISO 4217, бо плагіни криптоплатежів додають монети до списку валют WooCommerce, і цьому списку не можна довіряти. Він працює лише з базою USD, надсилає API-ключ у заголовку Bearer, повідомляє власний код помилки API для будь-якої відповіді не 2xx (хибний ключ, обмеження тарифу, ліміт запитів) і відхиляє нульові або нечислові ціни. Отримана ціна в USD за монету інвертується в монети за 1 USD.

Оновлення курсів на сайтах, де WP-Cron ненадійний або трафік постійнийВласний планувальник в одній опції, що перевіряється на звичайних запитах; підключення ніколи не зсуває заплановане виконання

PN_WP_CRON_WOOCS зберігає початок, наступний запуск, інтервал і останній запуск для кожного хука в одній опції та перевіряється з init, admin_init і rest_api_init. Оскільки його викликають у кожному запиті, attach() має бути ідемпотентним: з незмінним інтервалом він не чіпає next, а при зміні інтервалу перераховує next від останнього запуску, обмежуючи значенням «зараз плюс один інтервал». Три хуки реєструються з 0 прийнятих аргументів, бо rest_api_init передає об'єкт WP_REST_Server, який інакше потрапив би в параметр $reset і перезапускав би розклад у кожному REST-запиті.

process() зсуває наступний запуск уперед перед викликом хука, перехоплює й логує винятки, викинуті ним, і запускає кожен хук щонайбільше один раз за запит. Оновлений розклад зберігається в опцію після виконання хуків.

Одна невдала чи абсурдна відповідь API не повинна переоцінити весь магазинЗамінювати курс лише додатним числом і обмежувати нові курси нижньою та верхньою межею для кожної валюти

rate_auto_update() отримує кожну валюту у власному блоці try і замінює курс лише додатним числом, тож валюта чи джерело, що відмовило, не зупиняє інші й ніколи не записує нуль чи текст помилки як курс. get_rate() пропускає кожен числовий курс через ExchangeRateLimiter, який обмежує його необов'язковою нижньою й верхньою межею для кожної валюти. Після збереження дія woocs_sheduler_rates_updated дозволяє іншому коду відреагувати.

Зміна базової валюти робить недійсними всі збережені курсиПозначити нову базу й заново отримати всі курси відносно неї в тому самому запиті

Усі курси зберігаються як одиниці на 1 базової, тож нова база одразу робить хибним кожне число. save_etalon() зберігає прапорець нової бази, перемикає default_currency у пам'яті й викликає get_rate() для кожної іншої валюти до відповіді екрану адмінки, тож форма заповнюється узгодженими значеннями.

Магазини додають маржу поверх ринкових курсівЗастосувати фіксовану чи відсоткову націнку для кожної валюти в одному фільтрі над списком валют

Націнка зберігається поруч із курсом як фіксована сума або відсоток і застосовується у фільтрі woocs_currency_data_manipulation з пріоритетом 1, тож кожен споживач get_currencies() бачить курс із націнкою. get_currencies(true) пропускає фільтри, коли потрібне сире значення.

Замовлення, листи й звіти після продажу

у продукті

Що це даєКожне замовлення зберігає валюту й курс, за якими його оплачено, тож листи, рахунки, редагування замовлень і звіти про продажі показують правильні суми.

Проблема
Замовлення зберігається у валюті, в якій його оплачено, тоді як екрани адмінки, листи, рахунки, аналітика та пізніші редагування працюють з іншою поточною валютою.
Рішення

Курс оформлення зберігається в замовленні, валюта замовлення примусово задається скрізь, де замовлення відображається, а рядки аналітики конвертуються назад у базову.

Стек
  • WC_Order CRUD
  • HPOS
  • мета позицій замовлення
  • Таблиці WooCommerce Analytics
  • Листи WooCommerce
Задачі · 5
Пізніше знати, за яким курсом оплачено замовленняЗберігати курс і базову валюту як мета замовлення через CRUD API під час оформлення

Під час оформлення та на сторінці подяки курс, базова валюта й позначка «змінено вручну» записуються через $order->update_meta_data(), що працює і для HPOS, і для сховища на записах. Якщо поточної валюти немає в списку, використовується базовий курс. Мета-ключі приховані від показу позицій. Адміністратор може виправити збережений курс на екрані замовлення, і рядки аналітики товарів замовлення синхронізуються заново.

Перенести збережене замовлення в іншу валютуКонвертувати кожну суму назад збереженим курсом, а потім застосувати курс цільової валюти

Перерахунок конвертує підсумки замовлення, проміжні суми й підсумки рядків, масиви податків за ставками, позиції доставки та їхні податки, позиції податків і повернення. У HPOS він іде через сеттери CRUD, також конвертує рядки комісій і рядки купонів та перераховує податки. У застарілому сховищі він оновлює post meta і мета позицій замовлення напряму, зокрема знижку кошика замовлення.

Якщо сайт визначає woocs_order_recalculated_custom(), вона викликається перед збереженням із замовленням, обома валютами й старим курсом — для сум, які мають зберігати фіксоване значення для кожної валюти. Масова дія перераховує всі замовлення в базову валюту.

Листи, рахунки й сторінки акаунта відображаються у валюті відвідувачаПеремикатися на валюту замовлення безпосередньо перед відображенням кожного перегляду замовлення чи листа

Поточна валюта належить тому, хто ініціював запит: адміністраторові, що завершує замовлення, cron-завданню або клієнтові, який переглядає сайт в іншій валюті. FOX перемикається на валюту замовлення в wc_get_template для шаблонів листів, у сповіщенні про завершення і при повторному надсиланні листа, для відображення PDF-рахунків, у списках замовлень і переглядах замовлень у «Моєму акаунті», у попередньому перегляді замовлення в адмінці та для кожного рядка списку замовлень HPOS через фільтр імені покупця.

WooCommerce Analytics підсумовує замовлення, оплачені в різних валютахПісля того як WooCommerce запише рядки довідкових таблиць, ділити їх на збережений курс замовлення

WooCommerce Analytics копіює суми замовлень у власні довідкові таблиці як є, тож виручка змішувала б валюти. WOOCS_analytics підключається до woocommerce_analytics_update_product, _tax і _coupon, читає рядок, який WooCommerce щойно записав, ділить кожну суму на збережений курс замовлення (або на поточний, якщо його немає) і округлює до базових десяткових знаків. Застарілі звіти WooCommerce адаптовано так само, конвертуючи кожне замовлення назад.

Редагування замовлення в wp-admin використовує валюту адміністратораВиконувати AJAX редактора замовлення у валюті замовлення й застосовувати фіксовані ціни до доданих позицій

wp-admin зазвичай працює в базовій валюті. Для AJAX-дій редактора замовлення (додати позицію, зберегти позиції, перерахувати податки) поточна валюта задається як валюта замовлення, для користувачів, які можуть редагувати замовлення. Коли вручну додається товар із фіксованою ціною в цій валюті, проміжна сума й підсумок позиції беруться з фіксованої ціни, а підсумки замовлення перераховуються. Коли в редакторі додається купон, поточна валюта перемикається на валюту замовлення.

Контексти, які мають лишатися в базовій валюті

у продукті

Що це даєПошукові системи, експорти, синхронізації й екрани адмінки бачать базові ціни магазину, тож збережені дані та підключені сервіси лишаються узгодженими.

Проблема
Машинні споживачі читають ціни через ті самі хуки, що й покупці. Синхронізація, webhook чи краулер можуть нести сесію відвідувача й отримати конвертовані числа.
Рішення

Запити класифікуються до завантаження плагіна, а базова валюта примусово встановлюється навколо певних операцій WooCommerce.

Стек
  • WP REST API
  • Webhook-и WooCommerce
  • Action Scheduler
  • розмітка schema.org
Задачі · 6
WooCommerce REST API має відповідати в базовій валюті на будь-якому веб-сервері (преміум)Зіставляти маршрути /wc/vN/ з REQUEST_URI або rest_route і не завантажувати плагін

Системи POS та ERP синхронізують ціни через WooCommerce REST API, а запит може нести сесію відвідувача, який вибрав іншу валюту. Серверна змінна SCRIPT_URI, яку використовує загальний REST-запобіжник, існує в Apache, але не в nginx, тому маршрут також розбирається з REQUEST_URI за допомогою rest_get_url_prefix() або з ?rest_route=, і плагін завершується до створення свого об'єкта для будь-якого маршруту wc/vN. Store API і власний простір імен FOX це не стосується.

woocs_validate_currency() відповідає валютою магазину, коли об'єкта плагіна в запиті немає. Преміум-версія.

Дані webhook-ів мають будуватися в базовій валюті (преміум)Перемикатися на базову лише на час побудови даних, для асинхронної та синхронної доставки на shutdown

Асинхронна доставка йде через Action Scheduler: базова валюта вмикається з пріоритетом 1 на woocommerce_deliver_webhook_async і вимикається на 999. Синхронна доставка складніша: починаючи з WooCommerce 4.4 webhook-и ставляться в чергу й доставляються на shutdown, тому FOX вмикає базову валюту всередині фільтра woocommerce_webhook_deliver_async лише тоді, коли його викликано на shutdown із WC_Webhook і async=false, а вимикає в woocommerce_webhook_payload, одразу після build_payload().

Доставка може виконуватися в запиті, що несе cookie відвідувача, а отже і його валюту. Перемикаються і прапорець конвертації, і current_currency, бо фіксовані ціни для окремих валют читають current_currency напряму. Преміум-версія.

Пошукові системи індексують конвертовані ціни та валютиСкидати відомих ботів до базової валюти й переписувати пропозиції schema.org назад у базову валюту

Краулери можуть приходити з валютою в URL. Відомі user agent-и ботів скидаються до базової валюти у wp_head, якщо адміністратор цього не вимкнув. Незалежно від цього structured_data_product_offer() задає priceCurrency як базову й ділить записи price, lowPrice, highPrice і priceSpecification на курс, тож розмітка товару лишається узгодженою з валютою магазину.

Експорти, екрани товарів в адмінці й масові редактори мають бачити збережені базові значенняСкидати до базової для експортів і завантаження варіацій в адмінці; пропускати завантаження для деяких AJAX

Експорт товарів у CSV скидає валюту перед своїм запитом, тож експортовані ціни — це базові значення, які можна імпортувати назад. Завантаження варіацій у редакторі товару та кожна не-AJAX сторінка wp-admin працюють у базовій валюті. Плагін не завантажується для AJAX-дій масового редактора BEAR, для завантаження позицій замовлення, для REST-запитів, чий URL містить /refunds або paypal (PayPal Payments), і для повернень у бекенді, якщо їх не потребує відомий плагін, бо ці запити записують збережені суми.

Headless-фронтендам потрібні ціни в заданій валюті для кожного запитуREST-точки, що перемикають валюту на один виклик і потім відновлюють її

woocs/v3 надає список валют, ціну одного товару й пакет цін товарів. Колбек задає запитану валюту лише якщо вона існує в магазині, обчислює ціни з тим самим пріоритетом, що й головний конвертер (фіксована, за країною, за роллю, потім курс), повертає сирі значення для кожної варіації з min і max або HTML та відновлює попередню валюту.

Імпортер замовлень Etsy зберігав замовлення в AUD із валютою, яку для запиту обрав GeoIPВиправити імпортер так, щоб він скидав FOX до базової валюти магазину перед записом замовлення

Базовою валютою магазину був AUD. Під час запиту імпорту GeoIP перемкнув поточну валюту на USD, а імпортер записував поточну валюту в кожне замовлення. Виклик $WOOCS->reset_currency(), захищений class_exists('WOOCS'), додано у двох місцях коду замовлень імпортера, тож замовлення записуються в базовій валюті. Це патч до стороннього імпортера, і його треба застосовувати знову після оновлення того плагіна. Клієнт підтвердив, що це спрацювало.

Цифри

wordpress.org
  • Активні встановлення 50 000+ лічильник wordpress.org.
  • Відгуки 250 Середня оцінка: 4.4 з 5.
  • Років підтримки 12 З 20 вересня 2014 р., останнє оновлення 12 жовтня 2026 р..