makfly/stripe-cashier-bundle
makfly/stripe-cashier-bundle brings Stripe subscription billing to Symfony applications, offering Cashier-style customer, subscription, invoice, and webhook handling so you can integrate recurring payments with less boilerplate.
Architecture fit. Unchanged at the root: makfly/stripe-cashier-bundle is a Symfony bundle, not a Laravel package, and "Cashier" here is a re-implementation of Laravel Cashier's subscription semantics on Symfony's container and (presumably) Doctrine. v1.6.0 does not alter that framing, but it does materially change the scope of what is being re-implemented:
laravel/cashier has first-party support, thousands of dependents, and now ships equivalent metered billing (Meters API) and Stripe Tax support upstream. There is no scenario where the bundle beats it.Integration feasibility. Installability is unchanged: Composer, MIT, symfony: ^8 — greenfield or freshly upgraded apps only. Two release-specific deltas:
createUsageRecord with the Billing Meters API is exactly the kind of work we flagged as unowned risk last cycle ("Stripe API version drift → deserialization breakage"). Someone did it, in the right direction, ahead of the hard cutoff. That is the strongest evidence to date that the project is alive and that the maintainer reads Stripe changelogs.2026-07-18 stamp we already wanted to sanity-check, this means we cannot treat version numbers below 1.6.0 as evidence of anything — including that v1.5.0 was a considered, tested release. Re-verify provenance of every tag we would depend on.The real integration cost is still the webhook → entitlement pipeline, and it just got larger: tax and metered usage each require their own event handling, their own reconciliation, and their own failure semantics.
Technical risk. Still high, and the profile has shifted rather than improved. Sustainability risk is unchanged (21 stars, zero dependents, single maintainer, no downstream compatibility pressure). What changed is breadth-per-maintainer: the same person who could not be corroborated by a single dependent now owns multi-plan state transitions, meter event emission, and tax computation. Automatic tax in particular is not a wiring exercise — it requires address validation, tax ID collection and validation, reverse-charge and inclusive/exclusive handling, and invoice.finalized correctness. "Wire automatic tax end-to-end" in a changelog with no accompanying test commit is a claim, not a demonstration.
Two release-hygiene concerns worth escalating before any spike:
refactor(1.6.0): ... align quantity method signatures ships in a minor version. If anyone is already on 1.5.x usage records, that is potentially a silent breaking change. We would be adopting at 1.6.0 anyway, so it does not block us — but it is a data point on release discipline.feat, zero flagged test or test:. For billing code, that is the single most important thing to verify in the source.Key questions for the maintainer / our own spike (updated):
Billable-style interface? Who owns schema migrations? (unchanged, still unanswered, still the gate)stripe/stripe-php major and Stripe API version is pinned? Meters requires a recent API version (basil-era or later); what is the floor, and is it documented?event.id, out-of-order reconciliation — implemented or left to us? (unchanged)identifier is used for Stripe-side dedup, and what happens on a 429 or partial failure?customer.tax_id.created/updated, invoice.finalized)? Is reverse-charge / inclusive-tax modeled?Stack fit. Unchanged: viable only inside a Symfony-first application already on 8.x. The bundle remains an optional adapter, never our billing architecture. v1.6.0 does not change that conclusion; it changes the cost of the alternative.
Migration path. The internal-port recommendation is now more important, not less. The port needs to grow beyond BillingGateway / SubscriptionRepository:
SubscriptionRepository — plan state, multi-plan composition, lifecycle transitions.MeteredUsage — report usage with our own idempotency key; the adapter translates to Meters API or falls back to direct SDK.TaxProfile — addresses and tax IDs as our domain data, pushed outward; never read back as the system of record.Define all three before touching the bundle. The point of the port is that v1.6.0's growth in surface area is contained: if the tax integration turns out to be shallow, we swap one adapter and keep our domain model, our schema, and our reconciliation logic.
Compatibility. Pin and verify: PHP (Symfony 8 → 8.4-era), doctrine/orm + doctrine/dbal, symfony/messenger if webhooks route through a queue, and the exact stripe/stripe-php major. New checks: the Stripe API version floor implied by Meters, and whether the bundle's pinned SDK is new enough for the tax endpoints it calls — a mismatched SDK is the most likely way this release fails at runtime. Run composer why-not against our lockfile. Confirm the bundle's webhook route does not collide and now handles the additional event types it needs (invoice.finalized, tax ID events) without swallowing events it silently ignores.
Sequencing.
Maintenance. The fork-and-vendor outcome is now more likely, not less, and the fork is bigger. If we adopt, we inherit ownership of subscription state, meter emission, and tax computation — three subsystems, one of which (tax) carries compliance exposure. Budget a fork under our org with a named owner and an explicit "we will not chase Symfony 9 or the next Stripe API version" decision point. The one genuinely encouraging maintenance datapoint is that the maintainer did perform the Meters migration unaided; that raises the odds the project survives long enough for our fork to stay close to upstream, which lowers fork cost. Removing auto-tag also means releases are now manual — better hygiene, worse throughput, and a bus-factor-of-one release path.
Support. Unchanged: MIT, no commercial backing, no escalation path. The new tax surface makes this worse in kind, not just degree — a tax bug is not an engineering incident, it is a customer-credit and possibly a filing incident. On-call runbooks must cover "we believe tax was miscalculated on invoices in period X," which requires storing raw invoice payloads and tax breakdowns from day one.
Scaling. The primary axis is still events, but metered billing adds a second, much sharper one: usage volume. If the bundle emits one meter event per unit of work, it becomes the bottleneck and the rate-limit victim; verify batching, aggregate client-side before calling in, and enforce our own idempotency identifier so retries are free. Tax adds a read-path wrinkle — tax ID and address data now live in our DB, so data-residency and PII scope widen and must be reviewed before production. Subscription read paths should still be served from our own DB with Stripe as asynchronously reconciled source of truth.
Failure modes to design against.
invoice.finalized.event.id plus a processed-event table. (unchanged)Ramp-up. Engineer ramp on the API surface is unchanged — roughly a week for a mid-level Symfony engineer fluent in Doctrine and DI. What grew is the domain literacy required before that engineer is useful in review: metered billing semantics (aggregation windows, invoice timing, proration of usage) and tax (inclusive vs exclusive, reverse charge, validation) are now in scope alongside the existing proration/dunning/SCA material. Plan 1.5–2 weeks for the spike (up from 1–2) and 5–7 weeks to production hardening, with the extra time specifically in usage and tax reconciliation plus replay tests.
Recommendation. Unchanged in direction, adjusted in emphasis: do not build on this as a foundation. The v1.6.0 release is the first evidence that the project is actively maintained against Stripe's roadmap, which is enough to justify the spike we already costed — and enough to make fork-and-vendor a defensible Plan B if the source read shows real tests behind the tax and meter work. It is not enough to justify skipping the internal port, and the broadened scope means the spike's exit criteria are now stricter, not looser.
How can I help you explore Laravel packages today?