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

Magento 2商品价格/小计保留4位小数 VAT与总计保留2位小数问题咨询

Magento 2 价格舍入误差修复方案

你之前修改数值后被系统自动还原,是因为Magento会在quote更新、地址保存、税费计算等多个环节自动触发默认的价格计算逻辑,仅修改数据库值无法覆盖所有触发场景,需通过自定义插件拦截核心计算逻辑实现需求:

前置准备:创建自定义模块

  • 新建模块目录app/code/Vendor/PriceRounding
  • 创建注册文件app/code/Vendor/PriceRounding/registration.php:
<?php
use Magento\Framework\Component\ComponentRegistrar;
ComponentRegistrar::register(ComponentRegistrar::MODULE, 'Vendor_PriceRounding', __DIR__);
  • 创建模块配置文件app/code/Vendor/PriceRounding/etc/module.xml:
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
    <module name="Vendor_PriceRounding" setup_version="1.0.0">
        <sequence>
            <module name="Magento_Quote"/>
            <module name="Magento_Tax"/>
            <module name="Magento_Sales"/>
        </sequence>
    </module>
</config>

第一步:实现小计先舍入到2位的逻辑

创建依赖注入配置文件app/code/Vendor/PriceRounding/etc/di.xml,拦截小计计算类:

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
    <!-- 拦截小计计算逻辑 -->
    <type name="Magento\Quote\Model\Quote\Address\Total\Subtotal">
        <plugin name="vendor_subtotal_rounding" type="Vendor\PriceRounding\Plugin\SubtotalRoundingPlugin" sortOrder="10"/>
    </type>
    <!-- 拦截税费计算逻辑 -->
    <type name="Magento\Tax\Model\Calculation\AbstractAggregateCalculator">
        <plugin name="vendor_tax_rounding" type="Vendor\PriceRounding\Plugin\TaxCalculationPlugin" sortOrder="10"/>
    </type>
</config>

创建小计处理插件app/code/Vendor/PriceRounding/Plugin/SubtotalRoundingPlugin.php:

<?php
namespace Vendor\PriceRounding\Plugin;
use Magento\Quote\Model\Quote\Address\Total\Subtotal;
use Magento\Quote\Model\Quote\Address;

class SubtotalRoundingPlugin
{
    public function afterCollect(Subtotal $subject, $result, Address $address)
    {
        // 获取4位精度计算出的原始小计
        $rawSubtotal = $address->getSubtotal();
        $baseRawSubtotal = $address->getBaseSubtotal();
        // 舍入到2位
        $roundedSubtotal = round($rawSubtotal, 2);
        $baseRoundedSubtotal = round($baseRawSubtotal, 2);
        // 覆盖地址的小计值,后续所有计算均读取该舍入后的值
        $address->setSubtotal($roundedSubtotal);
        $address->setBaseSubtotal($baseRoundedSubtotal);
        $address->setSubtotalInclTax($roundedSubtotal);
        return $result;
    }
}

第二步:修改税费计算逻辑,基于舍入后的小计计算VAT

创建税费处理插件app/code/Vendor/PriceRounding/Plugin/TaxCalculationPlugin.php:

<?php
namespace Vendor\PriceRounding\Plugin;
use Magento\Tax\Model\Calculation\AbstractAggregateCalculator;
use Magento\Tax\Api\Data\QuoteDetailsInterface;

class TaxCalculationPlugin
{
    public function aroundCalculate(AbstractAggregateCalculator $subject, callable $proceed, QuoteDetailsInterface $quoteDetails, $storeId = null)
    {
        $result = $proceed($quoteDetails, $storeId);
        // 读取已舍入到2位的小计
        $roundedSubtotal = $quoteDetails->getSubtotal();
        $taxRate = $result->getAppliedTaxes()[0]['percent'] / 100;
        // 基于舍入后的小计重新计算VAT
        $calculatedTax = round($roundedSubtotal * $taxRate, 2);
        $baseCalculatedTax = round($roundedSubtotal * $taxRate, 2);
        // 覆盖税费计算结果
        $result->setTaxAmount($calculatedTax);
        $result->setBaseTaxAmount($baseCalculatedTax);
        $result->setGrandTotal($roundedSubtotal + $calculatedTax);
        $result->setBaseGrandTotal($roundedSubtotal + $baseCalculatedTax);
        return $result;
    }
}

第三步:部署生效

执行以下命令启用模块并生效:

bin/magento setup:upgrade
bin/magento setup:di:compile
bin/magento cache:clean

验证注意事项

  • 测试边缘场景:例如商品单价1.0004元,购买3件时4位精度小计为3.0012元,按逻辑会先舍入为3.00元,VAT按3.00元计算,小计+VAT与总金额不会出现1分差额
  • 如需兼容多税率、折扣等场景,可在对应插件中扩展逻辑,统一基于舍入后的2位小计计算即可

内容的提问来源于stack exchange,提问作者Aurel

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 08:09:02