v0.4.0 — WooCommerce Subscriptions integration
What's new
Auto-recalculate tax on every WooCommerce Subscriptions renewal.
The problem this solves
WooCommerce Subscriptions, by default, copies the parent subscription's original tax line onto every renewal order. That works fine on day one — but a year later, when state law has changed, transit-district rates have moved, or the customer has relocated, the renewal still bills the original rate. You silently under-collect (or over-collect) for months until someone notices.
What v0.4.0 does
A new `SubscriptionsBridge` hooks `wcs_renewal_order_created` (priority 20) and forces a fresh tax recalculation:
- WC's `calculate_taxes()` walks the renewal's line items
- That triggers `woocommerce_calc_tax`
- Which lands in our `TaxHandler`
- Which calls the engine with today's rates
- Renewal order saved with correct tax
The per-jurisdiction breakdown is also captured on the renewal so the admin order-edit page shows the same audit table as a regular order.
When it activates
The bridge is gated on `class_exists('WC_Subscriptions')`. If WC Subscriptions isn't installed, the hook is never registered — zero performance or behavior impact for the vast majority of stores.
If WC Subscriptions IS installed, the bridge activates automatically. No configuration toggle.
Failure handling
Recalc failures (engine unreachable, network issue, etc.) are caught and logged to the PHP error log; the renewal proceeds with whatever tax was inherited. Better to be a few cents off than to block a renewal payment.
⚠️ Live testing limitation
Live verification against the actual WC Subscriptions plugin (a paid $199/yr product) is deferred to merchants and contributors who own it. The integration is built against the documented `wcs_renewal_order_created` hook signature and verified with stubs in CI. Real-world signal is welcomed via GitHub issues — particularly:
- Address scenarios where the customer's destination changes mid-subscription
- Edge cases around tax-exempt customers becoming non-exempt (or vice-versa)
- Rate-change behavior across renewal boundaries
Quality gate
- 98/98 unit tests pass (7 new in `SubscriptionsBridgeTest`: detection-not-installed / register no-op / detection-active / register-hooks / recalc-method-call-sequence / recalc-survives-errors / recalc-skips-non-object)
- PHPStan level=max clean
- PHP-CS-Fixer (PSR-12 + risky) clean
- Security review re-run for v0.4.0: hook gating ✓, defensive type-checks on hook payload ✓, zero surface change for installs without WC Subscriptions ✓
Upgrade
Drop-in upgrade from v0.3.3 — no configuration required. The bridge auto-activates if WC Subscriptions is present and is invisible otherwise.
```bash
cd wp-content/plugins/opensalestax-woocommerce
git pull
composer install --no-dev
```
Full changelog
See CHANGELOG.md.