Overview
Commerce's payment gateway system is built on a driver pattern. Every gateway — built-in or third-party — implements the same PaymentGatewayModule interface. Once registered, a gateway automatically appears in Admin → Settings → Payment Gateways with a generated settings form.
Interface Contract
interface PaymentGatewayModule
{
public function name(): string;
public function slug(): string;
public function settingsFields(): array;
public function isConfigured(): bool;
public function supportsRedirect(): bool;
public function prepareData(Invoice $invoice): array;
public function formView(): ?string;
public function redirectUrl(Invoice $invoice): ?string;
public function charge(Invoice $invoice, array $payload): GatewayResult;
public function handleWebhook(Request $request): GatewayResult;
public function supportsRefund(): bool;
public function refund(Payment $payment, int $amountCents): GatewayResult;
}
Method Reference
| Method | Returns | Purpose |
|---|---|---|
name() |
string |
Human-readable name shown in the admin UI and client portal |
slug() |
string |
URL-safe identifier (e.g. mypay). Used in webhook route: /webhooks/mypay |
settingsFields() |
array |
Declares settings form fields (see below) |
isConfigured() |
bool |
Returns true only if all required credentials are present |
supportsRedirect() |
bool |
true for redirect gateways, false for inline |
prepareData() |
array |
Data passed to the form view or used to build a redirect URL |
formView() |
?string |
Blade view path for inline gateways, null for redirect gateways |
redirectUrl() |
?string |
Return the redirect URL for redirect gateways, null for inline |
charge() |
GatewayResult |
Process the payment for inline gateways |
handleWebhook() |
GatewayResult |
Handle incoming webhook POST and return payment result |
supportsRefund() |
bool |
true if the gateway can process refunds programmatically |
refund() |
GatewayResult |
Process a refund for a given payment |
Declaring Settings Fields
settingsFields() returns an array of field definitions. Commerce generates the settings form automatically — no Blade view required.
public function settingsFields(): array
{
return [
['key' => 'api_key', 'label' => 'API Key', 'type' => 'text', 'required' => true],
['key' => 'secret', 'label' => 'Secret', 'type' => 'password', 'required' => true],
['key' => 'sandbox', 'label' => 'Sandbox', 'type' => 'toggle', 'required' => false],
];
}
Supported field types: text, password, toggle, select (include options array for select).
Settings are stored as gateway_{slug}_{key} in the settings table. Read them with:
GatewayRegistry::config('mypay', 'api_key');
Inline Gateway Example
For an inline gateway, provide a Blade form view:
resources/views/gateways/mypay/form.blade.php
Return the view path from formView():
public function formView(): ?string
{
return 'gateways.mypay.form';
}
public function supportsRedirect(): bool
{
return false;
}
The form view receives $invoice and $preparedData (returned by prepareData()). On form submit, Commerce calls charge() with the $payload from the POST request.
Redirect Gateway Example
For a redirect gateway, implement redirectUrl() and set supportsRedirect() to true:
public function supportsRedirect(): bool
{
return true;
}
public function redirectUrl(Invoice $invoice): ?string
{
return 'https://pay.mypay.example/checkout?' . http_build_query([
'merchant_id' => GatewayRegistry::config('mypay', 'merchant_id'),
'amount' => $invoice->total_cents,
'reference' => $invoice->number,
'return_url' => route('commerce.invoice.return', $invoice),
'webhook_url' => route('webhooks.gateway', 'mypay'),
]);
}
Returning Results
All methods that process payments return a GatewayResult:
// Payment succeeded
return GatewayResult::success(transactionId: 'txn_abc123');
// Redirect the client to an external URL
return GatewayResult::redirect(url: 'https://pay.mypay.example/...');
// Payment failed
return GatewayResult::failure(message: 'Card declined by issuer');
Registering the Gateway
Register the gateway class in a service provider:
use App\Gateways\MyPayGateway;
use Commerce\GatewayRegistry;
public function boot(): void
{
GatewayRegistry::register(new MyPayGateway());
}
Or declare it in config/commerce.php:
'gateways' => [
App\Gateways\MyPayGateway::class,
],
Once registered, the gateway appears in Admin → Settings → Payment Gateways and the webhook route POST /webhooks/mypay is available automatically.
[!TIP] Test your gateway in isolation using
php artisan tinkerto callhandleWebhook()with a mocked request before wiring up real webhook events.