如何让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会返回所有货币的正确小数总额,但日元价格在前端也会显示小数,不符合需求
待解决问题
- 如何在保持后台和前端日元无小数的前提下,让API根据货币规则返回对应小数位的总额?
- 该场景下还有哪些可用的过滤器、动作或方法?
- 是否遗漏了关键配置或逻辑?
解决方案
核心问题在于$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; }
代码说明
- 货币小数位自动匹配:通过
wc_get_price_decimals_for_currency()函数自动获取对应货币的标准小数位(JPY为0,USD为2) - 获取原始金额:从订单元数据
_order_total或编辑态总额get_total('edit')中获取未被全局小数位取整的原始数值,避免四舍五入误差 - 批量处理金额字段:统一处理
subtotal、shipping_total等所有金额类字段,确保API返回的所有数值都符合对应货币的小数规则 - 优先级设置:将过滤器优先级设为20,确保在WooCommerce默认处理逻辑之后执行,覆盖默认的取整结果
补充注意事项
- 若使用第三方多货币插件(如WPML、Currency Switcher),需确认插件已正确保存订单的原始货币及金额元数据
- 可通过订单后台的"自定义字段"面板,验证
_order_total等元字段是否存储了带小数的原始金额
内容的提问来源于stack exchange,提问作者Ronin-0822
相关产品推荐
相关产品推荐

