This project is not covered by Drupal’s security advisory policy.

Synchronizes product prices and stock levels from a [Clover POS](https://www.clover.com)
account to Drupal Commerce product variations using the Clover REST API v3.

Features

  • **Price sync** — converts Clover item prices (stored in cents) to your store currency and updates Commerce product variation prices automatically.
  • **Stock sync** — reads Clover item stock levels and updates Commerce stock, with native support for the [Commerce Stock](https://www.drupal.org/project/commerce_stock) module (3.x) and a plain integer field fallback.
  • - **Cron sync** — runs on a configurable schedule (every 15 minutes up to once per day).
  • - **Real-time webhooks** — optional Clover webhook endpoint (`/clover-sync/webhook`) for instant updates when an item changes in Clover.
  • - **Manual sync** — one-click sync trigger from the admin settings page.
  • - **Rate-limit handling** — automatic 750 ms paging delay and exponential backoff retry on Clover 429 responses, safe for large catalogues.
  • - **SKU-based matching** — items are matched by SKU between Clover and
  • Drupal Commerce; unmatched items are skipped silently.

Requirements

  • Drupal 10.2 or 11
  • [Drupal Commerce](https://www.drupal.org/project/commerce) 3.x
  • (`commerce_product`, `commerce_price`)
  • A Clover merchant account with an API token (see [Configuration](#configuration) below)
  • - PHP 8.1 or higher

Optional

[Commerce Stock](https://www.drupal.org/project/commerce_stock) 3.x —
when installed, stock is managed via the transaction API. Without it, the
module falls back to a plain integer field on the product variation.

Installation

Install with Composer (recommended):

```bash
composer require drupal/clover_commerce_sync
drush en clover_commerce_sync
```

Or manually:

1. Download and extract the module into `modules/custom/clover_commerce_sync/`.
2. Enable it at **Admin → Extend** or via Drush:
```bash
drush en clover_commerce_sync
drush cr
```

Configuration

1. Get your Clover API credentials

**Merchant ID**

Log in to your Clover dashboard at [www.clover.com/dashboard](https://www.clover.com/dashboard).
Go to **Settings → Business Information**. Your alphanumeric Merchant ID
(e.g. `FB923TN9SW3X1`) is shown there. Do not use the numeric MID shown in
some sections — the REST API requires the alphanumeric form.

**API Token**

1. In the Clover dashboard, click the **Settings** icon (top right).
2. Type **API** in the settings search bar and select **API Tokens**.
3. Click **Create new token**, give it a name (e.g. "Drupal Sync"), and
enable the **Inventory → Read** permission.
4. Click **Create Token** and copy the token immediately — it is only shown once.

2. Configure the module

Go to **Commerce → Clover Sync** (`/admin/config/commerce/clover-sync`) and fill in:

| Field | Value |
|---|---|
| Merchant ID | Your alphanumeric Clover Merchant ID |
| API Access Token | The token you just created |
| Environment | Production (or Sandbox for testing) |
| Currency Code | Your store currency (e.g. `USD`) |
| Cron Sync Interval | How often cron will sync |
| Sync prices | Check to update prices |
| Sync stock levels | Check to update stock |
| Stock Field (fallback) | Machine name of the integer field on your product variation (only used without Commerce Stock module) |

3. Match SKUs

Every Clover item you want to sync **must have a SKU set in Clover** that
exactly matches the SKU on the corresponding Drupal Commerce product variation.
Items without a matching SKU are silently skipped.

4. Test the sync

Click **Run sync now** on the settings page. Check **Admin → Reports →
Recent log messages** for sync results.

5. Real-time webhook (optional)

Register the following URL in your Clover developer app's webhook settings:

```
https://yoursite.com/clover-sync/webhook
```

Clover will POST to this endpoint whenever an item changes, triggering an
immediate targeted sync. You can optionally set a **Webhook Verification
Secret** to validate incoming requests.

Troubleshooting

**401 Unauthorized**
Your API token is invalid or expired, or you are using the numeric MID
instead of the alphanumeric Merchant ID. Re-check both values.

**429 Too Many Requests**
Clover's rate limit was hit. The module retries automatically with
exponential backoff (up to 3 attempts). For very large catalogues, reduce
the cron sync interval to spread load over time.

**Items are not syncing**
Confirm that the Clover item has a SKU and that the same SKU exists on the
Drupal Commerce product variation. SKU matching is case-sensitive.

**500 error on cache clear (PHP 8.4)**
Ensure you are running the latest version of this module. Earlier versions
had a constructor property promotion conflict with `ControllerBase` that
was fixed in 1.0.1.

**Stock not updating**
If Commerce Stock module is installed, stock is updated via transactions —
check the stock transaction log. If it is not installed, confirm the integer
field name in the **Stock Field** setting matches the field on your product
variation type.

## How it works

1. On cron (or manual trigger), the module calls
`GET /v3/merchants/{mId}/items?expand=itemStock` with pagination.
2. For each item with a SKU, it looks up the matching Commerce product
variation by SKU.
3. If **Sync prices** is enabled, it converts the Clover price from cents to
a decimal and calls `ProductVariation::setPrice()`.
4. If **Sync stock** is enabled and Commerce Stock is present, it calculates
the delta between the current stock level and the Clover quantity and
creates a `STOCK_IN` transaction. Without Commerce Stock, it sets the
integer field directly.
5. Only changed variations are saved, minimizing database writes.

Maintainers

https://xvert.com

Project information

  • caution Minimally maintained
    Maintainers monitor issues, but fast responses are not guaranteed.
  • caution Maintenance fixes only
    Considered feature-complete by its maintainers.
  • Project categories: E-commerce
  • Created by mtnmn on , updated
  • shield alertThis project is not covered by the security advisory policy.
    Use at your own risk! It may have publicly disclosed vulnerabilities.

Releases