asciisd/cashier-core
Core billing toolkit for Laravel: subscription management, invoicing, and payment gateway abstractions. It packages reusable Cashier foundations so you can add recurring payments to any Laravel app with minimal boilerplate and consistent APIs.
Payment rail expansion / market coverage. A seventh bundled driver (Xoala, a white-label of Paymentz) means new corridor or acquirer coverage without a bespoke integration project. For roadmap decisions, each driver added is a "buy" against weeks of in-house PSP work — the question shifts from "can we support this acquirer?" to "is this acquirer worth a config block?"
Build vs. buy on the abstraction layer. The package's real product is the uniform contract (charge, webhook, refund, capture, authorize, void via supports()), not any single driver. Adoption is a bet that maintaining one contract + N driver quirks is cheaper than N native integrations in your app code. 2.5.0 is a data point for that bet: a driver whose semantics don't fit the contract (browser form POST, no refund) was absorbed as an asymmetric driver rather than a contract change — no breaking changes for existing connections.
Capability matrix as a product constraint. supports() reporting only charge + webhook for Xoala is now a first-class product fact: refund, capture, authorize and void throw. Anything you build that assumes symmetric gateway capability (one-click refunds in admin, partial captures, auth-then-capture flows) must either be gated per-connection or handled out-of-band for Xoala. This is a decision about support operations and finance workflows, not just code — refund-by-email/manual bank transfer is a downstream cost.
Headless vs. hosted checkout architecture. The Xoala bridge is the package's first non-webhook route, first Blade view, and first view-publishing tag. That is a genuine architectural fork:
web middleware so no session/CSRF) for free; you optionally publish cashier-core-views to brand it.cashier-core.routes.enabled / Cashier::ignoreRoutes() gates both webhook and checkout routes together — disabling routes to own your webhook endpoints also removes the interstitial, so you must implement the form-POST bridge yourself.That coupling is the main decision this release forces on existing adopters who run route-less.
Security and compliance scope creep. The package now serves a public, unauthenticated-by-design HTML endpoint whose URL is a bearer credential for a payment redirect. PM-owned consequences: security review of the signed-URL scheme (expiry window, replay, referrer leakage of the link, throttle adequacy), a CSP/asset decision for the Blade view, and a documented stance on publishing vs. shipping default views.
Onboarding friction as roadmap input. totype is account-specific, sits inside the request checksum, is required (the provider refuses to resolve without it), and a wrong value "fails opaquely at the hosted page." That is a support-ticket generator. Reasonable roadmap asks: a preflight/doctor command or config validation, and a legible error surfaced at the interstitial rather than at the acquirer.
Maintenance risk assessment. The gateway contract is vendored under .claude/skills/xoala/ precisely because the vendor's doc site renders samples in JavaScript and blanks its brand — the contract isn't recoverable from the URL. Translation: driver upkeep depends on captured, in-repo knowledge, and vendor API drift may be undocumented. Worth tracking as an ongoing cost of each driver you actually enable.
Low-risk upgrade. No breaking changes; existing connections and routes untouched; the new route group registers only when routes are enabled. Upgrade is a maintenance-window line item, not a project. The dev-2.x alias fix (2.3.x-dev → 2.5.x-dev) matters only to contributors and CI.
Adopt when:
Look elsewhere when:
totype checksum makes misconfiguration silent until a customer hits the payment page.To executives: This release adds a seventh payment provider at configuration cost rather than integration-project cost, extending the rails we can accept deposits on without adding code to our application. No breaking changes — existing payment flows are untouched, and the new surface only switches on when routes are enabled. The strategic value is optionality: adding or swapping an acquirer is a config change plus a driver, not a quarter of engineering. The caveat to state plainly: this provider is deposits-only in our stack — refunds on it are a manual, finance-side process, not a button.
To engineering: Uniform gateway contract with capability discovery via supports(); Xoala is a clean example of an asymmetric driver absorbed without a contract change. The interesting new pattern is a package-served, signed, expiring interstitial for providers that require a browser form POST rather than a redirect URL — no web middleware (no session, no CSRF), signed + throttle:cashier-checkout at 30/min/IP, checksum recomputed from the transaction row at render and never persisted. Views are publishable via cashier-core-views for branding. Both new routes sit under the existing routes.enabled / Cashier::ignoreRoutes() guard, so route-less deployments must supply their own bridge or skip this gateway. Config is base_url, member_id, secure_key, and a required account-specific totype that participates in the checksum — provider resolution fails without it, and a wrong value fails opaquely at the hosted page.
To security and support: Two asks. Security: review the signed-URL scheme as a bearer credential — expiry, replay, referrer leakage, throttle headroom — and sign off on the interstitial's asset/CSP posture. Support: add a runbook entry for Xoala onboarding (totype verification against the sandbox, symptom = failure at the hosted page with no useful error) and a documented refund path outside the system for this connection.
How can I help you explore Laravel packages today?