CatCode Order Sync with SalesDrive for WooCommerce
SalesDrive Sync for WooCommerce — send WooCommerce orders to SalesDrive CRM (retries, HPOS, encrypted API key, resend metabox).
Install
This is the repository archive. It installs, but the folder name will carry the branch suffix and updates will not flow.
Install straight from GitHub with WP-CLI:
wp plugin install https://github.com/catcodestudio/wp-salesdrive-sync/archive/refs/heads/main.zipSends every WooCommerce order to SalesDrive as a lead: at checkout or on a status change, with de-duplication, retries and an event log.
Description
SalesDrive is a third-party product; this is an independent integration, not affiliated with or endorsed by SalesDrive.
The plugin connects WooCommerce to your SalesDrive account through its order handler and JSON API. Every new order in your shop is created in SalesDrive as a lead with the buyer, the line items, the shipping cost and a comment carrying the delivery address, the payment method and the paid/unpaid mark.
Features
- Sends the order right after checkout (classic checkout and Checkout Blocks) or when it enters one of the statuses you choose
- De-duplication: the SalesDrive order id is stored in the order meta, and a database-level lock keeps two parallel hooks from creating the lead twice
- After a timeout the plugin asks SalesDrive whether the lead is already there (by
externalId) before repeating the attempt — the order handler itself does not deduplicate - Line items are sent with name, SKU, price and quantity; the shipping cost goes to
shipping_costs(optional) - Payment mark: for orders paid online a "Paid online" line is added to the lead comment (optional)
- Orders in a currency other than UAH carry the currency code in the comment — the order handler has no currency field
- Automatic retries on failure: 3 attempts with 5 min / 30 min / 2 h pauses (WP-Cron)
- Metabox on the order screen: sync status, SalesDrive ID, "Resend" button (an order already in the CRM is updated instead of duplicated)
- "Test connection" button on the settings page
- Event log with the last sync attempts, their HTTP status and error text
- The API key is encrypted at rest (libsodium, with an HMAC fallback)
- Buyer phone numbers are normalised to E.164 (+380…)
- HPOS-compatible (custom order tables) — order data is read and written through the WooCommerce CRUD only
cc_salesdrive_order_payloadfilter andcc_salesdrive_order_sentaction for site-specific tweaks
Requirements
- WooCommerce 6.0 or newer
- PHP 7.4 or newer
- A SalesDrive account domain (e.g. yourshop.salesdrive.me) and an API key on the order-base level with the "Orders: add" right ("Orders: read" is optional but recommended, see the FAQ)
How it works
- A customer places an order in your shop.
- The plugin builds the payload (buyer, line items, shipping, comment) and sends
POST /handler/to your SalesDrive domain with the key in theX-Api-Keyheader. - SalesDrive answers
{"success":true,"data":{"orderId":N}}— the id is stored in the order meta as_cc_salesdrive_order_id. - If SalesDrive is unreachable the attempt is repeated automatically (up to 3 times).
- Your manager sees the status and the id in the order metabox and in the log.
Installation
- Upload the plugin folder to
/wp-content/plugins/, or install the zip from Plugins → Add New → Upload. - Activate the plugin.
- Go to WooCommerce → SalesDrive Sync, enter your account domain and API key.
- Press "Test connection", pick the trigger statuses and save.
Frequently Asked Questions
Where do I get the API key?
In your SalesDrive account: Settings → General settings and integrations → Other services → API → API keys. Create a key on the order-base level with the "Orders: add" right. The key is kept in the WordPress database in encrypted form.
Why should the key also have the "Orders: read" right?
Because the SalesDrive order handler does not deduplicate: posting the same externalId twice creates two leads. If a send times out, the plugin cannot know whether the lead was created. With read access it looks the order up by externalId before retrying and adopts the existing id instead of sending again. Without it the order is flagged in the metabox so you can check the CRM yourself.
Can the same order end up in the CRM twice?
The plugin stores the SalesDrive id in the order meta and takes a database lock before sending, so parallel hooks (checkout, status change, payment callback) cannot both create it. The remaining case — a request that never gets an answer — is handled by the externalId lookup described above, or flagged as no_response when the key may not read orders.
What does the "Resend" button do?
If the order is not in SalesDrive yet, it creates the lead (POST /handler/). If it is already there, it updates it (POST /api/order/update/) with the current buyer, items, shipping and comment.
In which currency are the amounts sent?
In the order currency, as plain numbers: the SalesDrive order handler has no currency field, so the amounts land in whatever currency your SalesDrive account uses. For orders in a currency other than UAH the plugin adds the currency code to the lead comment so the manager is not misled.
What happens when I delete the plugin?
Deleting (not just deactivating) removes the plugin options and the log table. The SalesDrive ids stored on the orders are kept on purpose: they are what stops a reinstall from creating a second copy of an old order in the CRM.
External services
This plugin connects to the SalesDrive API on your own account domain (https://<your-account>.salesdrive.me), a third-party CRM service. The connection is the whole purpose of the plugin: it creates and updates your WooCommerce orders inside your own SalesDrive account.
What is sent and when:
POST /handler/— when a customer places an order, or when the order enters one of the statuses you selected as a trigger. Retried up to 3 times if SalesDrive is unavailable.POST /api/order/update/— when you press "Resend" in the order metabox for an order that already exists in SalesDrive.GET /api/order/list/— only after an attempt that got no response, to check byexternalIdwhether the lead already exists before retrying.GET /api/statuses/— only when you press "Test connection" on the settings page.
Every request carries your SalesDrive API key in the X-Api-Key header. The order data sent is: the WooCommerce order id as externalId, the shop host, the line items (name, SKU, price, quantity), the shipping method and its cost, the delivery city and address, the payment method title and whether the order is paid, the customer note, and the buyer's first and last name, e-mail address and phone number as entered at checkout.
No data is sent to any other service, and nothing about your visitors, site or administrators is sent beyond the order data listed above. Nothing is sent until you enter your SalesDrive domain and API key: without them the plugin makes no external requests.
This service is provided by SalesDrive: terms of service, privacy policy.
Screenshots
- Settings: account domain, API key, trigger statuses
- Sync log with the last attempts
- SalesDrive metabox on the WooCommerce order with the resend button
Changelog
0.2.0
- Renamed the plugin to "CatCode Order Sync with SalesDrive for WooCommerce" (new slug and text domain). Options, order meta and the log table keep their names, so nothing has to be migrated.
- Fixed: the "Resend" button in the order metabox never worked. The metabox drew its own
<form>inside the WooCommerce order form, and browsers drop a nested form — the click submitted the order form instead. It is a nonced link now, and the result is shown as an admin notice. - Fixed: the guard against a double send was a transient, i.e. a read-then-write — two parallel hooks could both pass it and create the lead in SalesDrive twice. It is now a database-level lock, and the order is re-read past the HPOS order cache before the final check.
- Fixed: uninstalling the plugin left the sync log table in the database forever. It is dropped now; the per-order SalesDrive ids are kept on purpose as the anti-duplicate guard.
- Fixed: the paid-order mark reached the CRM with an HTML entity instead of the currency sign.
- Added: after an attempt that gets no HTTP response the plugin looks the order up by
externalId(GET /api/order/list/) and adopts the existing lead instead of creating a second one; if the key may not read orders, the order is flagged in the metabox instead. - Added: orders in a currency other than UAH carry the currency code in the lead comment — the order handler has no currency field.
- Admin styles are now enqueued through a registered handle instead of raw `