musahmusah/laravel-multipayment-gateways
Installation
composer require musahmusah/laravel-multipayment-gateways
php artisan vendor:publish --provider="MusahMusah\MultiPaymentGateways\MultiPaymentGatewaysServiceProvider" --tag="config"
Publish the config file to customize gateway settings.
Configuration
Update config/multipayment-gateways.php with your API keys and preferred gateways (e.g., PayPal, Stripe, Flutterwave). Example:
'gateways' => [
'paypal' => [
'enabled' => true,
'client_id' => env('PAYPAL_CLIENT_ID'),
'secret' => env('PAYPAL_SECRET'),
],
'stripe' => [
'enabled' => true,
'secret_key' => env('STRIPE_SECRET_KEY'),
],
],
First Use Case: Create a Payment
Use the Payment facade to initiate a payment:
use MusahMusah\MultiPaymentGateways\Facades\Payment;
$payment = Payment::create([
'gateway' => 'paypal', // or 'stripe', etc.
'amount' => 100.00,
'currency' => 'USD',
'description' => 'Order #12345',
'metadata' => ['order_id' => 12345],
]);
This returns a Payment model with a gateway_response attribute containing the gateway-specific response (e.g., PayPal approval URL).
config/multipayment-gateways.php defines enabled gateways, API keys, and default settings.Payment facade is the primary entry point for all operations (create, verify, refund, etc.).webhook route handler (see routes/web.php after publishing).Payment facade to create a payment and redirect users to the gateway:
$payment = Payment::create(['gateway' => 'paypal', 'amount' => 100.00, ...]);
return redirect()->away($payment->gateway_response->redirect_url);
payment_id in the session or database for later verification./payment/webhook). Handle gateway-specific events in a service:
use MusahMusah\MultiPaymentGateways\Events\PaymentSucceeded;
PaymentSucceeded::subscribe(function ($event) {
// Update order status, send notifications, etc.
Order::find($event->payment->metadata['order_id'])
->update(['status' => 'paid']);
});
PaymentWebhookHandler class or override the handleWebhook method.$payment = Payment::find($request->payment_id);
$verified = $payment->verify($request->all());
verify() to check the gateway's response (e.g., PayPal's PayerID or Stripe's payment_intent).Payment model:
$payment->refund(['amount' => 50.00, 'reason' => 'Customer dispute']);
payments table migration. Customize it if needed (e.g., add user_id or invoice_number):
Schema::table('payments', function (Blueprint $table) {
$table->foreignId('user_id')->constrained()->nullable();
});
PaymentGatewayMock trait to simulate responses in tests:
use MusahMusah\MultiPaymentGateways\Testing\PaymentGatewayMock;
public function test_payment_creation()
{
$this->mockPaymentGateway('paypal', 'success');
$payment = Payment::create([...]);
$this->assertEquals('success', $payment->status);
}
$gateway = request()->input('gateway') ?? config('multipayment-gateways.default_gateway');
$payment = Payment::create(['gateway' => $gateway, ...]);
config/multipayment-gateways.php:
'debug' => env('APP_ENV') === 'local',
failed_jobs table or a third-party service.$valid = $payment->verifyWebhook($request->all());
if (!$valid) {
abort(403, 'Invalid webhook signature');
}
$payment->update(['idempotency_key' => $request->idempotency_key]);
payments table and check it before processing.cancel_url and return_url in the initial request. Add them to the Payment facade config:
'paypal' => [
'return_url' => route('paypal.callback'),
'cancel_url' => route('paypal.cancel'),
],
verify() method is called with the correct payload:
$payment->verify(['tx_ref' => $request->tx_ref, 'flw_ref' => $request->flw_ref]);
Route::middleware(['throttle:10,1'])->group(function () {
Route::post('/create-payment', [PaymentController::class, 'create']);
});
100.00 → 10000 for cents) and currencies are ISO codes (e.g., USD). The package handles conversion internally, but validate inputs:
$amount = (int) ($request->amount * 100);
'debug' => true in the config to log raw gateway responses and errors to storage/logs/laravel.log.gateway_response attribute on the Payment model for raw responses:
$payment = Payment::find(1);
\Log::info('Gateway Response:', [$payment->gateway_response]);
ngrok http 8000
https://your-ngrok-url.ngrok.io/payment/webhook.GatewayNotFound: Ensure the gateway is enabled in the config and the name matches exactly (case-sensitive).InvalidSignature: Verify your webhook secret matches the gateway's configuration.AmountMismatch: Double-check currency and amount formatting (e.g., 100.00 vs. 10000 for cents).Gateway class to add support for unsupported gateways:
namespace App\Gateways;
use MusahMusah\MultiPaymentGateways\Contracts\Gateway;
class CustomGateway implements Gateway {
public function create(array $data): array {
// Custom logic for your gateway
return ['redirect_url
How can I help you explore Laravel packages today?