Files
WooNooW/PAYMENT_GATEWAY_PATTERNS.md
dwindown 232059e928 feat: Complete Dashboard API Integration with Analytics Controller
 Features:
- Implemented API integration for all 7 dashboard pages
- Added Analytics REST API controller with 7 endpoints
- Full loading and error states with retry functionality
- Seamless dummy data toggle for development

📊 Dashboard Pages:
- Customers Analytics (complete)
- Revenue Analytics (complete)
- Orders Analytics (complete)
- Products Analytics (complete)
- Coupons Analytics (complete)
- Taxes Analytics (complete)
- Dashboard Overview (complete)

🔌 Backend:
- Created AnalyticsController.php with REST endpoints
- All endpoints return 501 (Not Implemented) for now
- Ready for HPOS-based implementation
- Proper permission checks

🎨 Frontend:
- useAnalytics hook for data fetching
- React Query caching
- ErrorCard with retry functionality
- TypeScript type safety
- Zero build errors

📝 Documentation:
- DASHBOARD_API_IMPLEMENTATION.md guide
- Backend implementation roadmap
- Testing strategy

🔧 Build:
- All pages compile successfully
- Production-ready with dummy data fallback
- Zero TypeScript errors
2025-11-04 11:19:00 +07:00

13 KiB

Payment Gateway Plugin Patterns Analysis

Overview

Analysis of 4 Indonesian payment gateway plugins to identify common patterns and integration strategies for WooNooW.


1. TriPay Payment Gateway

Architecture

  • Base Class: Tripay_Payment_Gateway extends WC_Payment_Gateway
  • Pattern: Abstract base class + Multiple child gateway classes
  • Registration: Dynamic gateway loading via glob()

Key Features

// Base abstract class with shared functionality
abstract class Tripay_Payment_Gateway extends WC_Payment_Gateway {
    public $sub_id;           // Unique ID for each gateway
    public $payment_method;   // API payment method code
    public $apikey;
    public $merchantCode;
    public $privateKey;
    
    public function __construct() {
        $this->id = $this->sub_id;  // Set from child class
        $this->init_settings();
        // Shared configuration from global settings
        $this->apikey = get_option('tripay_api_key');
        $this->merchantCode = get_option('tripay_merchant_code');
    }
}

Gateway Registration

function add_tripay_gateway($methods) {
    foreach (TripayPayment::gateways() as $id => $property) {
        $methods[] = $property['class'];
    }
    return $methods;
}
add_filter('woocommerce_payment_gateways', 'add_tripay_gateway');

// Auto-load all gateway files
$filenames = glob(dirname(__FILE__).'/includes/gateways/*.php');
foreach ($filenames as $filename) {
    include_once $filename;
}

Child Gateway Example (BNI VA)

class WC_Gateway_Tripay_BNI_VA extends Tripay_Payment_Gateway {
    public $sub_id = 'tripay_bniva';  // Unique ID
    
    public function __construct() {
        parent::__construct();
        $this->method_title = 'TriPay - BNI VA';
        $this->method_description = 'Pembayaran melalui BNI Virtual Account';
        $this->payment_method = 'BNIVA';  // API code
        
        $this->init_form_fields();
        $this->init_settings();
    }
}

Payment Processing

  • Creates transaction via API
  • Stores metadata: _tripay_payment_type, _tripay_payment_expired_time, _tripay_payment_pay_code
  • Handles callbacks via woocommerce_api_wc_gateway_tripay

Blocks Support

add_action('woocommerce_blocks_loaded', 'woocommerce_tripay_gateway_woocommerce_block_support');
function woocommerce_tripay_gateway_woocommerce_block_support() {
    if (class_exists('Automattic\WooCommerce\Blocks\Payments\Integrations\AbstractPaymentMethodType')) {
        include_once dirname(__FILE__).'/includes/admin/class-wc-tripay-blocks.php';
        add_action('woocommerce_blocks_payment_method_type_registration',
            function ($payment_method_registry) {
                $payment_method_registry->register(new WC_Tripay_Blocks());
            }
        );
    }
}

2. Duitku Payment Gateway

Architecture

  • Base Class: Duitku_Payment_gateway extends WC_Payment_Gateway
  • Pattern: Similar to TriPay - Abstract base + Multiple children
  • Registration: Manual array of gateway class names

Key Features

class Duitku_Payment_gateway extends WC_Payment_Gateway {
    public $sub_id;           // Set by child
    public $payment_method;   // API method code
    public $apiKey;
    public $merchantCode;
    public $endpoint;
    
    public function __construct() {
        $this->id = $this->sub_id;
        $this->init_settings();
        
        // Global configuration
        $this->apiKey = get_option('duitku_api_key');
        $this->merchantCode = get_option('duitku_merchant_code');
        $this->endpoint = rtrim(get_option('duitku_endpoint'), '/');
    }
}

Gateway Registration

add_filter('woocommerce_payment_gateways', 'add_duitku_gateway');

function add_duitku_gateway($methods){
    $methods[] = 'WC_Gateway_Duitku_VA_Permata';
    $methods[] = 'WC_Gateway_Duitku_VA_BNI';
    $methods[] = 'WC_Gateway_Duitku_OVO';
    $methods[] = 'WC_Gateway_Duitku_CC';
    // ... 30+ gateways manually listed
    return $methods;
}

// Load all gateway files
foreach (glob(dirname(__FILE__) . '/includes/gateways/*.php') as $filename) {
    include_once $filename;
}

Payment Processing

  • API endpoint: /api/merchant/v2/inquiry
  • Stores order items as array
  • Handles fees and surcharges
  • Callback via woocommerce_api_wc_gateway_{$this->id}

3. Xendit Payment

Architecture

  • Base Class: WC_Xendit_Invoice extends WC_Payment_Gateway
  • Pattern: Singleton + Conditional loading
  • Registration: Simple array, conditional CC gateway

Key Features

class WC_Xendit_PG {
    private static $instance;
    
    public static function get_instance() {
        if (self::$instance === null) {
            self::$instance = new self();
        }
        return self::$instance;
    }
    
    public function add_xendit_payment_gateway($methods) {
        $methods[] = 'WC_Xendit_Invoice';
        
        // For admin
        if (is_admin()) {
            return $this->xendit_payment_gateway_settings($methods);
        }
        
        // Conditional CC gateway (with/without addons)
        $cc_methods = 'WC_Xendit_CC';
        if ($this->should_load_addons()) {
            $cc_methods = 'WC_Xendit_CC_Addons';
        }
        
        $methods[] = $cc_methods;
        return $methods;
    }
    
    public function should_load_addons() {
        if (class_exists('WC_Subscriptions_Order') && function_exists('wcs_create_renewal_order')) {
            return true;
        }
        if (class_exists('WC_Pre_Orders_Order')) {
            return true;
        }
        return false;
    }
}

Gateway Registration

add_filter('woocommerce_payment_gateways', array($this, 'add_xendit_payment_gateway'));

Unique Features

  • Singleton pattern for main plugin class
  • Conditional gateway loading based on installed plugins
  • Addon support for subscriptions and pre-orders
  • Helper classes for logging, phone formatting, webhooks

4. WooCommerce PayPal Payments

Architecture

  • Pattern: Enterprise-level with dependency injection
  • Structure: Modular with services, modules, and extensions
  • Registration: Complex with feature detection

Key Features

// Modern PHP with namespaces and DI
namespace WooCommerce\PayPalCommerce;

class PPCP {
    private $container;
    
    public function __construct() {
        $this->container = new Container();
        $this->load_modules();
    }
}

Gateway Registration

  • Uses WooCommerce Blocks API
  • Feature flags and capability detection
  • Multiple payment methods (PayPal, Venmo, Cards, etc.)
  • Advanced settings and onboarding flow

Common Patterns Identified

1. Base Class Pattern

All plugins use abstract/base class extending WC_Payment_Gateway:

abstract class Base_Gateway extends WC_Payment_Gateway {
    public $sub_id;           // Unique gateway ID
    public $payment_method;   // API method code
    
    public function __construct() {
        $this->id = $this->sub_id;
        $this->init_settings();
        $this->load_global_config();
    }
}

2. Global Configuration

Shared API credentials stored in WordPress options:

$this->apiKey = get_option('provider_api_key');
$this->merchantCode = get_option('provider_merchant_code');
$this->endpoint = get_option('provider_endpoint');

3. Multiple Gateway Classes

One class per payment method:

  • WC_Gateway_Provider_BNI_VA
  • WC_Gateway_Provider_BCA_VA
  • WC_Gateway_Provider_OVO
  • etc.

4. Dynamic Registration

Two approaches:

// Approach A: Loop through array
function add_gateways($methods) {
    $methods[] = 'Gateway_Class_1';
    $methods[] = 'Gateway_Class_2';
    return $methods;
}

// Approach B: Auto-discover
foreach (glob(__DIR__ . '/gateways/*.php') as $file) {
    include_once $file;
}

5. Metadata Storage

Order metadata for tracking:

$order->update_meta_data('_provider_transaction_id', $transaction_id);
$order->update_meta_data('_provider_payment_type', $payment_type);
$order->update_meta_data('_provider_expired_time', $expired_time);

6. Callback Handling

WooCommerce API endpoints:

add_action('woocommerce_api_wc_gateway_' . $this->id, [$this, 'handle_callback']);

7. Blocks Support

WooCommerce Blocks integration:

add_action('woocommerce_blocks_loaded', 'register_blocks_support');
add_action('woocommerce_blocks_payment_method_type_registration', 
    function($registry) {
        $registry->register(new Gateway_Blocks());
    }
);

8. HPOS Compatibility

Declare HPOS support:

add_action('before_woocommerce_init', function () {
    if (class_exists(\Automattic\WooCommerce\Utilities\FeaturesUtil::class)) {
        \Automattic\WooCommerce\Utilities\FeaturesUtil::declare_compatibility(
            'custom_order_tables', 
            __FILE__, 
            true
        );
    }
});

WooNooW Integration Strategy

Current Implementation

We already have a good foundation:

  1. Payment channels filter - woonoow/payment_gateway_channels
  2. Channel-based payment IDs - bacs_account-name_0
  3. Dynamic gateway detection - payment_gateways() vs get_available_payment_gateways()

1. Gateway Metadata API 🆕

Provide a filter for gateways to register their metadata:

// In PaymentChannels.php or new PaymentGatewayMeta.php
add_filter('woonoow/payment_gateway_meta', function($meta, $gateway_id, $gateway) {
    // Allow gateways to provide additional metadata
    return $meta;
}, 10, 3);

2. Order Metadata Display 🆕

Show payment-specific metadata in Order Detail:

// In OrdersController.php show() method
$payment_meta = [];
$meta_keys = apply_filters('woonoow/payment_meta_keys', [
    '_tripay_payment_pay_code' => 'Payment Code',
    '_tripay_payment_expired_time' => 'Expires At',
    '_duitku_reference' => 'Reference',
    '_xendit_invoice_id' => 'Invoice ID',
], $order);

foreach ($meta_keys as $key => $label) {
    $value = $order->get_meta($key);
    if (!empty($value)) {
        $payment_meta[$key] = [
            'label' => $label,
            'value' => $value,
        ];
    }
}

3. Gateway Instructions Display 🆕

Show payment instructions in Order Detail:

// Allow gateways to provide custom instructions
$instructions = apply_filters('woonoow/payment_instructions', '', $order, $gateway_id);

4. Webhook/Callback Logging 🆕

Log payment callbacks for debugging:

// In a new WebhookLogger.php
add_action('woocommerce_api_*', function() {
    // Log all API callbacks
    error_log('[WooNooW] Payment callback: ' . $_SERVER['REQUEST_URI']);
}, 1);

5. Payment Status Sync 🆕

Provide a unified way to sync payment status:

do_action('woonoow/payment_status_changed', $order, $old_status, $new_status, $gateway_id);

Implementation Priority

Phase 1: Essential (Current)

  • Payment channels filter
  • Gateway title retrieval
  • Channel-based IDs

Phase 2: Enhanced Display 🎯

  • Payment metadata display in Order Detail
  • Payment instructions card
  • Gateway-specific order notes

Phase 3: Developer Experience 🎯

  • Gateway metadata API
  • Webhook logging
  • Payment status hooks

Phase 4: Advanced 🔮

  • Payment retry mechanism
  • Refund integration
  • Multi-currency support

Key Takeaways

What Works Well

  1. Base class pattern - Easy to extend
  2. Global configuration - Centralized API credentials
  3. Metadata storage - Flexible tracking
  4. WooCommerce hooks - Standard integration points

What Could Be Better ⚠️

  1. Manual gateway registration - Error-prone, hard to maintain
  2. Hardcoded metadata keys - Not discoverable
  3. No standard for instructions - Each gateway implements differently
  4. Limited admin UI - Payment details not easily visible

WooNooW Advantages 🎉

  1. REST API first - Modern architecture
  2. React SPA - Better UX for payment details
  3. HPOS native - Future-proof
  4. Centralized channels - Unified payment method handling

Conclusion

All payment gateways follow similar patterns:

  • Extend WC_Payment_Gateway
  • Use global configuration
  • Store order metadata
  • Handle callbacks via WooCommerce API
  • Support WooCommerce Blocks

WooNooW is already well-positioned to handle these gateways. The main enhancements needed are:

  1. Better display of payment metadata in Order Detail
  2. Unified API for gateways to provide instructions
  3. Developer-friendly hooks for payment events

These can be implemented incrementally without breaking existing functionality.