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
Project information
Minimally maintained
Maintainers monitor issues, but fast responses are not guaranteed.Maintenance fixes only
Considered feature-complete by its maintainers.- Project categories: E-commerce
- Created by mtnmn on , updated
This project is not covered by the security advisory policy.
Use at your own risk! It may have publicly disclosed vulnerabilities.
