Home / Module Development / Creating Payment Gateway Modules

Creating Payment Gateway Modules

Step-by-step guide to creating a custom payment gateway

Creating a Payment Gateway Module

Step 1: Create Module Directory

Create a directory for your gateway module:

/modules/gateways/yourgateway/

Important: The folder name should be lowercase with no spaces, and will be used as the module identifier.

Step 2: Create module.json

Create a module.json file with module metadata:

{
    "name": "yourgateway",
    "display_name": "Your Gateway",
    "description": "Payment gateway integration",
    "version": "1.0.0",
    "author": "Your Name",
    "website": "https://example.com"
}

Required fields:

  • name: Unique identifier (lowercase, no spaces) - must match folder name
  • display_name: Human-readable name shown to users
  • description: Brief description of the gateway
  • version: Module version (semantic versioning recommended)
  • author: Your name or organization

Step 3: Create Gateway Class

Create YourgatewayGateway.php implementing ModuleInterface:

<?php
require_once ROOT_PATH . '/core/ModuleInterface.php';

class YourgatewayGateway implements ModuleInterface {
    private $config = [];
    private $enabled = false;

    public function getName(): string {
        return 'yourgateway';
    }

    public function getType(): string {
        return 'gateway';
    }

    public function getConfigFields(): array {
        return [
            [
                'name' => 'api_key',
                'label' => 'API Key',
                'type' => 'text',
                'required' => true
            ],
            [
                'name' => 'api_secret',
                'label' => 'API Secret',
                'type' => 'text',
                'required' => true
            ],
            [
                'name' => 'environment',
                'label' => 'Environment',
                'type' => 'select',
                'options' => ['sandbox' => 'Sandbox', 'production' => 'Production'],
                'required' => true
            ]
        ];
    }

    public function initialize(array $config): bool {
        $this->config = $config;
        $this->enabled = !empty($config['api_key']) && !empty($config['api_secret']);
        return $this->enabled;
    }

    public function execute($action, $params = []) {
        switch ($action) {
            case 'process':
                return $this->processPayment($params);
            case 'webhook':
                return $this->handleWebhook($params);
            default:
                return ['success' => false, 'error' => 'Unknown action'];
        }
    }

    public function isEnabled(): bool {
        return $this->enabled;
    }

    public function getDisplayName(): ?string {
        return $this->config['display_name'] ?? 'Your Gateway';
    }

    // Optional but recommended: Get configuration
    public function getConfig(): array {
        return $this->config;
    }

    private function processPayment($params) {
        $invoice = $params['invoice'] ?? null;
        $amount = $params['amount'] ?? 0;
        
        if (!$invoice || !$amount) {
            return ['success' => false, 'error' => 'Invalid parameters'];
        }
        
        // Implement payment processing logic
        // Return standardized response based on your gateway type:
        
        // For hosted checkout (redirects user):
        return [
            'success' => true,
            'redirect_url' => 'https://gateway.com/checkout?session=xxx'
        ];
        
        // OR for embedded forms (like Stripe Payment Intents):
        // return [
        //     'success' => true,
        //     'client_secret' => 'pi_xxx_secret_xxx'
        // ];
        
        // OR for on-site buttons (like PayPal Smart Buttons):
        // return [
        //     'success' => true,
        //     'client_id' => 'your_client_id',
        //     'mode' => 'sandbox'
        // ];
    }

    private function handleWebhook($params) {
        $payload = $params['payload'] ?? '';
        
        // Verify webhook signature
        // Process payment confirmation
        // Update invoice status via PaymentManager::markPaid()
        
        return ['success' => true];
    }
}

Step 4: Required Actions

Payment gateway modules should implement these actions:

  • process: Initiate payment processing (required)
  • webhook: Handle webhook callbacks from the gateway (required)

Optional actions:

  • create_payment_intent: Create payment intent for embedded forms (like Stripe)
  • confirm_payment_intent: Confirm a payment intent
  • save_payment_method: Save payment methods for future use
  • charge_payment_method: Charge a saved payment method
  • create_subscription: Create recurring subscriptions
  • cancel_subscription: Cancel recurring subscriptions

Step 5: Auto-Detection

Once created, your module will be automatically detected in Admin → Settings → Payment Gateways (not Admin → Modules). Enable and configure it there.

Note: Payment gateways are managed separately from other modules (servers, registrars) in the Settings section.

Step 6: Integration

Once enabled, your gateway will automatically appear in:

  • Invoice payment pages (client/invoices/{invoice_number}/pay)
  • Wallet top-up pages (client/wallet?action=pay)
  • Checkout process (client/checkout)
  • Admin payment processing (admin/invoices.php)

No code modifications are required! The system automatically integrates your gateway into all payment flows.

Example: Stripe Gateway

See /modules/gateways/stripe/StripeGateway.php for a complete reference implementation.

Response Formats

The process action can return different response formats depending on your gateway type:

  • Hosted Checkout: ['success' => true, 'redirect_url' => '...']
  • Embedded Forms: ['success' => true, 'client_secret' => '...']
  • On-site Buttons: ['success' => true, 'client_id' => '...', 'mode' => '...']
  • Direct Processing: ['success' => true, 'transaction_id' => '...']