基于购物车小计的条件运费适配WooPayments多币种转换问题
WooPayments多币种下自定义阶梯运费的汇率转换问题
问题背景
我用以下自定义函数实现了基于购物车小计的阶梯运费:
function adjust_shipping_rate( $rates, $package ) { if (is_admin() && !defined('DOING_AJAX')) { return; } $cart_total = WC()->cart->get_subtotal(); // Define shipping rates based on cart total $shipping_rates = [ ['min' => 0, 'max' => 50, 'rate' => 20], ['min' => 50.1, 'max' => 100, 'rate' => 15], ['min' => 100.1, 'max' => 200, 'rate' => 10], ['min' => 200.1, 'max' => PHP_INT_MAX, 'rate' => 5] ]; // Find the appropriate shipping rate foreach ($shipping_rates as $range) { if ($cart_total >= $range['min'] && $cart_total <= $range['max']) { foreach ($rates as $rate_key => $rate) { if (strpos($rate_key, 'flat_rate') === 0) { $rates[$rate_key]->cost = $range['rate']; } } break; } } return $rates; } add_filter( 'woocommerce_package_rates', 'adjust_shipping_rate', 10, 2 );
未启用该函数时,WooPayments的多币种转换能正常转换运费金额;但启用后,仅转换运费的货币格式,金额未按汇率计算——比如原本$5运费应转为4.61€,实际显示为5.00€。
我已经知道用get_woocommerce_currency()可以获取当前货币代码,希望能直接获取WooPayments设置的当前汇率,在自定义函数里自行完成转换,且不想安装额外插件。
问题原因
你的处理方式确实存在问题:直接给$rates[$rate_key]->cost赋值原始金额时,跳过了WooPayments的多币种转换逻辑。WooPayments通常会在后续钩子中处理金额的汇率转换,但你直接覆盖了原始成本值,且未考虑当前币种的汇率。
解决方案
WooPayments的汇率存储在wp_options表的woocommerce_wcpay_multicurrency_settings选项中,我们可以直接读取该配置获取汇率,再手动完成运费金额转换:
修改后的函数代码
function adjust_shipping_rate( $rates, $package ) { if (is_admin() && !defined('DOING_AJAX')) { return $rates; } // 获取购物车小计(返回的是店铺基准货币金额) $cart_total = WC()->cart->get_subtotal(); // 定义基准货币下的阶梯运费(金额需与店铺基准货币一致) $shipping_rates = [ ['min' => 0, 'max' => 50, 'rate' => 20], ['min' => 50.1, 'max' => 100, 'rate' => 15], ['min' => 100.1, 'max' => 200, 'rate' => 10], ['min' => 200.1, 'max' => PHP_INT_MAX, 'rate' => 5] ]; // 获取当前币种和店铺基准货币 $current_currency = get_woocommerce_currency(); $base_currency = get_option('woocommerce_currency'); // 若使用基准货币,直接设置运费无需转换 if ($current_currency === $base_currency) { foreach ($shipping_rates as $range) { if ($cart_total >= $range['min'] && $cart_total <= $range['max']) { foreach ($rates as $rate_key => $rate) { if (strpos($rate_key, 'flat_rate') === 0) { $rates[$rate_key]->cost = $range['rate']; } } break; } } return $rates; } // 读取WooPayments多币种配置,提取当前币种汇率 $wcpay_multicurrency = get_option('woocommerce_wcpay_multicurrency_settings'); $exchange_rate = 1; if (!empty($wcpay_multicurrency['currencies'][$current_currency]['rate'])) { $exchange_rate = (float)$wcpay_multicurrency['currencies'][$current_currency]['rate']; } // 计算转换后的运费并赋值 foreach ($shipping_rates as $range) { if ($cart_total >= $range['min'] && $cart_total <= $range['max']) { $converted_rate = round($range['rate'] * $exchange_rate, 2); foreach ($rates as $rate_key => $rate) { if (strpos($rate_key, 'flat_rate') === 0) { $rates[$rate_key]->cost = $converted_rate; } } break; } } return $rates; } add_filter( 'woocommerce_package_rates', 'adjust_shipping_rate', 10, 2 );
关键说明
- 基准货币判断:如果当前使用的是店铺基准货币,无需转换,直接设置运费金额即可。
- 汇率获取:从WooPayments后台配置的汇率中读取值,确保和前台显示的汇率一致。
- 手动转换:用基准货币的运费金额乘以汇率,得到当前币种的运费,再赋值给运费成本。
- 小数处理:用
round()保留两位小数,符合货币显示的通用规范。
内容的提问来源于stack exchange,提问作者Trisha
相关产品推荐
相关产品推荐

