# 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 ```php // 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 ```php 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) ```php 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 ```php 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 ```php 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 ```php 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 ```php 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 ```php 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 ```php // 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`: ```php 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: ```php $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: ```php // 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: ```php $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: ```php add_action('woocommerce_api_wc_gateway_' . $this->id, [$this, 'handle_callback']); ``` ### 7. **Blocks Support** ✅ WooCommerce Blocks integration: ```php 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: ```php 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()` ### Recommended Enhancements #### 1. **Gateway Metadata API** 🆕 Provide a filter for gateways to register their metadata: ```php // 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: ```php // 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: ```php // Allow gateways to provide custom instructions $instructions = apply_filters('woonoow/payment_instructions', '', $order, $gateway_id); ``` #### 4. **Webhook/Callback Logging** 🆕 Log payment callbacks for debugging: ```php // 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: ```php do_action('woonoow/payment_status_changed', $order, $old_status, $new_status, $gateway_id); ``` --- ## Implementation Priority ### Phase 1: Essential (Current) ✅ - [x] Payment channels filter - [x] Gateway title retrieval - [x] 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.