WC Order Sync

Docs

Get up and running in five minutes.

This page covers the install, the wire format, and the signature verification recipe on the receiving side.

1. Install the plugin

Grab the latest wc-order-sync.zip from your account and upload it via Plugins → Add New → Upload Plugin. Activate it.

2. Configure

Go to Settings → WC Order Sync and fill three fields:

  • Remote base URL — the host that will receive the webhook.
  • Shop hostname — the bare hostname of this WooCommerce shop.
  • Shared HMAC secret — 64 hex characters (your endpoint must store the same value).

Click Test connection. A green badge means the secret matches and the channel is ready.

3. Wire format

On every order completion the plugin POSTs JSON to <remote_base_url>/api/woo/order-completed with header X-Woo-Signature: sha256=<hex> where the digest is computed over the raw request body using the shared secret.

POST /api/woo/order-completed HTTP/1.1
Host: api.example.com
Content-Type: application/json
X-Woo-Signature: sha256=4e0f...c1d2

{
  "shop_url": "example-shop.com",
  "order_ref": "wc-10421",
  "amount": "79.00",
  "currency": "EUR",
  "customer_email": "jane@example.com",
  "shipping": {
    "firstName": "Jane",
    "lastName": "Doe",
    "address1": "12 Rue Example",
    "city": "Paris",
    "postalCode": "75002",
    "country": "FR"
  },
  "cart": [ /* line items */ ]
}

4. Verify the signature on your endpoint

Use a constant-time comparison so timing leaks don't reveal partial matches. Below is a Node.js snippet; the same logic works in PHP, Python, Go, or whatever your back-office runs on.

import crypto from 'node:crypto';

function verifyWooSignature(rawBody, header, secret) {
  const expected =
    'sha256=' + crypto
      .createHmac('sha256', secret)
      .update(rawBody, 'utf8')
      .digest('hex');
  const a = Buffer.from(header || '');
  const b = Buffer.from(expected);
  return a.length === b.length && crypto.timingSafeEqual(a, b);
}

5. Idempotence

Each order is dispatched at most once per status transition. The receiving side should treat order_ref as a unique key and return 200 OK for any retry of an already-recorded order.

6. Rotating the secret

Generate a new 64-hex secret on your side, paste it into the plugin settings, click Test connection. The previous secret stops being accepted as soon as you save the new one.