joseph-leedy / module-custom-fees

joseph-leedy/module-custom-fees

Adds configurable custom fees to orders

magento2-module Compatibility: 2.4.7-2.4.9 Code Quality: Fail Tests: N/A Security: Pass OSL-3.0

Latest Stable Version Integration Test Status PHP Version Required Magento Version Required Hyvä Compatibility Total Downloads GitHub Sponsors

Custom Fees for Magento 2

by Joseph Leedy

Custom Fees allows merchants to configure additional fees to be charged to
customers when orders are placed.

Features

  • Allows fees to be configured with a label and amount to be added to an order
    • Custom fees configuration can be imported via a CSV spreadsheet
    • Conditions can be defined to determine whether a custom fee should be
      applied to an order based on product and cart details, including
      specific product attributes, product SKU, cart subtotal, cart item count,
      total cart weight and more
    • Custom fees can be applied as a fixed amount or a percentage of the order
      subtotal
  • Custom fees are displayed for orders, invoices and credit memos in both the
    frontend and backend
  • Custom fees can be charged and displayed including or excluding tax
  • Custom fees can be refunded via Magento's credit memo functionality
  • Discounts can be applied to custom fees using Cart Price Rules
  • Includes a report detailing all charged custom fees for a given time period
  • Fully compatible with the Hyvä theme (Hyvä Default, Hyvä CSP, Hyvä Checkout
    and Hyvä Checkout CSP)

Requirements

  • PHP 8.1 or greater
  • Magento Open Source 2.4.4 or greater, Adobe Commerce 2.4.4 or greater, or
    Mage-OS 1.0 or greater*
  • MySQL 8.0.4 or greater, MariaDB 10.6.0 or greater, or a MySQL 8-compatible
    database server (for generating reports)

Note: Mage-OS compatibility has not been tested, but it
is functionally equivalent to Magento Open Source 2.4.6 or greater.

Installation

This extension can be installed via Composer from Packagist by running
these commands from a terminal on a Web server or in the desired installation
location:

cd /path/to/your/store
composer require joseph-leedy/module-custom-fees
php bin/magento module:enable JosephLeedy_CustomFees
php bin/magento setup:upgrade
php bin/magento setup:di:compile
php bin/magento setup:static-content:deploy

Updating

This extension can be updated via Composer from Packagist by running
these commands from a terminal on a Web server or in the desired installation
location:

cd /path/to/your/store
composer update joseph-leedy/module-custom-fees
php bin/magento setup:upgrade
php bin/magento setup:di:compile
php bin/magento setup:static-content:deploy

Usage

Configuration

Custom Fees

Custom Fees can be added from the Magento Admin panel by going to Stores > Settings > Configuration > Sales > Sales > Custom Order Fees. The overall
display order of the Custom Fees block in relation to other totals shown in the
cart and checkout can be configured at Stores > Settings > Configuration > Sales > Sales > Checkout Totals Sort Order. All settings for this extension
can be configured in the Global (Default), Website or Store scope.

Report Aggregation

Report aggregation can be configured at Stores > Settings > Configuration > General > Reports > Custom Order Fees Report.

Taxes

Taxes can be configured at Stores > Settings > Configuration > Sales > Tax.

Available Settings
Setting Section Description Default
Tax Class for Custom Fees Tax Classes Sets the class used to determine fee tax amount None
Custom Fees Calculation Settings Sets whether the custom fees entered include or exclude tax Excluding Tax
Display Custom Fee Amount Shopping Cart Display Settings Controls how custom fees are shown in the Cart and Checkout Excluding Tax
Display Custom Fee Amount Orders, Invoices, Credit Memos Display Settings Controls how custom fees are shown on the Sales pages Excluding Tax

Importing Custom Fees

The Custom Fees configuration page allows fees to imported from a CSV
spreadsheet containing the following columns:

Column Description Example
code A unique code identifying the custom fee (allowed characters: "A-Z", "a-z", "0-9", "_") example_fee
title A short label describing the custom fee "Example Fee"
type The type of custom fee ("fixed" or "percent" [of order subtotal]) "fixed"
status Whether the custom fee is enabled or diasbled ("0", "disabled", "1", "enabled") "enabled"
show_percentage Optional - Whether or not to show the percentage next to the fee name ("0", "n", "no", "1", "y", "yes") "yes"
value The amount of the custom fee, in the store's default currency 5.00
Example CSV Import Spreadsheet
code,title,type,status,show_percentage,value
example_fee,"Example Fee",fixed,enabled,0,5.00

Configuring Adavanced Settings

Additional settings for a Custom Fee, including Conditions, can be found in the
Advanced Settings dialog by clicking on the cog icon "⚙️."

Reporting

To view a report of the collected custom order fees, go to Reports > Sales > Custom Order Fees in the Magento Admin panel.

Note: For performance reasons, the report generation process makes use of
special database functions that are only available in MySQL 8.0.4+ or
MariaDB 10.6.0+. Errors or unexpected behavior may occur when using incompatible
database server software versions.

Applying Discounts to Custom Fees

To apply a discount to a custom fee, go to Marketing > Promotions > Cart Price Rules in the Magento Admin panel and follow these instructions:

  1. Click on "Add New Rule" or select an existing rule
  2. Expand the "Actions" section and click on the "Apply to Custom Fee Amount"
    toggle

Note: To apply a discount to a specific custom fee, add an action
condition by following these instructions:

  1. In the "Actions" section, under the "Apply the rule only to cart items
    matching the following conditions..." heading, click on the green plus icon
  2. Select "Custom Fee" from the condition dropdown
  3. Click on the ellipses button and choose the desired custom fee from the list

Support

If you experience any issues or errors while using this extension, please
open an issue in the GitHub repository. Be sure to include all relevant
information, including a description of the issue or error, what you were doing
when it occurred, what versions of Magento Open Source or Adobe Commerce and PHP
are installed and any other pertinent details. I will do my best to respond to
your request in a timely manner.

License

The source code contained in this extension is licensed under the Open Software
License version 3.0 (OSL-3.0) license. A copy of this license can be found in
the LICENSE file included with the source code or online at
https://opensource.org/licenses/OSL-3.0.

Copyright for the included source code is exclusively held by Joseph Leedy,
all rights reserved.

History

A full history of the extension can be found in the CHANGELOG.md file.

Contributing

We welcome and value your contribution. For more details on how you can help us
improve and maintain this tool, please see the CONTRIBUTING.md file.

Shout-Outs

Contributors

These wonderful people have helped this extension become what it is today, and
I am truly grateful to them for their contributions:

Supporters

I owe the following fine folks a debt of gratitude for their continuing
support:

Changelog for Custom Fees for Magento 2 by Joseph Leedy

All notable changes to this extension will be documented in this file.

The format is based on Keep a Changelog, and this extension adheres to
Semantic Versioning.

For more information about this extension, please refer to the README
document.

Unreleased

1.5.0

Added

  • A product attribute that can be used to determine whether or not a custom fee
    should be applied to an order is now created automatically when the extension
    is installed
  • Data for the Custom Order Fees Report can now be aggregated automatically on
    a chosen schedule
  • Custom fees can now be charged with tax and displayed inclusive or exclusive
    of tax
  • Cart Price Rules can now be used to apply discounts to custom fees for
    orders, invoices and credit memos

Changed

  • Ordered custom fees are now indexed by their corresponding fee code
  • Data for ordered, invoiced and refunded custom fees is now represented by
    models with corresponding interfaces instead of arrays
  • Usages of the mixed[] type for extension attributes have been replaced with
    the new interfaces for ordered, invoiced and refunded custom fees
  • All total models, blocks and other logic now use the new interfaces and models

Removed

  • The data patch used to add missing fields to the existing custom order fees
    data has been removed
  • The plug-in used to temporarily store the refunded custom fee amounts entered
    in the Admin panel during credit memo creation has been removed

1.4.0

  • This version was skipped due to an issue with creating the tag for it

1.3.2

Fixed

  • Missing return type annotations have been added to the Custom Order Fees
    Interface
  • Incorrect sales orders were included in packing slips printed from the
    Magento Admin panel (caused by the plug-in used to join custom order fees
    with sales orders in the Admin Sales Order Grid)

1.3.1

Changed

  • Totals in the Custom Order Fees Report are now sorted by order currency

Fixed

  • Custom fee totals were rendered for the related order instead of the
    invoice or credit memo on sales PDF files printed from the Magento Admin panel

1.3.0

Added

  • Custom fees can be enabled or disabled
  • Custom fees can be refunded from credit memos without requiring an adjustment
    fee (the previous work-around was to create an adjustment fee of the same
    amount as the custom fee)

Changed

  • Renamed the custom_fees column in the custom_order_fees table to clarify
    its purpose (new name: custom_fees_ordered)
  • The custom_order_fees table now includes a column called
    custom_fees_refunded to track the total amount of custom fees refunded for
    each credit memo related to the order
  • The Custom Order Fees Report now includes a column for the total amount of
    custom fees refunded for each order, aggregated from the new
    custom_fees_refunded column in the custom_order_fees table
  • The custom_order_fees table now includes a column called
    custom_fees_invoiced to track the total amount of custom fees invoiced for
    each invoice related to the order

Deprecated

  • The method retrieve() in the CustomFeesRetriever service has been
    deprecated in favor of the retrieveOrderedCustomFees() method

1.2.3

Fixed

  • An exception was thrown when loading the Sales Order Grid in the Admin panel
    if the JSON data in the custom_order_fees table was quoted

1.2.2

Fixed

  • The Custom Order Fees Report did not aggregate custom fees if the custom
    order fee data was quoted in the database
  • The Custom Order Fees Report did not aggregate custom fees if the related
    orders had multiple invoices

Changed

  • Regenerated the database schema allowlist to add missing constraints for the
    custom_order_fees table

1.2.1

Fixed

  • Custom fees were not calculated correctly when calculating totals for
    orders with multiple invoices
  • Custom fees were not calculated correctly when calculating totals for
    orders with multiple credit memos

1.2.0

Added

  • Configuration for custom fees can be imported from a CSV spreadsheet
  • Conditions can be defined in the extension configuration to determine whether
    or not to apply a custom fee to an order
  • Custom Fees can be calculated as a percentage of an order's subtotal

1.1.1

Fixed

  • Softened dependency on Zend Framework 1 Database component to fix
    incompatibility with Magento 2.4.4 and 2.4.5

1.1.0

Added

  • Custom fees are now rendered in columns in the Sales Order Grid in the Admin
    panel
  • A report summarizing the total amount of collected custom order fees can be
    generated from the Admin panel
  • Custom fees are now rendered on the Cart page in the Hyvä frontend
  • Custom fees are now rendered on the Checkout pages in the Hyvä frontend

Fixed

  • Reorded custom fees totals to be placed after tax totals on customer and
    guest order, invoice and credit memo pages in Hyvä frontend

1.0.2

Fixed

  • Mark constructor parameters as explicitly nullable in custom order fees model
    to fix deprecation errors thrown by PHP 8.4

Changed

  • Moved the Custom Fees configuration field to be placed after the Tax
    field in the Totals Sort Order group

1.0.1

Fixed

  • Narrowed type for custom_fees Cart extension attribute to fix Swagger error
  • Added and updated method annotations in Custom Order Fees Interface to fix
    Swagger errors

1.0.0

Added

  • Initial version of extension
Versions
Version Stability QA Status Compatibility Released
1.5.0 stable Fail Magento 2.4.7-2.4.9 Details 2026-04-05 21:45:38
1.3.2 stable Not tested Not yet tested Details 2025-11-26 17:30:12
1.3.1 stable Not tested Not yet tested Details 2025-11-14 20:20:23
1.3.0 stable Not tested Not yet tested Details 2025-10-01 21:45:16
1.2.3 stable Not tested Not yet tested Details 2025-09-16 16:00:13
1.2.2 stable Not tested Not yet tested Details 2025-09-10 17:36:10
1.2.1 stable Not tested Not yet tested Details 2025-08-07 17:56:46
1.2.0 stable Not tested Not yet tested Details 2025-07-01 23:05:18
1.2.0-beta.1 beta Not tested Not yet tested Details 2025-06-27 20:19:44
1.1.1 stable Not tested Not yet tested Details 2025-05-08 16:21:24
1.1.0 stable Not tested Not yet tested Details 2025-05-05 15:01:40
1.0.2 stable Not tested Not yet tested Details 2025-04-10 22:51:47
1.0.1 stable Not tested Not yet tested Details 2025-04-08 22:18:48
1.0.0 stable Not tested Not yet tested Details 2025-02-05 00:18:02

Requires 25

Package Constraint
php ^8.1
ext-json *
ext-pcre *
magento/framework ~103.0.4
magento/module-backend ~102.0.4
magento/module-catalog ~104.0.4
magento/module-checkout ~100.4.4
magento/module-config ~101.2.4
magento/module-cron ~100.4.4
magento/module-directory ~100.4.4
magento/module-eav ~102.1.4
magento/module-quote ~101.2.4
magento/module-media-storage ~100.4.3
magento/module-reports ~100.4.4
magento/module-rule ~100.4.3
magento/module-sales ~103.0.4
magento/module-sales-rule ~101.2.4
magento/module-shipping ~100.4.4
magento/module-store ~101.1.4
magento/module-tax ~100.4.4
magento/module-ui ~101.2.4
psr/log >= 1.0
symfony/polyfill-php83 ^1.27
symfony/polyfill-php84 ^1.30
symfony/polyfill-php85 ^1.33

Requires-dev 11

Package Constraint
colinodell/psr-testlogger ^v1.3
dms/phpunit-arraysubset-asserts ^0.5.0
squizlabs/php_codesniffer ^3.10
dealerdirect/phpcodesniffer-composer-installer ^1.0
magento/magento-coding-standard *
phpstan/phpstan ^1.12 || ^2.1
phpstan/extension-installer ^1.4
bitexpert/phpstan-magento ^v0.32 || ^v0.40
phpunit/phpunit ^9.6
php-parallel-lint/php-parallel-lint ^1.4
friendsofphp/php-cs-fixer ^v3.75

Suggests 2

Package Reason
magento/zendframework1 Version 1.15 is used to interact with the database in Magento 2.4.4 and 2.4.5
magento/zend-db Version 1.16 is used to interact with the database in Magento 2.4.6+

Compatibility

Each Magento release line is installed on its supported PHP versions, then the module is built (DI compilation + static-content deploy) and its unit and integration suites are run. The matrix shows the lines and PHP versions the module is confirmed to install and run on. Code-quality results further down (phpstan, phpcs, …) are reported separately and never affect compatibility.

Compatibility matrix (Magento × PHP)
Magento PHP 8.2 PHP 8.3 PHP 8.4 PHP 8.5
2.4.7 Pass Pass
2.4.8 Pass Pass
2.4.9 Pass Pass

Code Quality

Advisory checks against the module's source. Static analysis runs once across the whole module; PHPStan re-runs per Magento + PHP version because resolvable symbols differ between releases. These NEVER affect the Compatibility badge — a phpcs finding can't make a module incompatible.

Static analysis

Coding standards (phpcs), mess detection (phpmd), copy-pasted code (cpd), PHP cross-version compatibility, composer.json validity. Each runs once for the whole module.

Static analysis results
Tool Status Findings Summary
PHPCS Fail 132 51 errors, 81 warnings (ruleset: Magento2) — 60 auto-fixable with phpcbf
PHPMD Warning 32 32 rule violations (UnusedFormalParameter:14, ExcessiveMethodLength:8, NPathComplexity:4, CyclomaticComplexity:3, ExcessiveParameterList:1)
Cpd Warning 28 28 duplicated chunks spanning 1235 total lines (min-lines=5, min-tokens=70)
Composer validate Info 2 valid; 2 advisory notes (composer validate --strict)

PHPStan

Type-checks the module's PHP against a real Magento install at the configured gate level. Re-runs per Magento and PHP version because resolvable symbols differ between releases. Cell → details modal.

PHPStan results by Magento and PHP version
Magento PHP 8.2 PHP 8.3 PHP 8.4 PHP 8.5
2.4.7 111 111
2.4.8 111 111
2.4.9 111 111

Tests

Unit and integration suites, run for each applicable Magento and PHP version. A test failure speaks to the module's behaviour, not its compatibility with a Magento line, so it is reported here separately and never reddens the compatibility matrix.

Unit tests

Unit tests results by Magento and PHP version
Magento PHP 8.2 PHP 8.3 PHP 8.4 PHP 8.5
2.4.7 N/A N/A
2.4.8 N/A N/A
2.4.9 N/A N/A

Integration tests

Integration tests results by Magento and PHP version
Magento PHP 8.2 PHP 8.3 PHP 8.4 PHP 8.5
2.4.7 N/A N/A
2.4.8 N/A N/A
2.4.9 N/A N/A

Security

Security checks run directly against the module: an audit of its declared dependencies for known vulnerabilities (composer audit) and a scan of its source for malware and web-shell signatures. Each runs once. A malware detection fails the version outright.

Security results
Tool Status Findings Summary
Composer audit Pass 0
Malware scan Pass 0
License
OSL-3.0
Authors
Make it pay

Turn an existing module into recurring revenue.

If you already maintain a Magento 2 module on GitHub or GitLab, listing it on Packagento takes about five minutes. We mirror your tags, handle distribution signing, and route paid licenses through Stripe Connect, so you can keep shipping the way you already do.