Download the PHP package damms005/laravel-cashier without Composer
On this page you can find all versions of the php package damms005/laravel-cashier. It is possible to download/install these versions without Composer. Possible dependencies are resolved automatically.
Download damms005/laravel-cashier
More information about damms005/laravel-cashier
Files in damms005/laravel-cashier
Package laravel-cashier
Short Description An opinionated, easily extendable and configurable package for handling payments in Laravel
License MIT
Homepage https://github.com/damms005/laravel-multipay
Informations about the package laravel-cashier
Laravel Multipay 💸

An opinionated Laravel package to handle payments, complete with blade views, routing, and everything in-between.
Whether you want to quickly bootstrap payment processing for your Laravel applications, or you want a way to test supported payment processors, this package's got you!
Although opinionated, this package allows you to "theme" the views. It achieves this theming by
@extend()ing whatever view you specify inconfig('laravel-multipay.extended_layout')(defaults tolayout.app).
Requirements:
This package is tested against:
- PHP ^8.2
- Laravel 11/12
Currently supported payment handlers
Currently, this package supports the following online payment processors/handlers
[!NOTE] key: ** for the indicated providers, a few features may be missing. PRs welcomed if you cannot afford the wait 😉
[!TIP] Your preferred payment handler is not yet supported? Please consider opening the appropriate issue type.
[!TIP] Adding a new payment handler is straight-forward. Simply add a class that extends
Damms005\LaravelMultipay\Services\PaymentHandlers\BasePaymentHandlerand implementDamms005\LaravelMultipay\Contracts\PaymentHandlerInterface[!NOTE] Payment providers that you so register as described above are resolvable from the Laravel Container to improve the flexibility of this package and improve DX.
Installation
Publish the config file.
Run migrations.
Demo Repo
I published an open source app that uses this payment package. It is also an excellent example of a Laravel app that uses Laravel Vite and leverages on Laravel Echo to provide realtime experience via public and private channels using Laravel Websocket, powered by Livewire.
Test drive 🚀
Want to take things for a spin? Visit /payment/test-drive (route('payment.test-drive') provided by this package) .
For Paystack, ensure to set paystack_secret_key key in the laravel-multipay.php config file that you published previously at installation. You can get your key from your settings page.
Warning
Ensure you have TailwindCSS installed, then add this package's views to thecontentkey of yourtailwind.config.jsconfiguration file, like below:
Needed Third-party Integrations:
-
Flutterwave: If you want to use Flutterwave, ensure to get your API details from the dashboard, and use it to set the following variables in your
.envfile: - Paystack: Paystack requires a secret key. Go to the Paystack dashboard to obtain one, and use it to set the following variable:
The
PAYSTACK_TERMINAL_IDis only required if you intend to use Paystack Terminal for payment processing.
- Remita: Ensure to set the following environment variables:
For most of the above environment variables, you should rather use the (published) config file to set the corresponding values.
Usage
Typical process-flow
Step 1
Send a POST request to /payment/details/confirm (route('payment.show_transaction_details_for_user_confirmation') provided by this package).
Check the test-drive/pay.blade.php).
This POST request will typically be made by submitting a form from your frontend to the route described above.
[!NOTE] if you need to store additional/contextual data with this payment, you can include such data in the request, in a field named
metadata. The value must be a valid JSON string.
Step 2
Upon user confirmation of transaction, user is redirected to the appropriate payment handler's gateway.
Step 3
When user is done with the transaction on the payment handler's end (either successfully paid, or declined transaction), user is redirected
back to /payment/completed (route('payment.finished.callback_url') provided by this package) .
Metadata Usage
In the payment initiation request in Step 1, you can provide a metadata field. This field is stored in the metadata column of the payments table, and available as AsArrayObject::class property of the Payment model and it provides powerful customization options for individual payments.
The metadata should be a valid JSON string containing key-value pairs that modify payment behavior.
Available Metadata Keys
completion_url
- After successful payment, the user will be redirected to the URL specified by this key instead of the default payment completion page
- When user is redirected to the specified URL, the transaction reference will be included as
transaction_referencein the URL query string
payment_processor
- Use this key to dynamically set the payment handler for the specific transaction
- Valid values are any of the providers listed above
- This will override the default payment processor configuration
split_code (Paystack only)
- When using Paystack, you can use this key to specify a split code to process the transaction as a Paystack Multi-split Transaction
- This feature is only available when using Paystack as the payment handler
additional_payment_payload (Paystack only)
- When using Paystack, you can use this key to specify additional parameters for transaction initialization. For example, you can set
channelsto restrict payment methods:{ "channels": ["card", "bank", "ussd", "qr", "mobile_money"] } - See Paystack transaction initialization documentation for all available parameters
- This feature is only available when using Paystack as the payment handler
Subscriptions (Recurring Payments)
This package provides built-in support for subscription-based recurring payments via the SubscriptionService class.
Supported Handlers
| Handler | Create plan | Subscribe | Pause / Cancel / Resume |
|---|---|---|---|
| Paystack | ✅ | ✅ | ✅ |
| Flutterwave | ✅ | ✅ | — |
Pause/cancel/resume requires the handler to implement the ManagesSubscriptions contract. Only Paystack does today; calling the management methods with an unsupported handler throws a SubscriptionManagementException.
Creating a Payment Plan
Before subscribing users, create a payment plan:
This registers the plan with the payment provider and stores it locally in the payment_plans table.
If a plan with the same amount, interval, and currency already exists for the handler, use findOrCreatePaymentPlan to avoid duplicates:
Subscribing a User to a Plan
This redirects the user to the payment gateway. Upon successful payment, a Subscription record is created automatically with the appropriate next_payment_due_date.
You can optionally provide a custom transaction reference and additional metadata:
Checking Active Subscriptions
A subscription is considered active if its status is active and its next_payment_due_date is in the future. Paused and cancelled subscriptions are excluded.
Managing Subscriptions (Pause, Cancel, Resume)
Subscriptions can be paused (temporarily suspended, intended to be resumed later), cancelled (permanently stopped), or resumed. Under the hood, both pause and cancel call the provider's "disable" endpoint so the subscription stops renewing; the difference between them is intent, tracked locally via the status column. Resume calls the provider's "enable" endpoint.
Provider note (Paystack): Paystack has no native "pause". Disabling a subscription stops it from renewing on its next payment date (you'll receive a
subscription.not_renewevent immediately, thensubscription.disableon the would-be charge date). You cannot shift the next payment date by an arbitrary number of days — a pause effectively skips the upcoming renewal. Re-enabling before the next payment date keeps billing uninterrupted; re-enabling after the period lapses starts a fresh cycle.
Capturing the provider's subscription code and token
To manage a subscription you need the provider's subscription code and email token. For Paystack these are delivered on the subscription.create webhook (data.subscription_code and data.email_token) shortly after the first successful charge on a plan. Persist them onto the local Subscription with recordProviderSubscriptionData():
If you did not capture them at creation time, you can retrieve them from the provider (Paystack) via the handler:
Pause, cancel, resume
Each method calls the provider, updates the local status, and returns the refreshed Subscription. They throw SubscriptionManagementException when:
- the handler does not implement
ManagesSubscriptions, - the subscription is missing its provider subscription code or email token, or
- you attempt to resume a subscription that is not paused.
Provider-side failures (e.g. an invalid subscription code) bubble up as an Exception carrying the provider's message.
Models
PaymentPlan — represents a recurring billing plan:
| Column | Description |
|---|---|
name |
Unique plan name |
amount |
Billing amount |
interval |
monthly or yearly |
description |
Human-readable description |
currency |
Currency code (e.g., NGN) |
payment_handler_fqcn |
Payment handler class name |
payment_handler_plan_id |
Plan ID from the payment provider |
Subscription — represents a user's subscription to a plan:
| Column | Description |
|---|---|
user_id |
The subscribed user |
payment_plan_id |
FK to payment_plans |
next_payment_due_date |
When the next payment is due |
metadata |
Optional JSON metadata |
payment_handler_subscription_code |
Provider's subscription code (required to manage it) |
payment_handler_email_token |
Provider's email token (required to manage it) |
status |
active, paused, or cancelled |
On successful payment, SuccessfulLaravelMultipayPaymentEvent is fired — listen for this to run any domain-specific logic.
Payment Conflict Resolution (PCR)
If for any reason, your user/customer claims that the payment they made was successful but that your platform did not reflect such successful payment, this PCR feature enables you to resolve such claims by simply calling:
The payment will be re-resolved and the payment will be updated in the database. If the payment is successful, the SuccessfulLaravelMultipayPaymentEvent event will be fired, so you can run any domain/application-specific procedures.
WebHooks Payment Notifications (optional)
One of the benefits of this package is to remove the need for you to have to deal with payment webhooks. Depending on your needs, the event handling may suffice for your use case.
If you need webhook notifications from payment providers, use the webhook endpoint provided by this package: route('payment.external-webhook-endpoint').
If you use this payment notification URL feature, ensure that in the handler for
SuccessfulLaravelMultipayPaymentEvent, you have not previously handled the event for that same payment.
Events
SuccessfulLaravelMultipayPaymentEvent
If there are additional steps you want to take upon successful payment, listen for SuccessfulLaravelMultipayPaymentEvent. This event will be fired whenever a successful payment occurs, with its corresponding Payment model.
Paystack Terminal
Paystack Terminal allows you to process payments on physical payment terminals. This feature is useful for point-of-sale (POS) systems and retail environments.
Prerequisites
- Ensure you have
PAYSTACK_SECRET_KEYconfigured in your.envfile - Obtain your Terminal ID from Paystack Dashboard
- Set the
PAYSTACK_TERMINAL_IDin your.envfile:
Alternatively, you can set the Terminal ID dynamically in your session:
Usage
The Paystack Terminal functionality is provided via the Terminal class:
Creating a Payment Request
Create a payment request that can be pushed to a terminal:
This creates a payment record and returns a Payment model instance with the payment details stored in metadata.
Checking Terminal Status
Verify that the terminal hardware is online and ready before pushing payments:
Pushing Payment to Terminal
Send a payment request to the terminal for processing:
The returned $eventId can be used to track the payment request delivery status.
Verifying Terminal Receipt
Confirm that the terminal received the payment request (within 48 hours of creation):
Error Handling
The Terminal class throws \Exception on failures. Common scenarios include:
- Terminal ID not configured
- Terminal hardware offline
- Invalid payment request data
- Network errors communicating with Paystack API
Always wrap Terminal method calls in try-catch blocks for proper error handling.
Webhook Push Notifications
When a payment succeeds, this package can automatically send a webhook to an external system (e.g. a financial tracking service). This uses spatie/laravel-webhook-server under the hood.
Setup
-
Install the webhook server package:
-
Set the webhook URL and signing secret in your
.env: -
Create a class that implements
Damms005\LaravelMultipay\Contracts\WebhookPayloadPackager: - Register your packager in a service provider:
Once configured, every SuccessfulLaravelMultipayPaymentEvent will trigger a signed webhook POST to the configured URL with the payload returned by your packager.
Backfilling Existing Payments
To send existing successful payments to the webhook endpoint:
Options:
--from=YYYY-MM-DD— only payments created on or after this date--to=YYYY-MM-DD— only payments created on or before this date--chunk=100— number of payments per batch (default: 100)
The command fail-fast aborts after 3 consecutive batch failures.
Testing
Credits
This package is made possible by the nice works done by the following awesome projects:
License
The MIT License (MIT). Please see License File for more information.
All versions of laravel-cashier with dependencies
damms005/laravel-flutterwave Version ^3.0
flutterwavedev/flutterwave-v3 Version ^1.0
guzzlehttp/guzzle Version ^7.3
illuminate/support Version ^7.0|^8.0|^9.0|^10.0|^11.0|^12.0
yabacon/paystack-php Version ^2.2