OwnPay’s plugin system lets you extend every part of the platform — from adding payment gateways and building admin dashboards to redesigning the checkout experience — without ever touching core files. Every feature you add lives in its own isolated directory underDocumentation Index
Fetch the complete documentation index at: https://mintlify.com/own-pay/OwnPay-Documentation/llms.txt
Use this file to discover all available pages before exploring further.
modules/, upgrades cleanly, and can be activated or deactivated per brand.
Plugin Types
OwnPay ships three distinct plugin types. Each type is loaded from a different directory and provides a different integration surface.Gateway
Add new payment methods: Stripe, bKash, GCash, crypto, or any custom processor. Gateway plugins implement the
GatewayAdapterInterface and handle checkout initiation, callback verification, webhook validation, and refunds.Addon
Extend the platform with new features: reporting dashboards, SMS notifications, CRM integrations, subscription billing, scheduled sync jobs, or custom API endpoints.
Theme
Override checkout page templates and inject brand-scoped CSS and JavaScript. Theme plugins control the full visual experience of every customer-facing screen.
Directory Structure
Each plugin lives under its own directory inside the type-specific subdirectory. The slug used as the directory name must match theslug field in manifest.json exactly.
Plugins placed under
modules/gateways/ must include "type": "gateway" in manifest.json. Addons go under modules/addons/ with "type": "addon", and themes under modules/themes/ with "type": "theme". Mismatches cause load failure.The manifest.json Schema
Every plugin requires a manifest.json at its root. This is the single source of truth for discovery, validation, and database registration.
Full Field Reference
Full Field Reference
| Field | Type | Required | Description |
|---|---|---|---|
name | string | ✅ | Human-readable display name shown in the admin panel. |
slug | string | ✅ | Unique lowercase identifier. Pattern: ^[a-z0-9][a-z0-9\-]{0,62}[a-z0-9]$. Must match directory name. |
version | string | ✅ | Semantic version string (e.g., 1.0.0). |
description | string | ✅ | Short human-readable summary. |
author | string | ✅ | Plugin author name or organisation. |
type | string | ✅ | One of "gateway", "addon", or "theme". |
entrypoint | string | ✅ | PHP filename containing the entrypoint class. No path traversal permitted. |
namespace | string | ✅ | PSR-4 root namespace. All classes under this namespace autoload from the plugin directory. |
capabilities | array | ✅ | One or more Capability enum string values (see Capabilities). |
requires.core | string | ✅ | Semver constraint the OwnPay core version must satisfy. |
requires.php | string | ❌ | PHP version constraint. |
permissions | array | ❌ | RBAC permission strings required for the plugin’s operations. |
icon | string | ❌ | Icon filename relative to plugin root. Copied to public/assets/img/gateways/{slug}.{ext}. |
color | string | ❌ | Hex brand color shown in the UI (e.g., "#635BFF"). |
csp | object | ❌ | Content Security Policy extensions. Keys: script_src, style_src, frame_src, connect_src. |
routes | array | ❌ | Addon route tuples ["METHOD", "/path", "handlerMethod", "middlewareGroup"]. |
cron | array | ❌ | Scheduled job declarations with name, schedule, and class. |
admin_menu | array | ❌ | Sidebar navigation entries with label and url. |
migrations | string | ❌ | Path to migrations directory. Defaults to "migrations". |
Plugin Lifecycle
When OwnPay boots, every enabled plugin passes through a fixed sequence of stages. Understanding this sequence is critical for knowing where to put your initialization code.Discovery
PluginLoader::loadActive() scans the type-specific modules/ subdirectory, finds all directories containing a manifest.json, and validates the manifest schema.Registration
Each manifest’s entrypoint file is token-scanned for blocked functions (
eval, exec, shell_exec, etc.). If the scan passes, the entrypoint class is instantiated and PluginInterface::register() is called, wrapped with events->pushOwner($slug) so all hook registrations are attributed to the plugin slug.Configuration
Config files and plugin settings stored in
op_system_settings are read. The PSR-4 autoloader is registered for the plugin’s declared namespace.Activation
PluginInterface::boot() is called after all plugins have registered. All DI container services are fully resolved at this point. Gateway plugins are automatically registered with GatewayBridge.Runtime
The plugin responds to HTTP requests and events through its registered hooks and routes. Brand-context scoping ensures each listener only fires for brands where the plugin is active.
Plugin Class Structure
All three plugin types implementOwnPay\Plugin\PluginInterface, which requires six methods.
Plugin API
Accessing Core Services
Resolve services from the$container argument passed to register() and boot(). The container holds all services registered in config/services.php.
Database Access
Plugin-owned tables must be prefixed withop_plugin_. Direct access to core op_* tables is blocked by PluginSandbox::validateSql().
Registering Routes
Routes declared inmanifest.json are automatically registered by the core router. Each entry is a tuple:
Adding Admin Menu Items
Declare static sidebar links inmanifest.json:
admin.menu.register hook:
Admin menu
url values must start with /. Off-site or javascript: URLs are silently dropped by PluginLoader::registerManifestAdminMenu().CLI Management Commands
Manage plugins from the command line usingphp public/index.php:
Database Migrations
Create.sql files in a migrations/ directory. Files execute in sort order on activation, and are tracked in op_plugin_migrations.
001_create_my_plugin_logs.down.sql.
Publishing to the Marketplace
Once your plugin is tested and documented, you can submit it to the OwnPay Plugin Marketplace for other operators to discover and install.Prepare
Ensure your plugin follows the directory structure, includes a complete
manifest.json, and provides a README.md with setup instructions.Test
Run your plugin against multiple OwnPay versions. Test activation, deactivation, and uninstallation. Verify all hooks fire correctly.
Package
ZIP the plugin directory. The archive root must contain
manifest.json. Blocked file extensions (.phar, .sh, .bat, .exe, .dll) will be rejected during installation.Review
The OwnPay team performs a security review — checking for blocked functions, SQL injection vectors, and proper capability declarations.