Integrate a custom fee to the tax calculation
Add additional taxable fees to sold products.
You might need to add fees to products when calculating tax, and then calculate tax for those fees.
Add a custom fee
The Stripe Tax module creates requests at the point of order, invoice, and credit memo creation and sends them to the Stripe Tax calculation API. The module runs through the items of the quote, invoice, or credit memo to add the details of the items or the entire order to the calculation request.
If you add a custom fee that requires tax calculation, you need to provide the details to the Stripe Tax module so the tax calculation request can add it.
In this integration, the developer of the custom fee provides the total value of the custom fee through an observer. The custom fee is added to the Tax calculation API request and sent to Stripe for calculation.
How the Stripe Tax module works
The Stripe Tax module adds fees based on where the fees occur:
- At the item level, the tax applies to each item of the quote, invoice, and credit memo.
- At the quote, order, invoice, or credit memo level, the tax applies to the whole cart.
The third-party developer must send the following details:
- The total price of the custom fee (if an item has a custom tax of 3, and the item quantity is 2, the value sent is 6)
- The tax class for the custom fee
- The code of the custom fee
These three components will be sent forward in an array with the following structure:
$details = [ 'amount' => $amountValue, // generic value—provide your own when developing 'tax_class_id' => $classId, // generic value—provide your own when developing 'code' => 'custom_fee' // generic value—provide your own when developing ];
You need to send this array structure based on the action being performed (quote calculation, invoice creation, or credit memo creation) and where the custom fee applies (item, quote, invoice, or credit memo level).
The observer sends this information to the Tax module, and provides an object that the information is added to. The observer needs to listen to one of the following six events, depending on the stage of the order process and where the custom fee needs to be applied:
stripe_applies to the items on an order.tax_ additional_ fee_ item stripe_applies to the quote.tax_ additional_ fee_ quote stripe_applies to invoice items.tax_ additional_ fee_ invoice_ item stripe_applies to the whole invoice.tax_ additional_ fee_ invoice stripe_applies to credit memo items.tax_ additional_ fee_ creditmemo_ item stripe_applies to the whole credit memo.tax_ additional_ fee_ creditmemo
Each of the events contains a Magento data object called additional_ where you can add the details of what needs to be calculated by the Stripe Tax module. To add the details of the tax calculation, call the method ->addAdditionalFee() with the details array as a parameter:
$additionalFees = $observer->getAdditionalFeesContainer(); // other operations to get the values to send forward $details = [ 'amount' => $amountValue, // generic value—provide your own when developing 'tax_class_id' => $classId, // generic value—provide your own when developing 'code' => 'custom_fee' // generic value—provide your own when developing ]; $additionalFees->addAdditionalFee($details); }
For cases when these additional fees might be added either on a parent or child item (for example, a bundled dynamic product), we send events for both the bundled product and the products within it.
When using bundled products or other products where you can specify the quantity of the top-level product and sub-product separately, send the amount of the additional fee, and consider the quantity of both the parent and child items.
After Stripe calculates the tax for the invoices, you receive an array of the tax and the base tax. You can use this information to set custom fields in the database, if required. The array contains the fee code as a key and the calculated values that are set for it. You can access the array by calling the getAdditionalFeesTax() method in the item or on the invoice.
Example for applying tax on the item at the quote level
Inside your events file (app/code/Vendor/YourModule/etc/events.), add the following event:
<event name="stripe_tax_additional_fee_item"> <observer name="your_custom_observer_name" instance="Vendor\YourModule\Observer\AddAdditionalFeeForQuoteItem" /> </event>
The data provided to the event in addition to the additional_ is:
item: The item the tax is calculated for.quote: The quote the item belongs to.
Inside your observer file (app/code/Vendor/YourModule/Observer/AddAdditionalFeeForQuoteItem.), add the code for creating the calculation details, as in the following example:
<?php namespace Vendor\YourModule\Observer; use \Magento\Framework\Event\ObserverInterface; use \Magento\Framework\Event\Observer; class AddAdditionalFeeForQuoteItem implements ObserverInterface { public function execute(Observer $observer) { $additionalFees = $observer->getAdditionalFeesContainer(); $item = $observer->getItem(); $quote = $observer->getQuote(); // Calculations where you determine that the item has an additional tax and the tax needs to be calculated // After the calculations are complete and you have the values, add them to the details array and send the array forward $itemDetails = [ 'amount' => $amount, // generic value determined from previous calculations—provide your own when developing 'tax_class_id' => $taxClassId, // generic value determined from previous calculations—provide your own when developing 'code' => 'custom_fee' // generic value—provide your own when developing ]; $additionalFees->addAdditionalFee($itemDetails); } }
Example for applying tax at the quote level
Inside your events file (app/code/Vendor/YourModule/etc/events.), add the following event:
<event name="stripe_tax_additional_fee_quote"> <observer name="stripe_tax_additional_fee_quote" instance="Vendor\YourModule\Observer\AddAdditionalFeeForQuote" /> </event>
The data provided to the event in addition to the additional_ is:
quote: The quote the tax is calculated fortotal: The collected totals up to this point
Inside your observer file (app/code/Vendor/YourModule/Observer/AddAdditionalFeeForQuote.), add the code for creating the calculation details, as in the following example:
<?php namespace Vendor\YourModule\Observer; use \Magento\Framework\Event\ObserverInterface; use \Magento\Framework\Event\Observer; class AddAdditionalFeeForQuote implements ObserverInterface { public function execute(Observer $observer) { $additionalFees = $observer->getAdditionalFeesContainer(); $quote = $observer->getQuote(); $total = $observer->getTotal(); // Calculations where you determine that the quote has an additional tax and the tax needs to be calculated // After the calculations are done and you have the values, add them to the details array and send the array forward $details = [ 'amount' => $amount, // generic value determined from previous calculations—provide your own when developing 'tax_class_id' => $taxClassId, // generic value determined from previous calculations—provide your own when developing 'code' => 'custom_fee' // generic value—provide your own when developing ]; $additionalFees->addAdditionalFee($details); } }
Example for applying tax on the item at the invoice level
Inside your events file (app/code/Vendor/YourModule/etc/events.), add the following event:
<event name="stripe_tax_additional_fee_invoice_item"> <observer name="your_custom_observer_name" instance="Vendor\YourModule\Observer\AddAdditionalFeeForInvoiceItem" /> </event>
The data provided to the event in addition to the additional_ is:
item: The item the tax is calculated for. The observer provides other details, such as the order item.invoice: The invoice that the item belongs to — you can get information such as the order of the item from the invoice.
Inside your observer file (app/code/Vendor/YourModule/Observer/AddAdditionalFeeForInvoiceItem.), add the code for creating the calculation details, as in the following example:
<?php namespace Vendor\YourModule\Observer; use \Magento\Framework\Event\ObserverInterface; use \Magento\Framework\Event\Observer; class AddAdditionalFeeForInvoiceItem implements ObserverInterface { public function execute(Observer $observer) { $additionalFees = $observer->getAdditionalFeesContainer(); $item = $observer->getItem(); $invoice = $observer->getInvoice(); // Calculations where you determine that the item has an additional tax and the tax needs to be calculated // After the calculations are complete and you have the values, add them to the details array and send the array forward $itemDetails = [ 'amount' => $amount, // generic value determined from previous calculations, provide your own when developing 'tax_class_id' => $taxClassId, // generic value determined from previous calculations, provide your own when developing 'code' => 'custom_fee' // generic value, provide your own when developing ]; $additionalFees->addAdditionalFee($itemDetails); } }
Example for applying tax at the invoice level
Inside your events file (app/code/Vendor/YourModule/etc/events.), add the following event:
<event name="stripe_tax_additional_fee_invoice"> <observer name="stripe_tax_additional_fee_quote" instance="Vendor\YourModule\Observer\AddAdditionalFeeForInvoice" /> </event>
The data provided to the event apart from the additional_ is:
invoice: The invoice where the custom fee is appliedorder: The order the invoice belongs to
Inside your observer file (app/code/Vendor/YourModule/Observer/AddAdditionalFeeForInvoice.), add the code for creating the calculation details, as in the following example:
<?php namespace Vendor\YourModule\Observer; use \Magento\Framework\Event\ObserverInterface; use \Magento\Framework\Event\Observer; class AddAdditionalFeeForInvoice implements ObserverInterface { public function execute(Observer $observer) { $additionalFees = $observer->getAdditionalFeesContainer(); $invoice = $observer->getInvoice(); $order = $observer->getOrder(); // Calculations where you determine that the invoice has an additional tax and the tax needs to be calculated // After the calculations are complete and you have the values, add them to the details array and send the array forward $details = [ 'amount' => $amount, // generic value determined from previous calculations, please provide your own when developing 'tax_class_id' => $taxClassId, // generic value determined from previous calculations—provide your own when developing 'code' => 'custom_fee' // generic value—provide your own when developing ]; $additionalFees->addAdditionalFee($details); } }
Changes to credit memos
When creating credit memos, the structure of the array that must be passed back to the Stripe Tax module changes. The tax_ is removed from the array, and the amount_ field must contain the tax amount that you want to refund for the custom fee.
$details = [ 'amount' => $amount, 'amount_tax' => $taxAmount, 'code' => 'custom_fee' ];
Nota
The code component of the details array needs to be the same code component provided in the invoice step. This ensures that Stripe knows what component to subtract the refunded amounts from.
Example for applying tax on the item at the credit memo level
Inside your events file (app/code/Vendor/YourModule/etc/events.), add the following event:
<event name="stripe_tax_additional_fee_creditmemo_item"> <observer name="your_custom_observer_name" instance="Vendor\YourModule\Observer\AddAdditionalFeeForCreditmemoItem" /> </event>
The data provided to the event in addition to the additional_ is:
item: The item the tax is calculated for. The observer also provides other details, such as the order item.creditmemo: The credit memo that the item belongs to.invoice: The invoice that the item belongs to.order: The order that the item belongs to.
Inside your observer file (app/code/Vendor/YourModule/Observer/AddAdditionalFeeForCreditmemoItem.), add the code for creating the details for the calculation as in the following example:
<?php namespace Vendor\YourModule\Observer; use \Magento\Framework\Event\ObserverInterface; use \Magento\Framework\Event\Observer; class AddAdditionalFeeForCreditmemoItem implements ObserverInterface { public function execute(Observer $observer) { $additionalFees = $observer->getAdditionalFeesContainer(); $item = $observer->getItem(); $creditmemo = $observer->getCreditmemo(); $invoice = $observer->getInvoice(); $order = $observer->getOrder(); // Calculations where you determine that the item has an additional tax and the tax needs to be refunded // After the calculations are complete and you have the values, add them to the details array and send the array forward $itemDetails = [ 'amount' => $amount, // generic value determined from previous calculations, please provide your own when developing 'tax_amount' => $taxAmount, // generic value determined from previous calculations, please provide your own when developing 'code' => 'custom_fee' // generic value, please provide your own when developing ]; $additionalFees->addAdditionalFee($itemDetails); } }
Example for applying tax at the credit memo level
Inside your events file (app/code/Vendor/YourModule/etc/events.), add the following event:
<event name="stripe_tax_additional_fee_creditmemo"> <observer name="stripe_tax_additional_fee_quote" instance="Vendor\YourModule\Observer\AddAdditionalFeeForCreditmemo" /> </event>
The data provided to the event in addition to the additional_ is:
creditmemo: The credit memo that the item belongs to.invoice: The invoice that the item belongs to.order: The order that the item belongs to.
Inside your observer file (app/code/Vendor/YourModule/Observer/AddAdditionalFeeForCreditmemo.), add the code for creating the calculation details, as in the following example:
<?php namespace Vendor\YourModule\Observer; use \Magento\Framework\Event\ObserverInterface; use \Magento\Framework\Event\Observer; class AddAdditionalFeeForInvoice implements ObserverInterface { public function execute(Observer $observer) { $additionalFees = $observer->getAdditionalFeesContainer(); $creditmemo = $observer->getCreditmemo(); $invoice = $observer->getInvoice(); $order = $observer->getOrder(); // Calculations where you determine that the invoice has an additional tax and the tax needs to be refunded // After the calculations are complete and you have the values, add them to the details array and sent the array forward $details = [ 'amount' => $amount, // generic value determined from previous calculations, please provide your own when developing 'tax_amount' => $taxClassId, // generic value determined from previous calculations, please provide your own when developing 'code' => 'custom_fee' // generic value, please provide your own when developing ]; $additionalFees->addAdditionalFee($details); } }