A comprehensive Filament 4 plugin to manage Shetabit Payment gateways with a beautiful admin interface.

composer require amidesfahani/filament-payment-manager
php artisan vendor:publish --tag="filament-payment-manager-config"php artisan vendor:publish --tag="filament-payment-manager-migrations"php artisan vendor:publish --tag="filament-payment-manager-views"
php artisan migrate
Add the plugin to your Filament panel in app/Providers/Filament/AdminPanelProvider.php:
use YourVendor\FilamentPaymentManager\FilamentPaymentManagerPlugin; public function panel(Panel $panel): Panel{ return $panel // ... ->plugins([ FilamentPaymentManagerPlugin::make(), ]);}
Add these to your .env file:
PAYMENT_CALLBACK_URL=https://yourdomain.com/payment/callbackPAYMENT_DEFAULT_CURRENCY=TPAYMENT_AUTO_LOAD_GATEWAYS=truePAYMENT_ENABLE_LOGGING=false
The config file config/filament-payment-manager.php allows you to customize:
use YourVendor\FilamentPaymentManager\Services\PaymentManagerService;use Shetabit\Multipay\Invoice; // Get the service$paymentManager = app(PaymentManagerService::class); // Create an invoice$invoice = new Invoice();$invoice->amount(10000); // Amount in Toman or Rial // Create payment (uses default gateway)$payment = $paymentManager->createPayment($invoice->getAmount()); // Or specify a gateway$payment = $paymentManager->createPayment($invoice->getAmount(), 'zarinpal'); // Purchase and get transaction IDtry { $transactionId = $payment->purchase($invoice, function($driver, $transactionId) { // Store transaction ID in your database })->pay()->render(); } catch (\Exception $e) { // Handle error}
use YourVendor\FilamentPaymentManager\Services\PaymentManagerService;use Shetabit\Payment\Facade\Payment; public function callback(Request $request){ $paymentManager = app(PaymentManagerService::class); try { $receipt = $paymentManager->verifyPayment(); // Payment successful $referenceId = $receipt->getReferenceId(); // Update your order status return redirect()->route('payment.success'); } catch (\Exception $e) { // Payment failed return redirect()->route('payment.failed'); }}
$paymentManager = app(PaymentManagerService::class); // Get all active gateways$gateways = $paymentManager->getActiveGateways(); // Get default gateway$defaultGateway = $paymentManager->getDefaultGateway(); // Get specific gateway by driver$gateway = $paymentManager->getGatewayByDriver('zarinpal');
You have three options for redirect forms:
Beautiful, modern redirect form with countdown timer and animations.
Create your own Blade view:
{{-- resources/views/payments/custom-redirect.blade.php --}}<!DOCTYPE html><html><head> <title>Payment Redirect</title></head><body> <h1>Redirecting to payment...</h1> <form method="{{ $method }}" action="{{ $action }}" id="payment-form"> @foreach($inputs as $name => $value) <input type="hidden" name="{{ $name }}" value="{{ $value }}"> @endforeach <button type="submit">Continue</button> </form> <script> document.getElementById('payment-form').submit(); </script></body></html>
Then set in gateway: payments.custom-redirect
Use placeholders in your HTML:
<form method="{method}" action="{action}"> {inputs} <button>Pay Now</button></form><script>document.forms[0].submit();</script>
[ 'merchantId' => 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx', 'callbackUrl' => 'https://yourdomain.com/payment/callback', 'description' => 'Payment for Order #123', 'currency' => 'T', // T=Toman, R=Rial 'mode' => 'normal', // normal, sandbox, zaringate]
[ 'merchantId' => 'your-merchant-id', 'password' => 'your-password', 'callbackUrl' => 'https://yourdomain.com/payment/callback', 'currency' => 'T',]
[ 'clientId' => 'your-client-id', 'clientSecret' => 'your-client-secret', 'callbackUrl' => 'https://yourdomain.com/payment/callback', 'currency' => 'USD', 'mode' => 'normal', // normal or sandbox]
[ 'secret' => 'sk_test_xxxxxxxxxxxxx', 'currency' => 'usd', 'success_url' => 'https://yourdomain.com/payment/success', 'cancel_url' => 'https://yourdomain.com/payment/cancel',]
If you disable auto-loading in config:
use YourVendor\FilamentPaymentManager\Services\PaymentManagerService;use YourVendor\FilamentPaymentManager\Models\PaymentGateway; $paymentManager = app(PaymentManagerService::class); // Load specific gateway$gateway = PaymentGateway::where('driver', 'zarinpal')->first();$paymentManager->registerGateway($gateway);
use YourVendor\FilamentPaymentManager\Models\PaymentGateway;use YourVendor\FilamentPaymentManager\Services\PaymentManagerService; $gateway = PaymentGateway::find(1);$paymentManager = app(PaymentManagerService::class); $html = $paymentManager->getRedirectForm( $gateway, 'https://payment.gateway.com/pay', 'POST', ['token' => 'abc123', 'amount' => 10000]); return response($html);
| Method | Description |
|---|---|
createPayment($amount, $driver = null) |
Create a new payment |
verifyPayment($driver = null) |
Verify a payment callback |
getActiveGateways() |
Get all active gateways |
getDefaultGateway() |
Get the default gateway |
getGatewayByDriver($driver) |
Get gateway by driver name |
registerGateway(PaymentGateway $gateway) |
Manually register a gateway |
getRedirectForm($gateway, $action, $method, $inputs) |
Get custom redirect form HTML |
| Property | Type | Description |
|---|---|---|
name |
string | Gateway display name |
driver |
string | Payment driver name |
is_active |
boolean | Active status |
is_default |
boolean | Default gateway flag |
config |
array | Gateway configuration |
callback_url |
string | Custom callback URL |
redirect_form_view |
string | Custom Blade view path |
redirect_form_html |
string | Custom HTML template |
sort_order |
integer | Display order |
description |
string | Internal notes |
The package includes a local test gateway:
// In Filament, create a gateway with driver 'local'// This allows you to test payment flow without real credentials
Many gateways support sandbox mode:
// Zarinpal'mode' => 'sandbox' // PayPal'mode' => 'sandbox'
Make sure your callback URL:
Iranian gateways typically require amounts in Rial, but you can use Toman by setting currency => 'T' in config. The package handles conversion automatically.
Contributions are welcome! Please submit pull requests or issues on GitHub.
This package is open-source software licensed under the MIT license.
For issues and questions:
Amid is a full-stack web developer (with a focus on Laravel) who has been coding for close to 20 years. You can learn more about Amid on his website.