# joseph-leedy/module-custom-fees

> Adds configurable custom fees to orders

`composer require joseph-leedy/module-custom-fees`

Canonical URL: https://packagento.com/joseph-leedy/module-custom-fees

## At a glance

- **Vendor**: joseph-leedy (https://packagento.com/joseph-leedy.md)
- **Latest version**: 1.5.0 — released 2026-04-05
- **Pricing**: Free
- **Package type**: Magento 2 module
- **Status**: active, accepting new buyers

## Installation

Packagento is licence-gated, so even free packages need a licence on a project before Composer can resolve them.

1. **Sign in or create an account** at https://packagento.com/customer/account/.

2. **Add the package to your account.** Open https://packagento.com/joseph-leedy/module-custom-fees and complete the free checkout. A licence is minted automatically.

3. **Create or pick a project, then activate the licence on it.**
   - Projects represent the Magento installs you deploy to. Manage them at https://packagento.com/projects/.
   - Activate the new licence on the project you'll deploy this package to. Activation is what generates the Composer credentials scoped to that project.

4. **Add the project credentials to your Magento codebase.**

   Grab the project's public + private key from https://packagento.com/projects/ (open the project, then its Credentials tab), and add them to `auth.json`:

   ```json
   {
     "http-basic": {
       "packagento.com": {
         "username": "ppk_live_...",
         "password": "psk_live_..."
       }
     }
   }
   ```

   Add the Packagento Composer repository to `composer.json`:

   ```json
   {
     "repositories": [
       { "type": "composer", "url": "https://packagento.com" }
     ]
   }
   ```

5. **Install and apply.**

   ```bash
   composer require joseph-leedy/module-custom-fees:*
   bin/magento setup:upgrade
   bin/magento setup:di:compile
   bin/magento cache:flush
   ```

## What it does

Adds configurable custom fees to orders

## README

<p align="center">
    <a href="https://packagist.org/packages/joseph-leedy/module-custom-fees"><img src="http://poser.pugx.org/joseph-leedy/module-custom-fees/v" alt="Latest Stable Version"></a>
    <a href="https://github.com/JosephLeedy/magento2-module-custom-fees/actions/workflows/run-integration-tests.yml"><img src="https://img.shields.io/github/actions/workflow/status/JosephLeedy/magento2-module-custom-fees/run-integration-tests.yml?label=integration%20tests" alt="Integration Test Status"></a>
    <a href="https://packagist.org/packages/joseph-leedy/module-custom-fees"><img src="http://poser.pugx.org/joseph-leedy/module-custom-fees/require/php" alt="PHP Version Required"></a>
    <a href="https://packagist.org/packages/joseph-leedy/module-custom-fees"><img src="https://img.shields.io/badge/magento-2.4.4%2B-F46F25" alt="Magento Version Required"></a>
    <a href="https://packagist.org/packages/joseph-leedy/module-custom-fees"><img src="https://img.shields.io/badge/hyvä-compatible-0A23B9" alt="Hyvä Compatibility"></a>
    <a href="https://packagist.org/packages/joseph-leedy/module-custom-fees"><img src="http://poser.pugx.org/joseph-leedy/module-custom-fees/downloads" alt="Total Downloads"></a>
    <a href="https://github.com/sponsors/JosephLeedy"><img alt="GitHub Sponsors" src="https://img.shields.io/github/sponsors/JosephLeedy"></a>
</p>

## 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)

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

### 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:

_(README truncated for .md surface. Full README on https://packagento.com/joseph-leedy/module-custom-fees.)_

## Changelog

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

_(Changelog truncated for .md surface. Full history on https://packagento.com/joseph-leedy/module-custom-fees.)_

## Recent Versions

| Version | Released |
|---|---|
| 1.5.0 | 2026-04-05 |
| 1.3.2 | 2025-11-26 |
| 1.3.1 | 2025-11-14 |
| 1.3.0 | 2025-10-01 |
| 1.2.3 | 2025-09-16 |
| 1.2.2 | 2025-09-10 |
| 1.2.1 | 2025-08-07 |
| 1.2.0 | 2025-07-01 |
| 1.2.0-beta.1 | 2025-06-27 |
| 1.1.1 | 2025-05-08 |

Showing 10 of 14 versions. Full release history on https://packagento.com/joseph-leedy/module-custom-fees.

## Dependencies

### Require

| Package | Constraint |
|---|---|
| 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-media-storage | ~100.4.3 |
| magento/module-quote | ~101.2.4 |
| 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 |
| php | ^8.1 |
| psr/log | >= 1.0 |
| symfony/polyfill-php83 | ^1.27 |
| symfony/polyfill-php84 | ^1.30 |
| symfony/polyfill-php85 | ^1.33 |

### Require (dev)

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

### Suggest

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

## Quality

Latest release (1.5.0) fails the Packagento QA pipeline. Verdicts below are per-cell (Magento line × PHP version) for the matrixed tools, and run-once for the static / security tiers.


### Compatibility

Each Magento line is installed on its supported PHP versions, then the module is built (DI compile + static-content deploy). Cells show passed / failed / untested; staircase gaps render as `–`.

| 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. Never affect the Compatibility verdict — 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.

| 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 against a real Magento install. Re-runs per Magento + PHP version because resolvable symbols differ between releases.

| 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 per Magento + PHP cell. Test failures speak to the module's behaviour, not its compatibility with a line, so they're reported here separately.

#### Unit Tests

| 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

| 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

Dependency-advisory audit (composer audit) plus a source malware scan. A malware detection fails the version outright.

| Tool | Status | Findings | Summary |
|---|---|---|---|
| Composer audit | Pass | 0 |  |
| Malware scan | Pass | 0 |  |

## Licence and pricing

Free. A licence is still minted on checkout and bound to your project for Composer access — no payment step.

Refundable within 14 days of first purchase via https://packagento.com/account/refunds/.

## Install via Claude Code or any MCP client

The Packagento MCP server can run the licence + project + Composer steps above in one tool call:

```
purchase_and_install_packages(
  composer_names=["joseph-leedy/module-custom-fees"],
  project_id="proj_xxx"
)
```

This handles cart, checkout, licence minting, project activation, and writes auth.json credentials. Connect a client with `claude mcp add packagento https://mcp.packagento.com`. Full setup at https://packagento.com/docs/mcp-setup.

## Vendor

joseph-leedy is a Magento 2 vendor on Packagento. See https://packagento.com/joseph-leedy.md for their full catalogue.

