CLAUDE.md 8.0 KB

Reverb OpenCart Integration

An OpenCart extension that syncs products, stock, prices, orders, and images between an OpenCart store and a Reverb.com marketplace listing.

Project Overview

Type: OpenCart 3.x Extension (with planned OpenCart 4.x compatibility)

Primary Market: Australia (reverb.com/au)

Sync Direction: Bidirectional (OpenCart ↔ Reverb)

Reference Documentation

Requirements

Admin Settings Page

The extension must provide an admin panel (Admin > Extensions > Modules > Reverb) that allows the store owner to:

  • Enter and save their personal Reverb.com API token
  • Select sync direction: One-way (OpenCart → Reverb) or Both-ways (bidirectional)
  • Select which OpenCart categories are eligible for sync
  • Manually trigger a full catalogue sync

Product Page Integration

Each product in the OpenCart admin must show a toggle/checkbox to:

  • Enable or disable syncing that individual product to Reverb
  • Show the Reverb listing ID and a direct link once the product is listed

Sync Scope (Bidirectional)

Field OC → Reverb Reverb → OC
Title / Name
Description
Price
Stock / Qty
Images
Orders

Extension Architecture (OpenCart 3.x)

File Structure

upload/
├── admin/
│   ├── controller/extension/module/reverb/
│   │   └── reverb.php              # Admin settings + manual sync trigger
│   ├── language/en-gb/extension/module/reverb/
│   │   └── reverb.php              # All user-facing strings
│   ├── model/extension/module/reverb/
│   │   └── reverb.php              # DB interactions (token storage, product map)
│   └── view/template/extension/module/reverb/
│       └── reverb.twig             # Admin settings form
├── catalog/
│   └── controller/extension/module/reverb/
│       └── reverb.php              # Webhook endpoint for Reverb callbacks
└── system/
    └── library/reverb/
        ├── ReverbApi.php           # HTTP client wrapping the Reverb REST API
        ├── ProductMapper.php       # Maps OC product fields ↔ Reverb listing fields
        └── OrderMapper.php         # Maps Reverb order payload → OC order format

OCMOD patch file (install.xml) injects the per-product toggle into the product edit page without modifying core files.

The upload folder and install.xml is zipped into a file called reverb.ocmod.zip for installing via the extension installer in opencart admin backend

Database Tables

The extension creates and manages the following tables.

oc_reverb_product_map

Column Type Notes
product_id INT FK to oc_product
reverb_listing_id VARCHAR(64) Reverb's listing ID once synced
sync_enabled TINYINT(1) Per-product on/off toggle
last_synced_at DATETIME Timestamp of last successful sync

oc_reverb_sync_log

Column Type Notes
log_id INT AUTO_INCREMENT
product_id INT
direction ENUM('push','pull')
status ENUM('success','error')
message TEXT Error detail or summary
created_at DATETIME

API token, sync mode, and category whitelist are stored in OpenCart's native oc_setting table via $this->config — no custom config table needed.

Key Design Decisions

  1. API Token storage: Stored via OpenCart's native settings system (oc_setting) with the key prefix module_reverb_. Never stored in a raw custom table.
  2. Per-product toggle: Stored in oc_reverb_product_map.sync_enabled; defaults to 0 (disabled) for all products.
  3. Category filter: Admin selects OpenCart categories; only products in those categories AND with sync_enabled = 1 are synced.
  4. Webhooks vs polling: Use Reverb webhooks for real-time order/listing updates; fall back to a scheduled cURL ping (OpenCart cron or system cron calling catalog/controller/extension/module/reverb/cron) for stock/price polling.
  5. Image sync: Upload OpenCart product images to Reverb via POST /listings/{id}/photos. Only push images OC → Reverb; do not pull images back.

Reverb API Essentials

Base URL: https://api.reverb.com/api/

Required headers on every request:

Authorization: Bearer <token>
Accept-Version: 3.0
Content-Type: application/hal+json

Rate limit: ~100 requests/min on the standard plan — batch operations where possible.

Key endpoints:

Endpoint Method Purpose
/my/listings GET List all existing seller listings
/listings POST Create a new listing
/listings/{id} PUT Update an existing listing
/listings/{id}/end PUT End/delist a listing
/listings/{id}/photos POST Upload a photo to a listing
/my/orders GET Fetch seller orders
/my/orders/{order_number} GET Fetch a single order
/webhooks POST Register a webhook endpoint
/categories/flat GET Get the full Reverb category tree

Sync Flow

OpenCart → Reverb (triggered on product save event or manual sync)

  1. Check product has sync_enabled = 1 AND is in an allowed category.
  2. Map OC product fields to a Reverb listing payload via ProductMapper::toReverb().
  3. If reverb_listing_id exists in the map → PUT /listings/{id}; otherwise → POST /listings and store the returned ID.
  4. Upload any new/changed images via POST /listings/{id}/photos.
  5. Update last_synced_at and log result in oc_reverb_sync_log.

Reverb → OpenCart (webhook or scheduled poll)

  1. Receive webhook POST to catalog/controller/extension/module/reverb/webhook (or poll /my/listings + /my/orders).
  2. For listing updates: look up OC product by reverb_listing_id, update price / stock / description via model.
  3. For new orders: map Reverb order payload to OC order via OrderMapper::toOpenCart(), create via $this->model_checkout_order->addOrder().
  4. Log result.

OpenCart 4.x Compatibility Notes

  • OC 4.x uses PHP namespaces: namespace Opencart\Admin\Controller\Extension\Module;
  • Controllers must extend \Opencart\System\Engine\Controller
  • Template paths and module structure differ from 3.x
  • Planned approach: ship separate 4.x controller files; share system/library/reverb/ classes between both versions (they are framework-agnostic)

Development Guidelines

  • PHP 7.4+ required; PHP 8.1+ preferred
  • Use $this->db->query() and $this->db->escape() for all database access — never raw PDO or unsanitised input
  • All user-visible strings must be defined in the language file, not hardcoded in controllers or templates
  • Wrap all Reverb API calls in try/catch; log errors to oc_reverb_sync_log rather than surfacing raw exceptions to the UI
  • The OCMOD XML file is required for injecting the per-product toggle without modifying core OpenCart files
  • Test against a Reverb sandbox account before connecting a live store