Skip to main content

CLI Plugin Development

The J2Commerce CLI scaffolding tool generates complete payment and shipping plugins from templates, reducing development time from hours to minutes. The tool uses stub files with placeholder tokens and conditional blocks to create production-ready plugin code.

Prerequisites

Before using the scaffolding tool, ensure:

  1. J2Commerce 6 is installed and enabled
  2. Console plugin plg_console_j2commerce is enabled
  3. Command-line access to your Joomla installation (SSH or terminal)

Quick Start

Enable the Console Plugin

If the console plugin is not yet enabled:

# Navigate to your Joomla root directory
cd /path/to/joomla

# Discover extensions
php cli/joomla.php extension:discover

# List console plugins to verify
php cli/joomla.php extension:list --type=plugin | grep console

Enable the plugin via the admin interface:

  1. Go to System -> Plugins
  2. Search for "J2Commerce Console"
  3. Set Status to Enabled

Generate a Payment Plugin (Interactive)

php cli/joomla.php j2commerce:create:plugin payment stripe

Generate a Shipping Plugin (Interactive)

php cli/joomla.php j2commerce:create:plugin shipping ups

Command Reference

Syntax

php cli/joomla.php j2commerce:create:plugin <type> <name> [options]

Arguments

ArgumentRequiredDescription
typeYesPlugin type: payment or shipping
nameYesPlugin name (lowercase, underscores, must start with letter)

Options

OptionDefaultDescription
--path=DIRCurrent directoryOutput directory for generated files
--installfalseCopy generated plugin to plugins/j2commerce/ directory
--forcefalseOverwrite existing files without prompting
-nfalseNon-interactive mode (use default options)

Exit Codes

CodeMeaning
0Success
1Invalid type argument
2Invalid name format
3Files already exist (use --force to overwrite)
4Stub file not found or processing error

Interactive Mode Walkthrough

Payment Plugin Prompts

When you run:

php cli/joomla.php j2commerce:create:plugin payment my_gateway

The command prompts for configuration options:

Creating payment plugin
========================

Answer the following questions to customize your plugin:

Display name (human-readable) [My Gateway]: Stripe
Include sandbox mode support? [Yes]: y
Include sandbox credential fields? [Yes]: y
Include webhook support? [No]: n
Include surcharge support? [Yes]: y
Include geozone restriction? [Yes]: y
Include min/max subtotal limits? [No]: n
Include debug logging? [Yes]: y

[OK] Created payment plugin: payment_stripe
* services/provider.php
* src/Extension/PaymentStripe.php
* language/en-GB/plg_j2commerce_payment_stripe.ini
* language/en-GB/plg_j2commerce_payment_stripe.sys.ini
* payment_stripe.xml
* tmpl/prepayment.php
* tmpl/postpayment.php
* tmpl/message.php

Shipping Plugin Prompts

When you run:

php cli/joomla.php j2commerce:create:plugin shipping my_carrier

The command prompts for configuration options:

Creating shipping plugin
=========================

Answer the following questions to customize your plugin:

Display name (human-readable) [My Carrier]: UPS
Include API credentials? [Yes]: y
Include sandbox mode support? [Yes]: y
Include surcharge support? [Yes]: y
Include geozone restriction? [Yes]: y
Include shipping tax (tax profile field)? [Yes]: y
Include custom rate table? [No]: n
Include debug logging? [Yes]: y

[OK] Created shipping plugin: shipping_ups
* services/provider.php
* src/Extension/ShippingUps.php
* language/en-GB/plg_j2commerce_shipping_ups.ini
* language/en-GB/plg_j2commerce_shipping_ups.sys.ini
* shipping_ups.xml
* forms/shippingmethod.xml
* tmpl/method.php

Payment Plugin Options

PromptDefaultDescription
Display nameAuto-generated from nameHuman-readable name shown to customers (e.g., "Stripe")
Sandbox mode supportYesInclude sandbox/production toggle for testing
Sandbox credential fieldsYesAdd sandbox API key and secret fields (only if sandbox enabled)
Webhook supportNoAdd webhook ID and secret fields for payment notifications
Surcharge supportYesAdd surcharge name, percent, and fixed amount fields
Geozone restrictionYesAdd geozone filter field to limit by region
Min/max subtotal limitsNoAdd order amount restriction fields
Debug loggingYesAdd debug toggle for logging API requests

Shipping Plugin Options

PromptDefaultDescription
Display nameAuto-generated from nameHuman-readable name shown to customers (e.g., "UPS")
API credentialsYesInclude API key and secret fields
Sandbox mode supportYesInclude sandbox toggle for testing
Surcharge supportYesAdd surcharge fields
Geozone restrictionYesAdd geozone filter field
Shipping taxYesAdd tax profile field for shipping tax
Custom rate tableNoInclude local method/rate tables for custom shipping rates
Debug loggingYesAdd debug toggle

Non-Interactive Mode

Use non-interactive mode with the -n flag to generate a plugin with all default options:

# Generate payment plugin with all defaults
php cli/joomla.php j2commerce:create:plugin payment stripe -n

# Generate shipping plugin with all defaults
php cli/joomla.php j2commerce:create:plugin shipping ups -n

Default options for payment plugins:

  • Sandbox mode: enabled
  • Sandbox credentials: enabled
  • Webhook support: disabled
  • Surcharge: enabled
  • Geozone: enabled
  • Min/max subtotal: disabled
  • Debug: enabled

Default options for shipping plugins:

  • API credentials: enabled
  • Sandbox mode: enabled
  • Surcharge: enabled
  • Geozone: enabled
  • Shipping tax: enabled
  • Custom rate table: disabled
  • Debug: enabled

Name Normalization

The command normalizes the plugin name into multiple formats automatically:

Input NameElementClass NameDisplay Name (default)
stripepayment_stripePaymentStripeStripe
authorize_netpayment_authorize_netPaymentAuthorizeNetAuthorize Net
upsshipping_upsShippingUpsUPS
dhl_expressshipping_dhl_expressShippingDhlExpressDHL Express
my_gatewaypayment_my_gatewayPaymentMyGatewayMy Gateway

Generated File Structure

Payment Plugin

payment_stripe/
├── payment_stripe.xml # Manifest with configuration fields
├── services/
│ └── provider.php # Dependency injection setup
├── src/
│ └── Extension/
│ └── PaymentStripe.php # Main plugin class
├── language/
│ └── en-GB/
│ ├── plg_j2commerce_payment_stripe.ini # Frontend language
│ └── plg_j2commerce_payment_stripe.sys.ini # Admin language
└── tmpl/
├── prepayment.php # Payment button/form template
├── postpayment.php # Success page template
└── message.php # Error message template

Shipping Plugin

shipping_ups/
├── shipping_ups.xml # Manifest with configuration fields
├── services/
│ └── provider.php # Dependency injection setup
├── src/
│ └── Extension/
│ └── ShippingUps.php # Main plugin class
├── language/
│ └── en-GB/
│ ├── plg_j2commerce_shipping_ups.ini # Frontend language
│ └── plg_j2commerce_shipping_ups.sys.ini # Admin language
├── forms/
│ └── shippingmethod.xml # Method configuration form (optional)
└── tmpl/
└── method.php # Shipping method template

Placeholder Tokens

Stub files use placeholder tokens that are replaced with actual values during generation.

Core Tokens

TokenExampleDescription
{{name}}stripePlugin element name (lowercase, underscores)
{{Name}}StripeClass name (PascalCase)
{{NAME}}STRIPEUppercase for language keys
{{display_name}}StripeHuman-readable display name
{{type}}paymentPlugin type (payment or shipping)
{{Type}}PaymentPlugin type (PascalCase)
{{element}}payment_stripeFull element name
{{namespace}}J2Commerce\Plugin\J2Commerce\PaymentStripeFull PHP namespace
{{year}}2024-2026Copyright year range
{{year_full}}2026Current year
{{month}}FebruaryCurrent month name

Conditional Blocks

Stub files support conditional blocks that include or exclude code sections based on prompt responses.

Syntax

{{#if condition}}
... content included when condition is true ...
{{/if}}

Available Conditions

ConditionPlugin TypeCorresponds To
sandboxPayment, ShippingSandbox mode support
api_credentialsPayment, ShippingAPI credentials fields
sandbox_credentialsPaymentSandbox credential fields
webhookPaymentWebhook support
surchargePayment, ShippingSurcharge support
geozonePayment, ShippingGeozone restriction
minmax_subtotalPaymentMin/max subtotal limits
shipping_taxShippingShipping tax (tax profile field)
custom_rate_tableShippingCustom rate table
debugPayment, ShippingDebug logging

Example: Conditional Fields in Manifest

{{#if sandbox}}
<field
name="sandbox"
type="radio"
layout="joomla.form.field.radio.switcher"
default="0"
label="PLG_J2COMMERCE_PAYMENT_{{NAME}}_USE_SANDBOX"
>
<option value="0">JNO</option>
<option value="1">JYES</option>
</field>
{{/if}}

When sandbox is enabled, the sandbox toggle field is included in the generated manifest. When disabled, the entire block is removed.

Example: Conditional Code in Plugin Class

{{#if surcharge}}
public function onCalculateFees(Event $event): void
{
// Surcharge calculation logic included
$surchargePercent = (float) $this->params->get('surcharge_percent', 0);
$surchargeFixed = (float) $this->params->get('surcharge_fixed', 0);
// ...
}
{{/if}}

After Generation

Install the Plugin

If you did not use --install, install the generated plugin manually:

Method 1: Discover Install

  1. Copy the plugin directory to plugins/j2commerce/
  2. Go to System -> Install -> Discover
  3. Click Discover
  4. Select the new plugin
  5. Click Install

Method 2: Use --install Flag

# Generate and install in one step
php cli/joomla.php j2commerce:create:plugin payment stripe --install

Configure the Plugin

  1. Go to System -> Plugins
  2. Search for the plugin by name (e.g., "Stripe" or "UPS")
  3. Enable the plugin
  4. Configure the settings:
    • Display name and image
    • API credentials (live and sandbox)
    • Payment/shipping status
    • Surcharge settings
    • Geozone restrictions

Implement Gateway Logic

The generated plugin is a skeleton. You must implement:

Payment Plugins

MethodPurpose
_prePayment()Build and render the payment form, redirect to gateway
_postPayment()Handle payment response, verify signature, update order status
onProcessWebhook()Handle webhook notifications (if webhook support enabled)

Shipping Plugins

MethodPurpose
onGetShippingRates()Calculate shipping rates from carrier API
onGetShippingOptions()Check availability and restrictions

Example: Implementing _prePayment()

// File: plugins/j2commerce/payment_stripe/src/Extension/PaymentStripe.php

public function _prePayment(array $data): string
{
$vars = new \stdClass();
$vars->order_id = $data['order_id'];
$vars->orderpayment_amount = $data['orderpayment_amount'];

// Get credentials based on sandbox mode
$sandbox = (bool) $this->params->get('sandbox', 0);
$vars->api_key = $sandbox
? $this->params->get('sandbox_api_key', '')
: $this->params->get('api_key', '');

// Build redirect URL or payment form
$vars->action_url = 'https://api.stripe.com/v1/checkout/sessions';

// TODO: Add your gateway-specific logic here
// - Create payment session
// - Generate signature
// - Set callback URLs

return $this->_getLayout('prepayment', $vars);
}

Example: Implementing _postPayment()

public function _postPayment(object $data): string
{
$app = Factory::getApplication();
$paction = $app->input->getString('paction');

switch ($paction) {
case 'display':
// Payment successful - update order status
$this->updateOrderStatus($data->order_id, 'Confirmed');
return $this->_getLayout('postpayment', $vars);

case 'cancel':
// User cancelled - restore cart
return $this->_getLayout('message', ['message' => 'Payment cancelled']);

default:
// Error handling
$this->log('Payment error: ' . print_r($data, true), Log::ERROR);
return $this->_getLayout('message', ['message' => 'Payment failed']);
}
}

Stub Customization

Stub File Locations

Stub files are located in:

administrator/components/com_j2commerce/stubs/
├── payment/
│ ├── manifest.xml.stub # Plugin manifest template
│ ├── provider.php.stub # Service provider template
│ ├── Extension.php.stub # Main plugin class template
│ ├── language.ini.stub # Frontend language template
│ ├── language.sys.ini.stub # Admin language template
│ └── tmpl/
│ ├── prepayment.php.stub # Pre-payment template
│ ├── postpayment.php.stub # Post-payment template
│ └── message.php.stub # Error message template
└── shipping/
├── manifest.xml.stub
├── provider.php.stub
├── Extension.php.stub
├── language.ini.stub
├── language.sys.ini.stub
├── forms/
│ └── shippingmethod.xml.stub # Method configuration form
└── tmpl/
└── method.php.stub # Shipping method template

Creating Custom Stubs

  1. Copy an existing stub file from stubs/payment/ or stubs/shipping/
  2. Modify the template using placeholder tokens and conditional blocks
  3. Save with the .stub extension in the appropriate directory

Example: Adding a New Conditional Field

In stubs/payment/manifest.xml.stub:

{{#if custom_field}}
<field
name="custom_option"
type="text"
label="PLG_J2COMMERCE_PAYMENT_{{NAME}}_CUSTOM_OPTION"
description="PLG_J2COMMERCE_PAYMENT_{{NAME}}_CUSTOM_OPTION_DESC"
/>
{{/if}}

Adding New Options

To add a new interactive option:

  1. Add the prompt in CreatePluginCommand.php:
// File: administrator/components/com_j2commerce/src/CliCommands/CreatePluginCommand.php

private function collectOptions(SymfonyStyle $io, string $type, string $name): array
{
// ... existing options ...

if ($type === 'payment') {
$options['custom_field'] = $io->confirm('Include custom field?', false);
}

return $options;
}
  1. Add the default in getDefaultOptions():
private function getDefaultOptions(string $type): array
{
if ($type === 'payment') {
return [
// ... existing defaults ...
'custom_field' => false,
];
}
// ...
}
  1. Use in stubs with {{#if custom_field}}...{{/if}}

Troubleshooting

Command Not Found

Error:

There are no commands defined in the "j2commerce" namespace.

Cause: The console plugin is not enabled.

Solution:

  1. Go to System -> Plugins
  2. Search for "J2Commerce Console"
  3. Set Status to Enabled

Alternatively via CLI:

# Check if plugin exists
php cli/joomla.php extension:list --type=plugin | grep j2commerce

# Enable via database (if needed)
mysql -u user -p joomla_db -e "UPDATE #__extensions SET enabled=1 WHERE element='j2commerce' AND folder='console'"

Permission Denied

Error:

file_put_contents(...): Failed to open stream: Permission denied

Cause: The output directory is not writable by the web server user.

Solution:

# Check current permissions
ls -la plugins/j2commerce/

# Fix permissions (adjust user/group for your system)
chmod -R 775 plugins/j2commerce/
chown -R www-data:www-data plugins/j2commerce/

Or use a different output path:

php cli/joomla.php j2commerce:create:plugin payment stripe --path=/tmp/plugins

Stub File Not Found

Error:

Stub file not found: /administrator/components/com_j2commerce/stubs/payment/manifest.xml.stub

Cause: Stub files are missing from the J2Commerce installation.

Solution:

  1. Reinstall J2Commerce component
  2. Verify the stubs directory exists:
ls -la administrator/components/com_j2commerce/stubs/

Plugin Does Not Appear After Install

Cause: Plugin manifest has incorrect values or database record missing.

Solution:

  1. Verify the generated manifest.xml has correct values:

    • group="j2commerce" attribute
    • Correct namespace
    • Valid plugin element name
  2. Run Discover in Extension Manager:

    • Go to System -> Install -> Discover
    • Click Discover
    • Install the plugin
  3. Check the database directly:

SELECT extension_id, name, element, folder, enabled
FROM #__extensions
WHERE type='plugin' AND folder='j2commerce';

Files Already Exist

Error:

File already exists: plugins/j2commerce/payment_stripe/payment_stripe.xml
(use --force to overwrite)

Solution:

Use --force to overwrite:

php cli/joomla.php j2commerce:create:plugin payment stripe --force

Or generate to a different path:

php cli/joomla.php j2commerce:create:plugin payment stripe --path=./output

Best Practices

  1. Use interactive mode for first-time plugin creation to understand all options
  2. Use non-interactive mode for automation scripts and CI/CD pipelines
  3. Always implement webhook signature verification for production payment plugins
  4. Enable debug logging during development for troubleshooting API issues
  5. Test with sandbox credentials before using live credentials
  6. Copy stubs locally before modifying to preserve originals