PHPackages                             ejosterberg/module-opensalestax - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Utility &amp; Helpers](/categories/utility)
4. /
5. ejosterberg/module-opensalestax

ActiveMagento2-module[Utility &amp; Helpers](/categories/utility)

ejosterberg/module-opensalestax
===============================

Magento 2 module — destination-based US sales tax via the self-hosted OpenSalesTax engine

v1.3.13(3w ago)016[5 PRs](https://github.com/ejosterberg/opensalestax-magento/pulls)Apache-2.0PHPPHP ^8.1CI passing

Since May 14Pushed 3w agoCompare

[ Source](https://github.com/ejosterberg/opensalestax-magento)[ Packagist](https://packagist.org/packages/ejosterberg/module-opensalestax)[ Docs](https://github.com/ejosterberg/opensalestax-magento)[ RSS](/packages/ejosterberg-module-opensalestax/feed)WikiDiscussions main Synced 1w ago

READMEChangelog (10)Dependencies (5)Versions (24)Used By (0)

OpenSalesTax for Magento 2
==========================

[](#opensalestax-for-magento-2)

> **v0.1.0 alpha.** Installable; passes its unit tests; not yet validated against a real Magento storefront. See `kickoff/` and `specs/` for the build plan.

A free, self-hostable Magento 2 module that swaps Magento's built-in tax calculator for the [OpenSalesTax engine](https://github.com/ejosterberg/opensalestax) on US-destination, USD checkouts. No per-transaction fees, no SaaS lock-in — merchants run both Magento and OpenSalesTax on their own infrastructure.

What this module does
---------------------

[](#what-this-module-does)

- Hooks `Magento\Tax\Model\Calculation::getRate` via a plugin (see [`specs/decisions/001-tax-extension-point.md`](specs/decisions/001-tax-extension-point.md)) to substitute Magento's tax-table rate with the rate computed by your OpenSalesTax engine for the customer's destination.
- Hooks `Magento\Quote\Model\Quote\Address\Total\Tax::collect` to surface per-jurisdiction tax breakdown ("Minnesota State Sales Tax", "Hennepin County Tax", ...) in the cart and order summary screens.
- Falls back to Magento's built-in tax tables on non-US destinations, non-USD currencies, or any engine error (default fail-soft behavior).

What this module does NOT do
----------------------------

[](#what-this-module-does-not-do)

- File or remit tax (calculation only — the merchant remits)
- Validate addresses
- Handle non-USD currencies or non-US destinations (passes those through to Magento)
- Validate tax-exempt customer certificates against state DORs
- Ship with the engine bundled — point it at your own [OpenSalesTax engine](https://github.com/ejosterberg/opensalestax)

Requirements
------------

[](#requirements)

- Magento 2 `^2.4.6` (PHP 8.1+)
- A reachable [OpenSalesTax engine](https://github.com/ejosterberg/opensalestax) instance (v0.22.0 or later)

Install
-------

[](#install)

```
composer require ejosterberg/module-opensalestax
bin/magento module:enable EJOsterberg_OpenSalesTax
bin/magento setup:upgrade
bin/magento setup:di:compile
bin/magento cache:clean
```

Configure
---------

[](#configure)

Stores → Configuration → Sales → Tax → **OpenSalesTax**

FieldPathDefaultPurposeEngine API URL`osstax/general/api_url`(empty)Base URL of your OST engine, e.g. `https://ost.example.com`API Token (optional)`osstax/general/api_token`(empty)Bearer token if your engine requires authentication. Stored encrypted in `core_config_data`.Fail Hard on Engine Error`osstax/general/fail_hard`NoIf **Yes**, an unreachable engine blocks checkout. If **No**, the module falls back to Magento's tax tables and logs a warning.While `api_url` is empty the module is inert — Magento's built-in tax calc handles everything.

How it works
------------

[](#how-it-works)

1. At checkout, Magento builds the cart totals. The totals pipeline reaches `Magento\Quote\Model\Quote\Address\Total\Tax::collect`.
2. Our plugin's `beforeCollect` checks the gate (configured? USD? shipping to US?). If all three are yes, it builds an OST engine payload from the quote and calls `POST /v1/calculate`.
3. The engine returns per-line tax + per-jurisdiction breakdown. We cache this in a request-scoped registry keyed by quote id.
4. Magento then asks `Calculation::getRate` for the rate to apply per line. Our plugin reads from the registry and returns the OST-derived effective rate, which Magento applies in the usual way.
5. Our `afterCollect` writes the per-jurisdiction breakdown onto the totals object so cart and order screens display individual jurisdictions instead of a single opaque tax line.

If any check fails (non-US, non-USD, engine down without fail-hard), control returns silently to Magento's built-in tax calc.

Logging
-------

[](#logging)

All engine interactions log structured metadata (quote id, line count, HTTP status, RTT in milliseconds) via Magento's `Psr\Log\LoggerInterface`. **Customer addresses and full payloads are never logged.** The API token is decrypted in memory only at request time and never written to logs.

Development
-----------

[](#development)

```
composer install
composer check       # runs phpunit + phpstan + phpcs + composer audit
```

See [`CONTRIBUTING.md`](CONTRIBUTING.md) for branch model, DCO sign-off, and the quality gate.

License
-------

[](#license)

Dual-licensed under your choice of [Apache-2.0](LICENSE-APACHE.txt) OR [GPL-2.0-or-later](LICENSE-GPL.txt). See [`LICENSE`](LICENSE).

###  Health Score

43

—

FairBetter than 89% of packages

Maintenance96

Actively maintained with recent releases

Popularity8

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity52

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~0 days

Total

18

Last Release

21d ago

Major Versions

v0.1.0 → v1.0.02026-05-14

### Community

Maintainers

![](https://www.gravatar.com/avatar/b647ae9c341fdf92c36cb479ba7535c2eff9ac92f8614965a3b5953f7b543152?d=identicon)[ejosterberg](/maintainers/ejosterberg)

---

Top Contributors

[![ejosterberg](https://avatars.githubusercontent.com/u/6363457?v=4)](https://github.com/ejosterberg "ejosterberg (55 commits)")

---

Tags

magentomagento-modulemagento2opensalestaxsales-taxtaxtax-providerus-taxmagentomagento2taxsales taxopensalestaxus-tax

###  Code Quality

TestsPHPUnit

Static AnalysisPHPStan

Type Coverage Yes

### Embed Badge

![Health badge](/badges/ejosterberg-module-opensalestax/health.svg)

```
[![Health](https://phpackages.com/badges/ejosterberg-module-opensalestax/health.svg)](https://phpackages.com/packages/ejosterberg-module-opensalestax)
```

###  Alternatives

[ecotone/ecotone

Enterprise architecture layer for Laravel and Symfony — CQRS, Event Sourcing, Durable Workflows (Sagas, Orchestrators), Projections, and Outbox messaging via PHP attributes.

562565.8k41](/packages/ecotone-ecotone)[run-as-root/magento2-prometheus-exporter

Magento2 Prometheus Exporter

68353.9k](/packages/run-as-root-magento2-prometheus-exporter)[opengento/module-gdpr

Gdpr Compliance Module for Magento 2

14484.6k](/packages/opengento-module-gdpr)[baldwin/magento2-module-less-js-compiler

Allows Magento 2 to compile less files using the less nodejs compiler

2350.1k](/packages/baldwin-magento2-module-less-js-compiler)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
