You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让WooCommerce REST API按货币返回带小数的订单总额

WooCommerce多货币场景API小数位适配问题

场景背景

搭建多货币WooCommerce商店,默认货币为日元(JPY),后台已设置价格小数位为0,确保前端和后台日元价格无小数显示。但商店同时支持美元(USD)等其他货币,需要WooCommerce REST API返回对应货币订单总额时保留正确小数位(如USD保留2位)。

当前问题

通过/wp-json/wc/v3/order/{id}接口获取订单数据时,所有货币的总额字段均被取整为整数,即使是需要小数的美元订单也不例外。

预期目标

  • 保持WooCommerce后台及前端商店的日元价格无小数显示
  • REST API根据订单所属货币的规则返回对应小数位的总额(如USD保留2位,JPY保留0位)

已尝试方案

使用woocommerce_rest_prepare_shop_order_object过滤器修改API响应,代码如下:

add_filter( 'woocommerce_rest_prepare_shop_order_object', 'modify_order_total_in_api', 10, 3 );

function modify_order_total_in_api( $response, $order, $request ) {

    // Check if the total exists
    if ( isset( $response->data['total'] ) ) {
        // Format the total with 2 decimals
        $response->data['total'] = number_format( $order->get_total(), 2, '.', '' );
    }

    return $response;
}

执行结果

  • API返回的金额确实添加了2位小数,但均为四舍五入后的整数(如美元订单实际总额25.99,API返回26.00)

额外上下文

  • 非日元货币(如USD)的金额在前端商店和订单后台均能正确显示小数
  • 若将后台小数位改为2,API会返回所有货币的正确小数总额,但日元价格在前端也会显示小数,不符合需求

待解决问题

  1. 如何在保持后台和前端日元无小数的前提下,让API根据货币规则返回对应小数位的总额?
  2. 该场景下还有哪些可用的过滤器、动作或方法?
  3. 是否遗漏了关键配置或逻辑?

解决方案

核心问题在于$order->get_total()返回的是基于全局小数位设置取整后的值,需要直接获取订单原始的未取整金额,并根据订单货币的小数规则格式化。

使用以下代码实现:

add_filter( 'woocommerce_rest_prepare_shop_order_object', 'wc_api_order_total_by_currency_decimals', 20, 3 );
function wc_api_order_total_by_currency_decimals( $response, $order, $request ) {
    // 获取订单使用的货币代码
    $currency = $order->get_currency();
    // 获取对应货币的标准小数位数
    $decimals = wc_get_price_decimals_for_currency( $currency );
    
    // 获取订单原始未取整的总额
    $raw_total = $order->get_meta( '_order_total', true );
    if ( empty( $raw_total ) ) {
        $raw_total = $order->get_total( 'edit' );
    }
    
    // 按货币小数位格式化总额字段
    if ( isset( $response->data['total'] ) ) {
        $response->data['total'] = number_format( (float)$raw_total, $decimals, '.', '' );
    }

    // 批量处理其他金额字段(如小计、运费、税费等)
    $amount_fields = ['subtotal', 'shipping_total', 'tax_total', 'discount_total'];
    foreach ( $amount_fields as $field ) {
        if ( isset( $response->data[$field] ) ) {
            $raw_value = $order->get_meta( '_' . $field, true );
            if ( empty( $raw_value ) ) {
                $raw_value = $order->get_meta( $field, true );
            }
            $response->data[$field] = number_format( (float)$raw_value, $decimals, '.', '' );
        }
    }

    return $response;
}

代码说明

  1. 货币小数位自动匹配:通过wc_get_price_decimals_for_currency()函数自动获取对应货币的标准小数位(JPY为0,USD为2)
  2. 获取原始金额:从订单元数据_order_total或编辑态总额get_total('edit')中获取未被全局小数位取整的原始数值,避免四舍五入误差
  3. 批量处理金额字段:统一处理subtotal、shipping_total等所有金额类字段,确保API返回的所有数值都符合对应货币的小数规则
  4. 优先级设置:将过滤器优先级设为20,确保在WooCommerce默认处理逻辑之后执行,覆盖默认的取整结果

补充注意事项

  • 若使用第三方多货币插件(如WPML、Currency Switcher),需确认插件已正确保存订单的原始货币及金额元数据
  • 可通过订单后台的"自定义字段"面板,验证_order_total等元字段是否存储了带小数的原始金额

内容的提问来源于stack exchange,提问作者Ronin-0822

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 00:02:15