Drupal is a registered trademark of Dries Buytaert
External Authentication Module externalauth crossed 100,000 active installs. LocalGov News 2.5.4 Minor update available for module localgov_news (2.5.4). LocalGov Guides 2.2.5 Minor update available for module localgov_guides (2.2.5). LocalGov Step-by-step 2.2.5 Minor update available for module localgov_step_by_step (2.2.5). LocalGov Subsites 2.6.2 Minor update available for module localgov_subsites (2.6.2). LocalGov Blogs 1.1.3 Minor update available for module localgov_blogs (1.1.3). LocalGov Publications 1.1.5 Minor update available for module localgov_publications (1.1.5). ConsentX Cookie Consent 1.0.1 Minor update available for module consentx (1.0.1). Varbase Editor 10.1.5 Minor update available for module varbase_editor (10.1.5). S3 File System 8.x-3.11 Module s3fs updated after 6 months of inactivity (8.x-3.11).

# Clover Commerce Sync

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

Contributions, bug reports, and pull requests are welcome.

Activity

Total releases
1
First release
Jul 2026
Latest release
6 hours ago
Releases (12 mo)
1 ▲ from 0
Maintenance
Active

Releases

Version Type Release date
1.0.x-dev Dev Jul 21, 2026