Skip to main content
Addons are the general-purpose extension type in OwnPay. Unlike gateways (which implement GatewayAdapterInterface) or themes (which override checkout templates), addons extend the platform through event hooks, custom HTTP routes, cron jobs, admin menu entries, and database-backed functionality.

How addon plugins work

PluginLoader::loadActive() scans modules/addons/, validates each manifest.json, token-scans all PHP files, and calls the two-phase lifecycle:
  1. register(EventManager $events, Container $container) - called during boot phase. All hook and filter registrations are attributed to the plugin slug.
  2. boot(Container $container) - called after all plugins have registered. Use this phase to capture container services.

Directory structure

The manifest.json file

The entrypoint class

The entrypoint must implement OwnPay\Plugin\PluginInterface:

Accessing core services

Plugins are not wired into the DI container automatically. Resolve services manually from the $container argument:

Routes

Routes declared in manifest.json under the routes array are registered into the core router:

Cron jobs

Declare scheduled jobs in manifest.json under the cron array:
Supported schedules: every_minute, every_5min, every_15min, every_30min, hourly, every_6hours, daily, weekly.

Admin menu entries

Database migrations

Create a migrations/ directory with .sql files. Plugin tables must be prefixed op_plugin_.

Security requirements

  • No eval() or OS commands
  • No direct op_* table access
  • Escape all output
  • Use parameterized queries
  • Respect tenant isolation

Checklist

  • manifest.json complete; slug matches directory name
  • Entrypoint implements PluginInterface with all six methods
  • All hooks registered inside register()
  • uninstall() drops any op_plugin_ tables
  • Plugin tables named op_plugin_{slug}_*
  • Admin routes use the "admin" middleware group
  • Cron jobs implement CronJobInterface
  • No eval(), exec(), shell_exec()
Last modified on July 15, 2026