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

Billing For Laravel Laravel Package

pushery/billing-for-laravel

pushery/billing-for-laravel is a Laravel package for adding billing and subscription features to your application, with configurable plans, invoicing, and payment handling for a lightweight, straightforward integration.

View on GitHub
Deep Wiki
Context7

Product Decisions This Supports

  • Marketplace vs. single-merchant architecture. BillingManager::forAccount(PaymentAccount $account) plus per-account credentials, test mode, and Mollie profile means the product can move from "the platform collects and settles later" to "each shop charges into its own Mollie or Stripe account." That is a foundational decision (platform-of-record vs. connected accounts) and it is now a configuration choice rather than a custom build.
  • Revenue timing: collect in advance or in arrears. billing.collection_timing (BILLING_COLLECTION_TIMING) now decides when a new subscription on a package-billed driver is charged: in_advance (the default) bills a period when it begins, the first one at the next billing:run after the mandate exists or when the trial ends; in_arrears keeps the old behaviour of charging at the period's end. This is a pricing-and-cash-flow decision, not a technical one — a yearly subscriber now pays on day one instead of after a year — and it has downstream consequences for dunning (a failed advance invoice is a failed upcoming period, not a past one), refunds, revenue recognition, and churn accounting. Each subscription keeps the timing it started with, so nothing already running changes.
  • Retention lever: pause instead of cancel. PausesSubscriptions::pause() / unpause() stops collection on an active, non-ending subscription and grants no access until resumed. On package-billed drivers the paused days are added back to the period; a cancellation while paused ends it immediately; Stripe maps to pause_collection with void. Decide whether "pause" appears in the cancel flow, which plans may pause, and what (if anything) a paused customer can still see or do. SubscriptionPaused / SubscriptionUnpaused exist precisely so access locks and notices are your policy, not the package's.
  • Proration policy for plan and seat changes. A swap or seat change inside an advance-collected period squares the remainder at once: an upgrade is charged for the time left as its own order with its own invoice after credit is spent; a downgrade leaves the difference as credit that future payments spend first, capped at the period's payment for that time; each tier is valued over its own interval (monthly → yearly costs a twelfth of the yearly price for a month). A provider-refused charge does not undo the change — it stays open and is collected after the next paid cycle. That is a concrete packaging decision: immediate proration vs. next-cycle, credit vs. refund, and how much unpaid-change exposure you tolerate.
  • EU compliance as a product surface. CancellationButton::declare() accepts a cancellation declared on your own pages (signed in or not) as a DeclaredCancellation per § 312k BGB, and withdrawals/prorated cancellations refund the period in progress now that ReadsSubscriptionPayments answers with the order that paid it. Decide whether you sell into DE/EU, whether the statutory button ships, and who signs off. Compliance work moves from legal backlog to configuration plus copy review.
  • SEPA onboarding without a payment. DirectDebitMandates::text() returns the mandate wording for the payer's country under a reference and give() registers it from name + IBAN, with IBAN country/length/check-digit validation before anything reaches Mollie, the exact displayed text recorded, and consent stored once (text, reference, account holder, notice period, when and from where) with erasure unlinking it. This enables a mandate-first or no-card signup path for EU customers; the shipped German wording covers AT, DE, LI, LU, and billing.direct_debit.mandate_wordings takes your own SepaMandateWording elsewhere.
  • AI feature economics. CostCalculator::costOf($model, TokenUsage::fromLaravelAi($response->usage)) prices a call across five token buckets from a dated billing.ai.rates table, and SpendBrake::spend($provider, $cost, owner: $user) enforces per-provider and per-owner daily caps atomically (check-and-count in one statement). The decision this unlocks is whether AI features ship with hard margin protection and per-user fairness limits from day one rather than a post-hoc cost surprise.
  • Packaging of allowances, prepaid units, and overage. Expiring UsageGrants are drawn first-expiring-first, and only then are non-expiring bought prepaid units spent, so nothing that expires goes unused; billing:usage:flush writes off expired remainders each minute as usage.grant_expired; a reference makes a grant idempotent per owner and meter. A blocking meter may declare grace, letting work under way finish past the ceiling, with the excess owed as debt on the balance row and repaid by the next grant before any of its units can be spent. That is the "does the plan reset, and is a hard stop a cliff or a soft overage?" decision, made explicit.
  • Checkout ownership and per-tenant presentation. ChargeOptions still carries return/cancel/webhook URLs, locale, methods, metadata, order lines, addresses, and the card token; accountCsp() and billing.redirect_hosts still force a call on custom domains and embedded card fields.
  • Build vs. buy for back-office and finance ops. billing:money-back:reconcile, RefundFailed, ChargebackReversed, RefundResult::failureCode/failureMessage, and the delivery ledger remain off the roadmap. New: billing:doctor names every Stripe webhook event type an endpoint at a package address is not subscribed to and fails while one is missing — catching the class of silent breakage where, for example, a missing invoice.upcoming pushed usage billing a cycle late without a word. The package still stops at emitting events and recording outcomes.
  • Ops tuning without redeploys. Metering backoff, stall deadline, and closed-period grace (BILLING_METERING_*, grace may be 0, backoff/stall at least 1) and a payment account's Molli client timeouts, connect timeout, and retries — separate values for web requests and for queue workers/scheduler/Artisan — are now environment-set, with invalid or sub-second values falling back to shipped defaults. Decide whether operations tunes these in production or whether they are fixed in config review.
  • Roadmap sequencing around churn. Another minor release with a behaviour-changing default and six migrations. Budget an upgrade slot per release rather than assuming drop-in.

When to Consider This Package

Consider adoption when:

  • You run a multi-tenant Laravel application where tenants/shops each hold their own Mollie or Stripe account, and you need per-account webhooks (billing.webhook_path/{provider}/{account}), per-account verification secrets, and per-account replay.
  • You need a normalized payment event model across Mollie and Stripe (AccountPaymentChanged with pending/authorized/paid/partially-or-fully-refunded/failed-refund/chargeback/failed/canceled/expired, plus refunded and charged-back amounts, idempotency key, metadata).
  • You are selling subscriptions you bill yourself and want first-class choice over advance vs. arrears collection, pause/resume, mid-period swaps and seat changes with immediate squaring, expiring grants, prepaid units, and grace on hard-stop meters — without building a billing engine.
  • You sell into the EU/DE and would otherwise commission the SEPA mandate wording, consent record, erasure unlink, § 312k cancellation declaration, and withdrawal refund arithmetic.
  • You ship AI features on laravel/ai and want per-call cost attribution plus daily caps per provider and per owner before you turn them on for customers.
  • You want provider-specific complexity absorbed: Mollie's missing webhooks for canceled refunds and reversed chargebacks, Stripe's refund failure reasons, Mollie's lack of error codes, payment-method narrowing, and the Stripe endpoint event-type checklist.
  • You accept pre-1.0 risk. At v0.46.0 with a behaviour-changing billing default and several new migrations in one minor release, you need pinned versions, an upgrade budget each cycle, and tests around first-invoice timing, pause/resume access, proration arithmetic, mandate wording, and custom-domain redirects.

Look elsewhere when:

  • You have a single account, simple payments, and no subscription lifecycle. Laravel Cashier or a thin Mollie client is less surface area.
  • You need split payments / payouts inside one transaction. This is charge-into-an-account, not marketplace fund splitting.
  • In-person/terminal is core. Mollie cancel() throws SaleNotCancelable because an open terminal payment cannot be taken off remotely; the buyer must press cancel on the device, and the terminal stays busy until the payment expires.
  • You need rich Stripe payment-method metadata (amounts, countries, names, logos); Stripe's configuration does not expose it, Mollie does.
  • Your billing model is entirely delegated to Stripe and you have no package-billed subscriptions — much of collection_timing, proration, grants, and the pause semantics are driver-specific value you would not exercise.
  • You do not ship AI features or metered usage; the cost, spend-brake, grant, and grace machinery is inert surface until you do.
  • You do not sell into the EU/DE and don't want to carry mandate wordings and statutory cancellation code through review cycles.
  • You require LTS, semantic-versioning guarantees, or vendor support, or first-class providers beyond Mollie/Stripe rather than the extendAccountCsp() / extendAccountPaymentMethods() / ReportsMoneyBackOutcomes / CollectsDirectDebits seams.
  • You are not prepared to own the decision layer: dunning policy for advance invoices, customer remediation for failed refunds, chargeback-won workflows, pause access rules, and legal sign-off on mandate and cancellation copy.

How to Pitch It (Stakeholders)

For executives — one paragraph. This release turns the package from a payments layer into a billing policy layer. We can now choose to collect subscriptions in advance or in arrears, pause a subscription instead of losing the customer, settle upgrades, downgrades, and seat changes at the moment they happen with correct credit, hand out allowances that expire and prepaid units that don't, and let a blocking meter grant a small grace so work in flight finishes rather than failing at its last unit. EU selling becomes a product feature rather than a legal backlog item: SEPA mandates can be taken on our own form without a payment, with the exact wording, consent, and erasure trail stored, and the statutory § 312k BGB cancellation declaration plus withdrawal refunds of the period in progress are supported. If we ship AI features, per-call cost attribution and hard daily caps per provider and per owner are available before launch, so margin protection is configuration. Operations can tune metering backoff, stall, and grace and the Mollie client's timeouts and retries from the environment, and billing:doctor now fails the build when a Stripe endpoint is missing an event type we depend on — the class of silent failure that previously delayed usage billing by a cycle with no error anywhere. In short, it removes advance/arrears billing, pause, proration, mandate onboarding, usage allowances, AI spend control, and webhook drift detection from our roadmap.

For engineering — what to plan for. One breaking change and a batch of migrations. (1) billing.collection_timing defaults to in_advance, so a new subscription on a package-billed driver is charged at the next billing:run after the mandate exists or when the trial ends, rather than at period end. Existing subscriptions are grandfathered into arrears, and the timing is recorded per subscription by 2026_10_15_000163_add_collection_timing_to_billing_subscriptions_table — so the risk is confined to new signups, which is exactly what staging tests miss if they use seeded old data. Test first-invoice timing at signup and at trial end, dunning on a failed advance invoice, and the rule that a period-end downgrade is applied before the next period is charged. (2) Run and review six migrations: collection_timing, paused_at, mandate consents, direct debit notices, AI spend, and expiring grants/grace. (3) Publish or set the new environment variables — BILLING_METERING_BACKOFF_SECONDS, BILLING_METERING_STALL_HOURS, BILLING_METERING_CLOSED_PERIOD_GRACE_MINUTES (grace may be 0, backoff and stall need ≥ 1), and BILLING_MOLLIE_ACCOUNT_REQUEST_TIMEOUT / _CONNECT_TIMEOUT / _RETRIES plus the three BILLING_MOLLIE_ACCOUNT_BACKGROUND_* counterparts; invalid values silently keep shipped defaults, so assert the resolved values in a boot test. (4) Pause requires access gating in the app, implementation of PausesSubscriptions on any custom driver, and void semantics on Stripe; cancellation while paused ends immediately — verify that path. (5) The direct debit flow checks that text() matches exactly what the form displayed, validates IBAN before calling Mollie, and throws DirectDebitMandateRefused with a reason you bind to the offending field; wordings outside AT/DE/LI/LU require your own SepaMandateWording and legal review. (6) billing:doctor now returns failure for missing Stripe event types — add it to CI and fix endpoint subscriptions before deploying, or the deploy gate will (correctly) block you.

Risk framing. Pre-1.0 with recurring minor-version breakage is the main cost; pin versions and budget an upgrade slot per release. The advance-collection default is the change that can quietly alter revenue timing, and grandfathering means the blast radius is new subscriptions only — precisely the ones least represented in staging data. Provider-side gaps remain documented constraints: Stripe method listings lack amounts, countries, and logos, and Mollie's terminal cancel is device-bound. The new regulatory surface (mandate wording per country, § 312k declaration, withdrawal refunds) is not a code-review item; schedule counsel alongside the engineering ticket. Confirm all of this against the near-term roadmap before committing.

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.
shitoudev/permissionmanager
johannesclimacus/laravel-tui
hocvt/seotools
vitalybaev/sypexgeo
amphibee/themosis-ignition
gito-me/fast-excel
frankyso/laravel-ipaymu
geolize-studio/laravel-chile
boomerangui/chat
jinas/dhivatar
store-doc/laravel-storage-driver
plus-it/laravel-translation-manager
diephp/perhaps
diephp/telegraph
osmaviation/spreadsheet
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console