WooCommerce Integration — Technical Reference
026-ecommerce-integration — WooCommerce Adapter
| Field | Detail |
|---|---|
| Module | 026-ecommerce-integration |
| Adapter | WoocommerceAdapter |
| Port | EcommerceProviderPort |
| API Version | wc/v3 |
| Date | March 28, 2026 |
The Biggest Difference from Shopify: No OAuth
This is the most important thing to internalize upfront. WooCommerce does not have an OAuth flow. Authentication is done via pre-generated API keys — a Consumer Key and Consumer Secret — which the client generates through their WordPress admin under WooCommerce → Settings → Advanced → REST API.
This means the connection UX in the PWA will be different: instead of a "Connect" button that redirects to an authorization screen, you need a form where the client pastes their store URL, Consumer Key, and Consumer Secret.
API
The current WooCommerce REST API version is wc/v3. Base URL structure:
https://client-store.com/wp-json/wc/v3/products
https://client-store.com/wp-json/wc/v3/orders
https://client-store.com/wp-json/wc/v3/products/{id}/stock
Authentication over HTTPS uses the Consumer Key as username and Consumer Secret as password via HTTP Basic Auth — this is the simplest and most secure method. Over plain HTTP, OAuth 1.0a is required, but HTTPS should always be required from clients.
⚠️ Prerequisite that will trip clients up: WordPress pretty permalinks must be enabled. Default permalinks will not work with the REST API. This must be in the client onboarding checklist.
Webhooks
Webhooks are configured under WooCommerce → Settings → Advanced → Webhooks. The first time a webhook is saved with Active status, WooCommerce sends a ping to the delivery URL to verify it is reachable.
Each webhook request includes a X-WC-Webhook-Signature header — a base64-encoded HMAC-SHA256 hash of the payload — which the handler uses to verify authenticity. This is equivalent to Shopify's X-Shopify-Hmac-SHA256, so the verification pattern in the adapter is identical.
Topics needed for v1
| WooCommerce Topic | Shopify Equivalent |
|---|---|
order.created | orders/create |
product.updated | — |
product.stock_updated | inventory_levels/update |
⚠️ Retry behavior: WooCommerce disables webhooks automatically after 5 failed delivery retries. Unlike Shopify which retries for 48 hours, WooCommerce stops much sooner. The sync log and BullMQ polling fallback are even more critical here than with Shopify.
Key Differences vs. Shopify
| Shopify | WooCommerce | |
|---|---|---|
| Auth flow | OAuth (redirect) | Manual key entry (form) |
| Connection setup | Automated | Client must generate keys manually |
| Rate limits | 2–4 req/sec (enforced) | Depends on client's hosting — no hard platform limit |
| Webhook retries | 19 retries over 48 hours | 5 retries, then disabled |
| API stability | Versioned, quarterly deprecations | Tied to WordPress/WooCommerce version — clients may run old versions |
| Store URL | myshop.myshopify.com (predictable) | Any custom domain |
| Hosting | Shopify-managed | Self-hosted — server config varies widely |
The Hosting Wildcard: Biggest Operational Risk
With Shopify, every store runs on Shopify's infrastructure. With WooCommerce, clients are self-hosted — some on cheap shared hosting, some on managed WordPress, some on their own VPS. This introduces risks that cannot be controlled from the adapter side:
- FastCGI configurations may not pass Authorization headers correctly. In that case, credentials need to be passed as query string parameters instead of the Authorization header.
- ModSecurity (a common server security module) can block POST and PUT requests, causing silent failures on product pushes.
- Outdated WooCommerce versions may not have
wc/v3available. Clients running WooCommerce below 3.5 need to update first. - Cheap shared hosting providers sometimes throttle outbound webhook delivery, causing delays in order ingestion.
The adapter needs to be defensive: good error messages, a connection test on setup, and detailed sync log entries that surface exactly what failed and why.
Credentials Storage
Unlike Shopify, there is no global app-level secret. Credentials are per-client store and live in the ecommerce_connection table alongside the shop URL. No new Doppler entries are needed — the Consumer Key and Consumer Secret are stored encrypted in the existing connection record, the same way Shopify access tokens are stored.
Webhook Registration — Automate It
The WooCommerce REST API exposes a /webhooks endpoint. Rather than asking clients to manually create webhooks in their WordPress admin, the adapter should register them programmatically immediately after the client saves their credentials. This removes step 6 from the client setup flow entirely and is worth building into v1.
Client Setup Flow
This is more involved than Shopify's 2-minute OAuth flow. Walk clients through it during onboarding.
- In WordPress admin: WooCommerce → Settings → Advanced → REST API → Add Key
- Set permissions to Read/Write
- Copy the Consumer Key and Consumer Secret — they are only shown once
- In FlowPOS PWA → Integraciones → Connect WooCommerce
- Enter the store URL, Consumer Key, and Consumer Secret
- FlowPOS registers the required webhooks automatically via the API
Steps 1–3 require the client to be in their WordPress admin. Steps 4–6 happen entirely inside FlowPOS.
Webhook Signature Verification
The verification logic is identical to Shopify's — only the header name differs:
// Shopify uses: X-Shopify-Hmac-SHA256
// WooCommerce uses: X-WC-Webhook-Signature
import * as crypto from 'crypto';
function verifyWooCommerceWebhook(
payload: Buffer,
signature: string,
secret: string
): boolean {
const hash = crypto
.createHmac('sha256', secret)
.update(payload)
.digest('base64');
return hash === signature;
}
Adapter Implementation Notes
Following the existing EcommerceProviderPort contract, the WoocommerceAdapter maps to wc/v3 endpoints as follows:
| Port Method | WooCommerce Endpoint |
|---|---|
getAuthorizationUrl() | N/A — replaced by credential form in PWA |
exchangeCodeForToken() | N/A — replaced by credential validation on save |
revokeConnection() | Delete registered webhooks via DELETE /wc/v3/webhooks/{id} |
pushProduct() | POST /wc/v3/products or PUT /wc/v3/products/{id} |
updateInventoryLevel() | PUT /wc/v3/products/{id} (stock quantity field) |
pullOrders() | GET /wc/v3/orders?after={since}&status=processing |
acknowledgeOrder() | PUT /wc/v3/orders/{id} → set status to on-hold or processing |
Note: The
getAuthorizationUrlandexchangeCodeForTokenmethods defined in the port are OAuth-specific. For WooCommerce, implement them as no-ops or throw aProviderNotSupportedOperationexception, and handle the credential-based connection flow at the application service layer with a provider-aware branch.
Speckit Command (WooCommerce Adapter)
/speckit.specify Add WooCommerceAdapter to the existing ecommerce integration module (026). Implements EcommerceProviderPort using WooCommerce REST API wc/v3 with Basic Auth (Consumer Key + Consumer Secret). Connection flow is credential-based (no OAuth) — client enters store URL and keys in PWA form. Adapter programmatically registers required webhooks via the WooCommerce REST API on connect, and removes them on disconnect. Covers product push, inventory level sync, order pull, and HMAC-SHA256 webhook verification. Must handle self-hosted environment variability: FastCGI auth header fallback, outdated API version detection, and connection test on credential save. Zero changes to domain layer or application service — only a new infrastructure adapter and a WooCommerce branch in EcommerceProviderFactory.