Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Opensalestax Bagisto Laravel Package

ejosterberg/opensalestax-bagisto

A Bagisto extension that connects your store to the Open Sales Tax service, calculating accurate US sales tax rates at checkout. It adds tax lookup to Bagisto's cart and order flow, helping merchants handle destination-based sales tax without manual rate tables.

View on GitHub
Deep Wiki
Context7

Getting Started

  1. Install into an existing Bagisto store: composer require ejosterberg/opensalestax-bagisto. Bagisto's package discovery handles the service provider registration.
  2. Publish and inspect the config: php artisan vendor:publish --tag=config (or the package-specific tag listed in the README) and open config/opensalestax.php. This is the first file to read — it is the single source of truth for credentials and the new nexus_states gate.
  3. Set credentials and, new in v0.2.0, the nexus list in .env:
OPENSALESTAX_API_KEY=...
OPENSALESTAX_NEXUS_STATES=MN,WI,IA
  1. Rebuild config cache on every deploy: php artisan config:cache. The nexus list is read at config-build time, so a stale cache is the most common "my change did nothing" cause.
  2. First use case: configure a single nexus state, then place two test orders — one shipping to MN (should hit the OpenSalesTax engine) and one to TX (should never call the engine and fall back to Bagisto's native tax). Confirm the split in your HTTP client logs or the package's log channel before touching production.

The listener registered by the service provider is the second place to look. It is the seam where the v0.2.0 gate lives, and it is what you will extend if env-based config stops being enough.

Implementation Patterns

Treat the nexus list as deployment config, not code. Never hardcode state arrays in a custom listener or observer. One OPENSALESTAX_NEXUS_STATES value per environment keeps staging and production honest and lets finance change the list without a release.

Pair the gate with real Bagisto tax rates. The whole point of the filter is that "Bagisto's built-in tax handles those carts." If your non-nexus tax classes/rates are empty or stale, those orders silently collect zero tax — a compliance problem, not a bug report. Audit tax classes whenever the nexus list changes.

Address-change lifecycle. The gate keys off the cart's shipping destination. Bagisto carts mutate freely during checkout, so verify the listener re-evaluates on the shipping-address update event rather than only at cart creation. Test the flow: start in TX (fallback), switch to MN mid-checkout, confirm the engine rate appears.

Testing with Pest/PHPUnit:

config(['opensalestax.nexus_states' => ['MN', 'WI']]);
Http::fake([/* opensalestax endpoint */]);

// Assert the engine is never called for a TX cart
Http::assertNothingSent();

Cover three cases: in-nexus (engine called), out-of-nexus (no call, Bagisto tax applied), and unset/empty (v0.1 behavior — engine called for everything). The third is your backward-compatibility regression test.

Keep parity across platforms. The release notes deliberately align with WooCommerce v0.5, Vendure v1.2, and Odoo v0.3. If you run more than one storefront, keep the same state list string everywhere — divergence means the same customer gets different tax depending on which store they buy from.

Observability. Log the gate decision (state, in_nexus, engine_called) at info level. When a customer disputes a tax charge, "the engine was skipped because TX wasn't in the nexus list" is the answer you need in one grep, not an investigation.

Extension point. If you outgrow env config — per-channel nexus, DB-driven lists, effective-date ranges — don't fork the listener. Extend it or bind a replacement via the container, and keep the config option as the fallback so the upstream package stays upgradable.

Gotchas and Tips

  • Normalize state codes. The docs say "2-letter state codes"; assume nothing about your input. mn, wi with a trailing space will not match MN. Trim and uppercase before comparing, and validate the parsed list at boot so a typo fails loudly instead of silently disabling tax for a state.
  • Empty is not "none". OPENSALESTAX_NEXUS_STATES= (or unset) restores v0.1 behavior — the engine runs for every state. There is no documented way to express "zero nexus states." If you need to disable the engine entirely, use Bagisto's own tax settings, not this filter.
  • Config caching bites twice. env() calls inside the config file only resolve when the config is cached. Changing .env without config:cache in your deploy script leaves the old nexus list live, and config:clear in production will drop all other cached config. Pick one discipline and script it.
  • Destination-based only. "Shipping to a state" means the ship-to address. It does not account for origin/sourcing rules, local or district taxes, or marketplace-facilitator treatment. The engine owns rate math; this filter only decides whether the engine runs. Don't try to encode sourcing logic into the state list.
  • No-tax states and non-US addresses will never match a 2-letter US code and will therefore always fall through to Bagisto tax. That is usually correct, but confirm it is intentional for your markets — silent fallthrough is easy to miss.
  • Expect totals to shift on upgrade. v0.2.0 is additive and non-breaking at the code level, but the moment you set a nexus list, every non-nexus cart changes tax treatment. Replay a handful of recent orders in staging and diff the totals before promoting.
  • Debug by toggling. To compare engine output against Bagisto output for the same cart, temporarily clear the nexus list (returning to v0.1 behavior), capture the engine's response, then restore the list and compare. Do this in staging — in production, non-nexus carts will start hitting the API and you may incur per-call costs.
  • The list is manual. There is no economic-nexus threshold tracking here — no revenue or transaction counts per state. Put a recurring calendar reminder (quarterly is typical) to review nexus obligations against the configured list.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
roundly-consulting/kubernetes-api-for-laravel
roundly-consulting/plausible-for-laravel
gvp/gvp-laravel-template
metasyncsite/laravel-metasync-client
roundly-consulting/onboarding-for-laravel
andydefer/laravel-notification
adachsoft/cli-process-tester
jhaskell13/laraflow
sebastienheyd/boilerplate-media-manager
ccast/tagixo-primix
pretendtrue/laravel-builder
sawmainek/laravel-scout-tntsearch-driver
tomshaw/laravel-calendar-table
dibakar/laravel-ownership
steadrun/laravel-monitor
labyrinthe/connect-laravel
elmogy/layan
drewdan/sentinel-client
dskripchenko/laravel-llm
fatryst/nuonuo