Everyone

Building a Gateway Module

How to implement the PaymentGatewayModule interface and register a custom payment gateway in Opterius Commerce.

Last updated 1776211200

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 tinker to call handleWebhook() with a mocked request before wiring up real webhook events.

Related Topics