# Oscommerce

> This skill should be used when the user asks to "create an osCommerce addon", "osCommerce module development", "osCommerce payment module", "osCommerce shipping module", "osCommerce hook system", or needs guidance on osCommerce add-on and module development.

- Skill: `biggora/oscommerce` (Agent Skill, multi-file: 3 files)
- Install (CLI): `npx skillmds@latest add biggora/oscommerce`
- Raw SKILL.md: https://api.skillmd.com/api/skills/biggora/oscommerce/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: biggora (https://skillmd.com/u/biggora)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/biggora/oscommerce

---


# osCommerce Add-on and Module Development

## Overview

osCommerce (Open Source Commerce) is one of the earliest open-source PHP e-commerce platforms, originally released in 2000. Despite its age, osCommerce continues to power thousands of online stores, particularly among merchants who adopted the platform early and have maintained their installations over the years. The platform is built on procedural PHP with direct MySQL queries, using a custom framework with `tep_` prefixed utility functions.

Two major versions remain in active use: osCommerce Online Merchant 2.3 (the widely deployed stable release) and osCommerce Online Merchant 2.4 (which introduced a hook system and modernized some internals). The 2.3 line uses direct file modification for customization, while 2.4 provides hooks that reduce the need to edit core files. Both versions share the same module architecture for payment, shipping, and order total extensions.

osCommerce does not use Composer, PSR autoloading, namespaces, or modern PHP patterns. All code follows procedural conventions with global variables, `include`/`require` statements, and direct database access through wrapper functions. Understanding this legacy architecture is essential for building add-ons that integrate cleanly.

## Module Types

osCommerce extends its functionality through typed module directories. Each module type has a specific location, interface, and purpose.

### Payment Modules

Payment modules handle payment processing during checkout. They reside in `includes/modules/payment/` with corresponding language files in `includes/languages/{language}/modules/payment/`. Each payment module is a single PHP class file that implements a standard set of properties and methods.

Required properties: `code`, `title`, `description`, `enabled`, `sort_order`. Required methods: `selection()` (render checkout form), `pre_confirmation_check()`, `confirmation()`, `process_button()`, `before_process()`, `after_process()`, `install()`, `remove()`, `keys()`.

```php
class my_payment {
  var $code, $title, $description, $enabled, $sort_order;

  function __construct() {
    $this->code = 'my_payment';
    $this->title = MODULE_PAYMENT_MY_PAYMENT_TEXT_TITLE;
    $this->description = MODULE_PAYMENT_MY_PAYMENT_TEXT_DESCRIPTION;
    $this->sort_order = defined('MODULE_PAYMENT_MY_PAYMENT_SORT_ORDER') ? MODULE_PAYMENT_MY_PAYMENT_SORT_ORDER : 0;
    $this->enabled = defined('MODULE_PAYMENT_MY_PAYMENT_STATUS') && MODULE_PAYMENT_MY_PAYMENT_STATUS == 'True';
  }

  function selection() {
    return array('id' => $this->code, 'module' => $this->title);
  }

  function pre_confirmation_check() { return false; }
  function confirmation() { return false; }
  function process_button() { return false; }
  function before_process() { return false; }

  function after_process() {
    // Process payment after order creation
    global $order_id;
    // Call payment gateway API, update order status
  }

  function install() {
    tep_db_query("INSERT INTO configuration (configuration_title, configuration_key, configuration_value, configuration_description, configuration_group_id, sort_order, set_function, date_added) VALUES ('Enable My Payment', 'MODULE_PAYMENT_MY_PAYMENT_STATUS', 'True', 'Enable payment module?', 6, 0, 'tep_cfg_select_option(array('True', 'False'), ', now())");
    tep_db_query("INSERT INTO configuration (configuration_title, configuration_key, configuration_value, configuration_description, configuration_group_id, sort_order, date_added) VALUES ('Sort Order', 'MODULE_PAYMENT_MY_PAYMENT_SORT_ORDER', '0', 'Display sort order.', 6, 1, now())");
  }

  function remove() {
    tep_db_query("DELETE FROM configuration WHERE configuration_key IN ('" . implode("', '", $this->keys()) . "')");
  }

  function keys() {
    return array('MODULE_PAYMENT_MY_PAYMENT_STATUS', 'MODULE_PAYMENT_MY_PAYMENT_SORT_ORDER');
  }
}
```

### Shipping Modules

Shipping modules calculate shipping rates during checkout. They reside in `includes/modules/shipping/` and implement a `quote()` method that returns available shipping options with rates. The `quote()` method receives no parameters -- it reads the order contents from global variables (`$order`, `$shipping_weight`, `$shipping_num_boxes`).

### Order Total Modules

Order total modules add line items to the order summary (subtotal, tax, shipping, discount, grand total). They reside in `includes/modules/order_total/` and implement a `process()` method that calculates and stores the module's contribution to the order total. Standard order total modules include `ot_subtotal`, `ot_tax`, `ot_shipping`, `ot_total`, and custom modules like `ot_discount` or `ot_coupon`.

### Content Modules

Content modules (osCommerce 2.3.4+ and 2.4) inject content into specific page locations. They reside in `includes/modules/content/` organized by page area (e.g., `includes/modules/content/index/` for the homepage). Content modules implement an `execute()` method and use the template system to render output.

### Header Tags Modules

Header tags modules add content to the HTML `<head>` section -- meta tags, canonical URLs, structured data, analytics scripts. They reside in `includes/modules/header_tags/` and implement an `execute()` method that outputs HTML to be inserted in the `<head>`.

For complete module structure details, configuration key conventions, and version differences, see [references/addon-architecture.md](references/addon-architecture.md).

## Add-on System

### File-Based Installation

osCommerce add-ons are distributed as file archives (ZIP or TAR.GZ). Installation is manual: extract the files and copy them to the correct locations in the osCommerce directory tree. There is no package manager, dependency resolver, or automated installer.

A typical add-on includes:

- Module PHP file(s) in the appropriate `includes/modules/` subdirectory.
- Language file(s) in `includes/languages/{language}/modules/`.
- Optional template modifications (edited core files with change markers).
- Optional SQL queries for database schema changes.
- A README with installation instructions listing every file to copy and every core file to modify.

### Apps Marketplace

The osCommerce Apps Marketplace (apps.oscommerce.com) hosts community-contributed add-ons. Add-ons are categorized by type (payment, shipping, admin tools, SEO, reports) and tagged with version compatibility. The marketplace provides download links, version history, support forums, and user ratings.

Publishing to the Apps Marketplace requires an osCommerce community account. Upload the add-on archive, provide a description, installation instructions, and screenshots. There is no formal review process -- community moderation handles quality control through ratings and forum feedback.

### Installation Best Practices

- Always back up the store before installing an add-on.
- Verify version compatibility (2.3 vs 2.4) before installation.
- Review all core file modifications before applying them.
- Use a diff tool to merge changes when multiple add-ons modify the same core file.
- Test in a staging environment before deploying to production.

## Hook System (osCommerce Online Merchant 2.4+)

osCommerce 2.4 introduced a hook system that reduces the need to directly modify core files. Hooks allow modules to register callbacks for specific events without editing the files that trigger those events.

### Site Hooks

Site hooks fire at defined points in the catalog (storefront) and admin page lifecycle. Register a hook by placing a PHP file in the appropriate hooks directory:

```
includes/hooks/shop/{hookPoint}/my_addon.php
includes/hooks/admin/{hookPoint}/my_addon.php
```

Each hook file defines a class with methods corresponding to the hook actions. The hook system automatically discovers and loads hook files from these directories.

### Action Hooks

Action hooks fire during specific business operations (before/after processing forms, orders, or database operations). Common action hooks include `beforeProcess`, `afterProcess`, `siteWide`, and page-specific hooks.

For complete hook system documentation including registration, catalog vs admin hooks, and migration patterns, see [references/hook-system.md](references/hook-system.md).

## Development Patterns

### tep_ Functions

osCommerce provides a set of utility functions prefixed with `tep_` (The Exchange Project, the original project name). These functions wrap common operations:

- `tep_db_query($query)` -- Execute a MySQL query.
- `tep_db_fetch_array($result)` -- Fetch the next row from a query result.
- `tep_db_num_rows($result)` -- Count rows in a result set.
- `tep_db_insert_id()` -- Get the last auto-increment ID.
- `tep_db_input($string)` -- Escape a string for safe SQL use.
- `tep_output_string($string)` -- HTML-encode a string for display.
- `tep_href_link($page, $params, $connection)` -- Generate a URL for an osCommerce page.
- `tep_image($src, $alt, $width, $height)` -- Generate an `<img>` tag.
- `tep_draw_form($name, $action, $params, $method)` -- Generate a `<form>` tag.
- `tep_draw_input_field($name, $value, $params)` -- Generate an `<input>` tag.

### Database Access

All database access uses the `tep_db_*` functions. There is no ORM, query builder, or prepared statement support in the core. Prevent SQL injection by using `tep_db_input()` for all user-supplied values:

```php
$customer_id = (int)$_GET['cID'];
$query = tep_db_query("SELECT customers_firstname, customers_lastname FROM customers WHERE customers_id = " . $customer_id);
$customer = tep_db_fetch_array($query);
```

### Configuration System

Module settings are stored in the `configuration` database table. Each setting is a row with `configuration_key`, `configuration_value`, and metadata columns. The `install()` method inserts configuration rows; the `remove()` method deletes them.

Read configuration values with the constant defined by the configuration key:

```php
if (defined('MODULE_PAYMENT_MY_PAYMENT_API_KEY')) {
  $api_key = MODULE_PAYMENT_MY_PAYMENT_API_KEY;
}
```

osCommerce loads all configuration values as PHP constants at startup, so configuration reads are simple constant references with no database queries at runtime.

### Global Variables

osCommerce relies heavily on global variables. The `$order` object contains the current order during checkout. The `$currencies` object handles currency formatting. The `$languages_id` variable identifies the active language. Access these globals within module methods:

```php
function after_process() {
  global $order, $order_id, $currencies;
  $total = $currencies->format($order->info['total']);
}
```

## Limitations

Understanding osCommerce's limitations is critical for setting development expectations:

- **No Composer or PSR autoloading** -- All files are loaded via `include`/`require`. There is no dependency management. Introducing third-party libraries requires manual file placement and autoloader bootstrapping.
- **No namespaces** -- All classes exist in the global namespace. Name collisions between add-ons are possible. Use unique, descriptive class names.
- **Procedural architecture** -- The codebase is primarily procedural PHP, not object-oriented. While modules use classes, the overall architecture relies on global state and function calls.
- **Manual file management** -- Installation, updates, and removal of add-ons require manual file operations. There is no built-in add-on installer or update mechanism.
- **Direct core file editing** -- Many customizations in osCommerce 2.3 require editing core files. This creates merge conflicts when updating the core, and multiple add-ons modifying the same file can conflict with each other.
- **No REST API** -- osCommerce does not include a built-in API. External integrations require custom-built endpoints or third-party API add-ons.
- **Limited template system** -- Template modifications involve editing PHP files that mix logic and presentation. There is no template engine (no Twig, Smarty, or Blade).
- **Security considerations** -- The legacy codebase predates modern security practices. Ensure all custom code escapes output, validates input, and uses `tep_db_input()` for SQL parameters.

## Anti-Patterns

- **Modifying core files without markers** -- When core file edits are necessary (osCommerce 2.3), always surround changes with comment markers (`// BEGIN MyAddon` / `// END MyAddon`) so they can be identified and merged during updates.
- **Hardcoding language strings** -- Use language files and defined constants for all user-facing text. Hardcoded strings prevent internationalization.
- **Ignoring the configuration system** -- Store all module settings in the `configuration` table through `install()` and `keys()`. Do not use config files, hardcoded values, or separate database tables for simple settings.
- **Skipping input validation** -- Always cast numeric IDs to `(int)`, use `tep_db_input()` for strings in queries, and validate form submissions before processing.
- **Using deprecated MySQL functions** -- osCommerce 2.3 originally used the `mysql_*` extension. Updated versions use `mysqli_*`. Ensure compatibility with the installed PHP version and database wrapper.

## Reference Files

- [Add-on Architecture](references/addon-architecture.md) -- Module structure for payment/shipping/order_total, configuration keys, install()/remove() methods, language files, file placement, version differences, Apps architecture
- [Hook System](references/hook-system.md) -- Site hooks, action hooks, hook registration, catalog vs admin hooks, migration from direct file editing to hooks

