SAP Business One is one of the most widely used ERPs for mid-market businesses. Connecting it to WooCommerce creates a powerful combination: SAP’s robust back-office capabilities paired with WooCommerce’s flexible ecommerce frontend. But the integration is not trivial, and I have seen enough of these projects go sideways to be blunt about where the risk actually lives. It is almost never in the WooCommerce half. It is in the mapping, the session handling, and the assumptions you make about the SAP side before you have seen the client’s real data. Here is how I would build it.
Why SAP + WooCommerce?
Companies running SAP B1 that launch or migrate their ecommerce to WooCommerce typically need:
- Inventory synced in real-time across retail and online channels
- Orders from WooCommerce automatically created as sales orders in SAP
- Customer data unified across both systems
- Product catalog managed in SAP, displayed in WooCommerce
- Pricing rules (volume discounts, customer-specific) controlled by SAP
Architecture: The Middleware Approach
Never connect WooCommerce directly to SAP’s database. SAP B1 exposes a Service Layer (REST-like API) that’s the proper integration point.
WooCommerce REST API <--> Middleware (Node.js/Python) <--> SAP Service Layer
Message Queue
Error Handling
& Audit Log
The middleware sits between both systems, handling:
- Data transformation (SAP’s field names to WooCommerce’s schema)
- Rate limiting and batching
- Error recovery and retry logic
- Logging and monitoring
SAP Service Layer Basics
// Authenticate with SAP B1 Service Layer
const login = await fetch('https://sap-server:50000/b1s/v1/Login', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
CompanyDB: 'YOUR_DB',
UserName: 'manager',
Password: 'password'
})
});
// Session cookie for subsequent requests
const sessionId = login.headers.get('set-cookie');
// Fetch items (products)
const items = await fetch('https://sap-server:50000/b1s/v1/Items?$select=ItemCode,ItemName,QuantityOnStock&$filter=SalesItem eq \'Y\'', {
headers: { 'Cookie': sessionId }
});
Data Mapping
This is where most integrations break down. SAP and WooCommerce have fundamentally different data models.
I learned to respect the mapping table the hard way, and not on the web. In the late ’90s I built multi-language CD-ROM projects — the kind where one master source had to feed six languages onto a disc that could not be patched after it shipped. You kept one source of truth and transformed it into every target, and the discipline was absolute: get a field mapping wrong and there was no hotfix, just a coaster with your name on it. SAP field validation has that same unforgiving temperament. It will reject a sales order for a unit-of-measure mismatch you did not know existed, exactly the way a strict character encoding used to blow up a German string on a disc mastered for an English machine. The lesson carried over intact: the mapping table is the project. Everything else is plumbing around it. Build the table first, on paper, against the client’s real records, before you write a line of sync code.
Products
| SAP B1 Field | WooCommerce Field | Notes |
|---|---|---|
| ItemCode | sku | Primary identifier |
| ItemName | name | |
| QuantityOnStock | stock_quantity | Sum across warehouses |
| ItemPrices (Price List) | regular_price | Multiple price lists in SAP |
| SalesItem (Y/N) | status | Y = publish, N = draft |
| Picture | images[0].src | SAP stores path, needs URL conversion |
| ItemGroup | categories | Map SAP groups to WC categories |
Orders
| WooCommerce Field | SAP B1 Object | Notes |
|---|---|---|
| order.id | DocEntry (ref) | Store WC order ID in SAP’s remarks |
| line_items | DocumentLines | Map by SKU |
| billing address | AddressExtension | BillTo address |
| shipping address | AddressExtension | ShipTo address |
| customer email | BusinessPartner | Match or create BP |
| payment_method | Payment Terms | Map WC gateway to SAP terms |
Customers
| WooCommerce Field | SAP B1 Field | Notes |
|---|---|---|
| EmailAddress | Unique identifier | |
| first_name + last_name | CardName | Concatenate |
| billing.company | CardName | If B2B |
| billing.address_1 | Addresses | Address object in SAP |
| — | CardCode | Auto-generated in SAP |
Sync Flows
Product Sync (SAP → WooCommerce)
Frequency: Every 5 minutes or on-change webhook
- Query SAP for items modified since last sync
- For each item, check if SKU exists in WooCommerce
- If exists: update stock, price, and status
- If new: create product in WooCommerce with full details
- Log the sync result
Critical consideration: SAP’s price lists support customer-group-specific pricing. Map SAP price lists to WooCommerce’s role-based pricing plugins or custom meta fields.
Order Sync (WooCommerce → SAP)
Trigger: WooCommerce webhook on order.created
- Receive webhook payload
- Find or create BusinessPartner in SAP (match by email)
- Map line items to SAP ItemCodes (by SKU)
- Create Sales Order in SAP
- Store SAP DocEntry in WooCommerce order meta
- Update WooCommerce order note: “Synced to SAP: SO-{DocEntry}”
Inventory Sync (SAP → WooCommerce)
Trigger: SAP UDF or addon fires on stock change, or poll every 60 seconds
- Get stock levels from SAP (all warehouses or specific ones)
- Calculate available-to-sell:
OnHand - Committed - Update WooCommerce via batch endpoint
- Handle multi-warehouse: sum or pick specific warehouse
Error Handling
SAP integrations are particularly error-prone because:
- SAP Service Layer sessions expire after 30 minutes of inactivity
- SAP field validation is strict (wrong UoM, missing required fields = rejection)
- Network between your middleware and SAP server may be unreliable
Retry strategy:
async function sapRequest(endpoint, options, retries = 3) {
for (let i = 0; i < retries; i++) {
try {
await ensureSession(); // Re-login if session expired
const response = await fetch(${SAP_URL}${endpoint}, options);
if (response.status === 401) {
await login(); // Session expired
continue;
}
return await response.json();
} catch (error) {
if (i === retries - 1) throw error;
await sleep(Math.pow(2, i) * 1000);
}
}
}
Lessons from Production
- Always use SAP’s Service Layer, never direct DB queries. SAP’s business logic lives in the application layer. Bypassing it will corrupt your data.
- Handle SAP’s session management carefully. The Service Layer has a concurrent session limit. Pool and reuse sessions.
- Test with SAP’s production-like data. SAP demo databases have simple structures. Real customer SAP instances have custom fields, user-defined tables, and approval workflows that break naive integrations.
- Plan for SAP upgrades. SAP B1 updates can change Service Layer behavior. Version-lock your integration and test after each SAP update.
- Monitor SAP license usage. Each Service Layer session consumes a SAP license. Confirm with the client that their license supports integration sessions.
Build vs. Buy: How I Actually Decide
Clients always ask whether they can skip the middleware and buy an off-the-shelf connector. My answer is a decision, not a survey, and it comes down to three questions.
- How custom is the SAP instance? If the client runs close to a stock SAP B1 configuration — standard items, one or two price lists, a single warehouse — a packaged connector may genuinely be enough, and I will tell them to buy it. The moment there are user-defined fields, approval workflows, or UDTs feeding business logic, packaged connectors start silently dropping data, and silent data loss between an ERP and a storefront is the worst failure mode there is.
- Who owns it at 2 a.m.? A connector you buy is a black box when a sync fails during a sale. Middleware you own has logs you can read and a retry queue you can replay. For any store where a stalled order sync means real money, I want the audit log in the diagram above to be mine.
- Is the price model per-order? Several connectors bill per synced transaction. On a low-margin, high-volume store that math turns ugly fast. Model it against a busy month, not an average one.
My rule of thumb: buy for a near-stock SAP and a modest catalogue; build (or commission) middleware the moment the SAP side carries real customisation. The engineering cost of middleware is a one-time expense. Corrupted business-partner records are a recurring one.
Conclusion
SAP-WooCommerce integration is a middleware problem, not a plugin problem. Off-the-shelf connectors exist but rarely handle the complexity of real SAP implementations with custom fields, multiple price lists, and warehouse configurations. Invest in proper middleware architecture, comprehensive data mapping, and robust error handling. The payoff — automated order flow, real-time inventory, and unified customer data — is worth the engineering investment.
Last modified: August 2, 2026
United States / English
Slovensko / Slovenčina
Canada / Français
Türkiye / Türkçe