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 Laravel Package

moffhub/billing

Feature-based subscription billing for Laravel with African payment support: gate routes by feature, meter usage, manage subscriptions and invoices, and accept payments via M-Pesa, Airtel Money, Paystack, Flutterwave, and 10+ more through one unified API.

View on GitHub
Deep Wiki
Context7

Technical Evaluation

Architecture fit. The package follows conventional Laravel package anatomy — service provider, publishable config and migrations, an artisan seeder (billing:sync-plans --seed), and a trait-based Billable that attaches to any paying entity. That is the lowest-ceremony footprint available in this stack. The domain model (Plan → Feature → Subscription → Usage → Invoice → Payment) is correctly abstracted: gating on feature slugs rather than plan names means repackaging commercial tiers does not require code changes. Feature types (boolean | metered | consumable) cover entitlement, quota, and credit burn-down without workarounds. The PaymentProviderInterface (charge/refund/status/verifyWebhook) is a genuine seam, and PaymentManager::driver() mirrors Laravel's familiar Manager pattern — a team can extend or replace a provider without forking core billing logic. Events fire on every state change, which cleanly pushes notification fanout into the host app.

Integration feasibility. Four commands to install and migrate; gating is declarative via feature:, plan:, and usage: middleware plus @feature/@plan Blade directives, so retrofitting onto existing routes is mechanical rather than invasive. The 32 API endpoints are mounted under a configurable prefix/middleware/rate limit, so they can be scoped behind auth:sanctum rather than exposed by default. GET /payments/options driven by BILLING_ENABLED_PROVIDERS maps directly to a "choose how to pay" screen without per-provider UI plumbing.

Technical risk, ranked.

  1. Zero external validation on money-moving code. 0 stars, 0 dependents. No production evidence exists for the ledger, proration, or settlement paths. This is an "evaluate," not an "adopt," until certified.
  2. Provenance. Latest release is dated 2026-11-06. Verify signed tags, that the Packagist artifact matches the repo commit, and review the diff before any version reaches a payment path.
  3. Partial settlement. Splitting amounts above per-transaction caps (M-Pesa 250k) into linked tranches against one invoice creates multi-state settlements. Tranche 2-of-3 timeout behavior is undocumented.
  4. Idempotency. charge(int $amount, string $currency, array $options) exposes no documented idempotency key (usage recording has transactionId; payments do not advertise one). Blind retry is a double-charge vector.
  5. Webhook surface. 13 public callback routes. The trust model is well-designed — IP allowlist, signature verification, and unverified callbacks enqueued for status re-query instead of settling inline (confirm_unverified defaults on). But M-Pesa, T-Kash, Co-op, and Pesapal are unsigned by design, so settlement liveness is coupled to each provider's status API availability.
  6. Tax/currency assumptions. VAT 16% Kenya default; amounts are integer minor units (750000 = KES 7,500.00). Multi-jurisdiction and multi-currency behavior is unproven.

Key questions for the maintainer. Test coverage and CI matrix (Laravel/PHP versions)? Idempotency and retry contract on charge/refund? Proration algorithm on upgrade/downgrade — day-proration or credit-based? Invoice numbering: gapless and sequential under concurrency, and any tax-authority (e.g. eTIMS) export hooks? Behavior after confirm_backoff exhausts — dead-letter or silent drop? Semver and Laravel-major compatibility policy? Is PayOrchestra optional or load-bearing? Security disclosure channel and support commitment?

Integration Approach

Stack fit. Compatible with any Laravel app on a supported major; the only structural decision is which model carries the Billable trait (User, Team, or Company). Make that call once — changing it later is a data migration. Adopt the minor-unit convention (integer cents) in your own services and API contracts on day one; mixed units is the canonical billing defect.

Migration path. Greenfield is clean: seed plans and features as deploy-time data, gate routes incrementally. If you already have subscribers on Cashier/Stripe or a homegrown system, do not treat this as a migration tool — there is no importer. Run it in parallel behind a flag for new sign-ups only, or backfill plans/features manually with dual-written status until reconciled. If cards are a material channel today, this is additive to Cashier, not a replacement — which means two reconciliation sources of truth. Scope that cost explicitly.

Compatibility checks before commit. Table-name collisions on plans/subscriptions/invoices are the most likely blocker; confirm a prefix strategy. Confirm PHP and Laravel versions, database (MySQL vs Postgres), and a working queue driver — the webhook confirmation path is queue-dependent. Confirm your auth guard maps cleanly onto the documented Sanctum middleware.

Sequencing — the critical path is commercial, not technical.

  1. Week 0: start provider onboarding in parallel. Daraja, KCB BUNI, Equity Jenga, and Co-op sandbox credentials plus paybill/till provisioning carry multi-week lead times. Code is days; onboarding is weeks.
  2. Sandbox vertical slice: seed 3 plans, exercise subscribe → gate → meter → invoice → charge → webhook → refund end-to-end. No live money.
  3. Data model review: trait placement, table prefixing, currency and minor-unit conventions signed off.
  4. Shadow mode: gating and metering live in staging against real plan definitions.
  5. Canary: manual/bank-transfer driver only, one cohort. Human-settled and fully reversible — this is the kill switch.
  6. Progressive rollout: mobile money first (highest conversion), cards (Paystack/Flutterwave) second, bank rails last (longest onboarding).

Operational Impact

Maintenance. Fourteen drivers means fourteen integration surfaces that can silently drift when a provider changes an endpoint or signature scheme. Budget a standing 10–15% of one engineer for provider upkeep. Single-maintainer upstream implies fork risk: the PaymentProviderInterface seam makes a provider fork survivable; a fork of ledger or proration logic is not. Pin exact versions, review diffs, and disable automated dependency merges for this package. Keep your own invoice and subscription records of record if you need audit independence.

Support. No commercial support indicated. Establish an escalation path to the maintainer and an internal owner before go-live, or the package is unsupportable for revenue-critical paths. Customer-visible burden lands on you — "my M-Pesa payment didn't reflect" becomes your ticket queue. The async confirmation path improves correctness at the cost of settlement latency; write UI copy and support macros accordingly.

Scaling. Package code is thin; the constraints are provider rate limits, per-day caps, and your queue. Annual and enterprise invoices will fan out into multiple tranches against the 250k cap — more rows, more callbacks, more reconciliation. Size that before selling high-ticket plans. Usage metering writes on every metered action, so the usage table is a hot path: validate write amplification and indexing before high-volume features (API calls, OCR) go live. Webhook routes are public by design — put them behind edge rate limiting and off latency-sensitive pools.

Failure modes to design for.

  • Silent provider drift: status endpoint changes, re-query fails, payments sit pending. Alert on pending payments older than N minutes.
  • Tranche partial failure: some but not all tranches settle. Run an invoice-keyed reconciliation job with a manual-resolution queue.
  • Forged or replayed callback: mitigated by default. Never set confirm_unverified to false.
  • Double charge on retry: unproven idempotency. Enforce your own idempotency keys at the edge and a no-blind-retry rule on charge().
  • Queue outage: confirmation jobs stall and settlement freezes. Alert on queue depth and job age.
  • Deploy-time entitlement mutation: billing:sync-plans --seed can change live plans. Gate the command; never run it unattended in production.

Ramp-up. One to two engineer-days to a sandbox slice; two to three weeks to production-grade (hardening, observability, reconciliation, runbooks); provider onboarding dominates the calendar. Learning curve is low for Laravel-fluent engineers — the non-obvious domain skill is reconciliation and dispute handling, not the API.

Adoption gate. Promote from "evaluate" to "adopt" only after: sandbox certification across at least two providers with different auth schemes (one signed, one unsigned — e.g. Paystack plus M-Pesa), a written reconciliation runbook, alerting on stuck payments, and a documented upstream support arrangement. Absent those, cap usage at non-revenue-critical gating and metering.

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.
se7enxweb/flysystem
lampwick/laravel
jeslage/statamic-emojis
micahdshackelford/rmap-laravel
draftsmaninc/draftsman
square-bit/laravel-volition
himito/laravel-mailman
htinlynn/genius-helper
maco-studios/hephaestus
elmogy/larafast
xeviant/laravel-paystack
gorilladash/laravel-website-sdk
martialbe/flysystem-oss
chondal/3312client
jeroen-g/flickr
opscale-co/nova-genbi
itsjustvita/laravel-retention
tequilarapido/trackit
gregsphotography/site-builder-filament
cabaoctavio/laravel-query-log