Product Sync : Woo-commerce
Step 1: Enable Auto-Import in Eshopbox
When a seller toggle on the auto-import of products , and configure the below settings-
Map the tax classes of Woocommerce with those of Eshopbox. You can also select the default tax code for your products. If the tax code is not the same for all products, then leave it blank.
The mapped tax classes will be saved in DB.
The HSN code is not a default field saved with the WooCommerce product catalog. If seller has selected the HSN code attribute while creating a product then will mention the same here. If there are no attributes, can select the default HSN code of the products. If the HSN code is not the same for all products, then leave it blank
Once the configurations are saved will register webhook for products.
Create Webhook URL:
POST https://woo-casually-quality-runaway.wpcomstaging.com/wp-json/wc/v3/webhooks
Request Body:
{
"name": "Product created/Product updated/Product deleted",
"topic": "product.created/product.updated/product.deleted",
"delivery_url": "https://default-dot-esb-integration-engine-staging.appspot.com/_ah/api/esb/v3/woocommerce-productwebhook/{connectionId}"
}
Whenever event will be triggered on the delivery URL:
The Woocommerce catalog comprises four types of products, out of which simple, variable and bundle products are synced in the Eshopbox catalog. The products in Woocommerce have three publishing status, namely Draft, Pending Review, and Published. All products, regardless of their status, will be pulled into the catalog.
{
"id": 66,
"name": "New-ArrivalBag",
"slug": "new-arrivalbag",
"permalink": "https://woo-casually-quality-runaway.wpcomstaging.com/product/new-arrivalbag/",
"date_created": "2023-12-06T20:02:30",
"date_created_gmt": "2023-12-06T14:32:30",
"date_modified": "2023-12-06T20:02:30",
"date_modified_gmt": "2023-12-06T14:32:30",
"type": "simple",
"status": "publish",
"featured": false,
"catalog_visibility": "visible",
"description": "\u003cp\u003e\u003cimg class\u003d\"alignnone size-medium wp-image-67\" src\u003d\"https://woo-casually-quality-runaway.wpcomstaging.com/wp-content/uploads/2023/12/fashionbag-300x300.jpg\" alt\u003d\"\" width\u003d\"300\" height\u003d\"300\" /\u003e\u003c/p\u003e\n",
"short_description": "\u003cp\u003eNew fashionable bags in store\u003cbr /\u003e\n[contact-form]\u003c/p\u003e\n",
"sku": "Newbag",
"price": "1800",
"regular_price": "1800",
"sale_price": "",
"on_sale": false,
"purchasable": true,
"total_sales": 0,
"virtual": false,
"downloadable": false,
"downloads": [],
"download_limit": -1,
"download_expiry": -1,
"external_url": "",
"button_text": "",
"tax_status": "taxable",
"tax_class": "",
"manage_stock": false,
"backorders": "no",
"backorders_allowed": false,
"backordered": false,
"sold_individually": false,
"weight": "0.5",
"dimensions": {
"length": "12",
"width": "13",
"height": "14"
},
"shipping_required": true,
"shipping_taxable": true,
"shipping_class": "",
"shipping_class_id": 0,
"reviews_allowed": true,
"average_rating": "0.00",
"rating_count": 0,
"upsell_ids": [],
"cross_sell_ids": [],
"parent_id": 0,
"purchase_note": "",
"categories": [
{
"id": 1375,
"name": "Women",
"slug": "women"
}
],
"tags": [],
"images": [
{
"id": 67,
"date_created": "2023-12-07T01:30:00",
"date_created_gmt": "2023-12-06T14:30:00",
"date_modified": "2023-12-07T01:30:00",
"date_modified_gmt": "2023-12-06T14:30:00",
"src": "https://woo-casually-quality-runaway.wpcomstaging.com/wp-content/uploads/2023/12/fashionbag.jpg",
"name": "fashionbag",
"alt": ""
}
],
"attributes": [],
"default_attributes": [],
"variations": [],
"grouped_products": [],
"menu_order": 0,
"price_html": "\u003cspan class\u003d\"woocommerce-Price-amount amount\"\u003e\u003cbdi\u003e\u003cspan class\u003d\"woocommerce-Price-currencySymbol\"\u003e\u0026#36;\u003c/span\u003e1,800.00\u003c/bdi\u003e\u003c/span\u003e",
"related_ids": [
27,
25,
26,
24
],
"meta_data": [
{
"id": 346,
"key": "_wpcom_is_markdown",
"value": "1"
},
{
"id": 347,
"key": "_last_editor_used_jetpack",
"value": "classic-editor"
},
{
"id": 355,
"key": "_product_addons",
"value": []
},
{
"id": 356,
"key": "_product_addons_exclude_global",
"value": "0"
},
{
"id": 372,
"key": "group_of_quantity",
"value": ""
},
{
"id": 373,
"key": "minimum_allowed_quantity",
"value": ""
},
{
"id": 374,
"key": "maximum_allowed_quantity",
"value": ""
},
{
"id": 375,
"key": "minmax_do_not_count",
"value": "no"
},
{
"id": 376,
"key": "minmax_cart_exclude",
"value": "no"
},
{
"id": 377,
"key": "minmax_category_group_of_exclude",
"value": "no"
},
{
"id": 385,
"key": "_wpas_done_all",
"value": "1"
}
],
"stock_status": "instock",
"has_options": false,
"post_password": "",
"bundled_by": [],
"bundle_stock_status": "instock",
"bundle_virtual": false,
"bundle_layout": "",
"bundle_add_to_cart_form_location": "",
"bundle_editable_in_cart": false,
"bundle_sold_individually_context": "",
"bundle_item_grouping": "",
"bundle_min_size": "",
"bundle_max_size": "",
"bundle_price": [],
"bundled_items": [],
"bundle_sell_ids": [],
"jetpack_publicize_connections": [],
"jetpack_sharing_enabled": true,
"jetpack_likes_enabled": true,
"brands": [],
"_links": {
"self": [
{
"href": "https://woo-casually-quality-runaway.wpcomstaging.com/wp-json/wc/v3/products/66"
}
],
"collection": [
{
"href": "https://woo-casually-quality-runaway.wpcomstaging.com/wp-json/wc/v3/products"
}
]
}
}
We will log the response received and push it in taskqueue, their will be a taskqueue listener in default service which will process and pass it to pubsub topic.
“listener/woocommerceproducts”
The delivery URL : https://default-dot-esb-integration-engine-staging.appspot.com/_ah/api/esb/v3/woocommerce-productwebhook/connectionId
has parameter connectionId actual identifier of the connection for which you want to receive product import data.
We will get the connectionId from the endpoint to fetch the authentication token details and also against which account, we have to create a product.
Will execute the below query to fetch the connections details againts which we have received an event
SELECT
ie_appinstall_connection.id AS connectionId,
ie_appinstall_connection.inputFields,
ie_app_automation_steps.id AS appAutomationStepId,
ie_app_automation_steps.appId,
ie_app_automation_steps_config.isActive,
ie_app_automation_steps_config.latestSyncTimeStamp AS latestSyncTimeStamp,
ie_appinstall_connection.isActive AS appIsActive,
ie_app_automation_steps.otherDetails
FROM
ie_appinstall_connection
LEFT JOIN
ie_app_installation ON ie_app_installation.appInstallationId = ie_appinstall_connection.appInstallationId
LEFT JOIN
ie_app ON ie_app.appId = ie_app_installation.appId
LEFT JOIN
ie_app_automation_steps ON ie_app_automation_steps.appId = ie_app.appId
LEFT JOIN
ie_app_automation_steps_config ON ie_app_automation_steps_config.connectionId = ie_appinstall_connection.id
AND ie_app_automation_steps_config.appAutomationStepId = ie_app_automation_steps.id
WHERE
ie_appinstall_connection.id IN (:connectionId)
AND ie_app_automation_steps_config.isActive = '1';
for that connection run the below query to fetch the channel Data
Fetches channel data from cache, if not in cache it fetches data from Database.
.String cacheKey = connection_channeldata + connectionId;
SELECT accounts.account_slug AS accountSlug,
channels.connectionId AS connectionId,
channels.externalChannelId AS externalChannelId,
external_wms_channels.locationId AS locationId,
warehouses.externalWarehouseId AS externalWareHouseId
FROM channels
LEFT JOIN external_wms_channels ON channels.id = external_wms_channels.channel_id
LEFT JOIN warehouses ON warehouses.id = external_wms_channels.warehouse_id
LEFT JOIN accounts ON channels.account_id = accounts.id
LEFT JOIN channel_account_mapping ON channel_account_mapping.external_wms_channel_id = external_wms_channels.id
WHERE channels.connectionId = :connectionId
AND channel_account_mapping.enrollmentStatus = 'ACTIVE';
Channel connection map object:
{
"channelData": {
"integrationType": "",
"externalChannelId": " ",
"accountSlug": " ",
"connectionId": " ",
"isActive": "active",
"inputFields": {
"consumer_key": "harshitaeshop",
"consumer_secret": "harshita@123"
}
"otherDetails":
{
"taxCode" : {
"WOO_CLASS1":"ESBHH1",
"WOO_CLASS2":"ESBHH1",
"WOO_CLASS3":"ESBHH2"
},
}
}
}
}
We will push the channel connection data in the middlelayer along with product details received from webhook event and create products in WMS.
Before creating product in Eshopbox we have to check that if attributes.variation= true and variation list is not empty then call the API for each variations.
Variant cases:
If in products response we get key type=”variable” and also “attributes.variations” is “true” then, iterate through each variations and fetch the product details for each
"variations": [
64,
63,
62
]
Iterate through each variationId and call API for each variantId
variations API for each variationId
https://woo-briskly-different-dinosaur.wpcomstaging.com/wp-json/wc/v3/products/<product_id>/variations/<id>
Response
{
"id": 78,
"date_created": "2023-12-21T11:03:24",
"date_created_gmt": "2023-12-21T05:33:24",
"date_modified": "2023-12-21T11:09:51",
"date_modified_gmt": "2023-12-21T05:39:51",
"description": "",
"permalink": "https://woo-briskly-different-dinosaur.wpcomstaging.com/product/jacket-new/?attribute_size=M",
"sku": "jacketcheckM",
"price": "230",
"regular_price": "234",
"sale_price": "230",
"date_on_sale_from": null,
"date_on_sale_from_gmt": null,
"date_on_sale_to": null,
"date_on_sale_to_gmt": null,
"on_sale": true,
"status": "publish",
"purchasable": true,
"virtual": false,
"downloadable": false,
"downloads": [],
"download_limit": -1,
"download_expiry": -1,
"tax_status": "taxable",
"tax_class": "",
"manage_stock": true,
"stock_quantity": 20,
"stock_status": "instock",
"backorders": "no",
"backorders_allowed": false,
"backordered": false,
"low_stock_amount": null,
"weight": "1",
"dimensions": {
"length": "12",
"width": "13",
"height": "14"
},
"shipping_class": "",
"shipping_class_id": 0,
"image": null,
"attributes": [
{
"id": 0,
"name": "size",
"slug": "size",
"option": "M"
}
],
"menu_order": 1,
"meta_data": [
{
"id": 734,
"key": "_gift_card_template_default_use_image",
"value": "product"
},
{
"id": 740,
"key": "min_max_rules",
"value": "no"
},
{
"id": 741,
"key": "variation_group_of_quantity",
"value": ""
},
{
"id": 742,
"key": "variation_minimum_allowed_quantity",
"value": ""
},
{
"id": 743,
"key": "variation_maximum_allowed_quantity",
"value": ""
},
{
"id": 744,
"key": "variation_minmax_do_not_count",
"value": "no"
},
{
"id": 745,
"key": "variation_minmax_cart_exclude",
"value": "no"
},
{
"id": 746,
"key": "variation_minmax_category_group_of_exclude",
"value": "no"
}
],
"name": "M",
"parent_id": 77,
"_links": {
"self": [
{
"href": "https://woo-briskly-different-dinosaur.wpcomstaging.com/wp-json/wc/v3/products/77/variations/78"
}
],
"collection": [
{
"href": "https://woo-briskly-different-dinosaur.wpcomstaging.com/wp-json/wc/v3/products/77/variations"
}
],
"up": [
{
"href": "https://woo-briskly-different-dinosaur.wpcomstaging.com/wp-json/wc/v3/products/77"
}
]
}
}
In this case for every variant will get unique SKU accordingly will create the product in Eshopbox.
If the SKU is blank, Eshopbox will use the Woocommerce unique ID of the product with the prefix "woo-" as the SKU.
To Create or Update Product -
Step 1 : Check if product exist or not in Eshopbox based on “active” inventoryItem Id from listing table and if it exist then update the Product else Create new Product in Eshopbox.
We will pass the list of itemId to check the status of itemId which we receive
SELECT * FROM listings WHERE itemID = 'SDL490996946' AND channel_id = 2710 AND STATUS = "ACTIVE"
Case 1 : If record exist from the above query, then update the Product in Eshopbox.
Update Product API:
PUT : https://{workspace}.myeshopbox.com/product-engine/api/v1/products/{sku}
Request Body:
{
"imageUrl": "https://cdn.filestackcontent.com/hdYluVCqSADCASjjjcuaeC",
"mrp": 1499.0,
"unitPrice": 799.0,
"hsnCode": "6101112",
"weight": 167.0,
"dimensionLength": 5.0,
"dimensionWidth": 5.0,
"dimensionHeight": 5.0,
"dimensionUnit": "cm"
}'
In case dimensions are updated in Woocommerce, the corresponding dimensions will be updated in Eshopbox, if Weight and dimensions are not verified.
According to Product and Inventory Team,Dimension and product Images are not update when ProductWeightVerification status is in inverification status other then this user is allowed to change the Dimension of the product
Case 2 i) : Else, check product exist in Eshopbox or not,
https://{workspace}.myeshopbox.com/product-engine/api/v1/products
If product exist will get Esin in response and mark the product available in Eshopbox.
{
"87162143127": {
"esin": "0SGAT12SG25F",
"brand": "Kapas Kraft"
},
"623731HSHS": {
"esin": "7HASI6ASDJ8S",
"brand": "Kapas Kraft"
}
}
Mark Product Availability:
POST https://{workspace}.myeshopbox.com/product-engine/api/v2/productListing/bulk
Request Body
{
"channelCode": "CH1234",
"availability": true,
"productMap": [
{
"ESIN": {
"sellersku": "sku",
"productId_variantId/productId": "key"
},
"ESIN1" :{
"sellersku": "sku",
"productId_variantId/productId": "key"
}
}
]
}
We will save the mark available response body and when will create the products will together mark it as avaialble.
ii) : If product does not exist in Eshopbox create product.
Check the configuration of product sync for that connection saved in otherDetails which are fetched already and saved in channel Object.
"otherDetails":
{
"taxCode" : {
"WOO_CLASS1":"ESBHH1",
"WOO_CLASS2":"ESBHH1",
"WOO_CLASS3":"ESBHH2"
},
}
Create a Product:
POST https://{workspace}.myeshopbox.com/product-engine/api/v1/products
Mapping for creating product in WMS
Eshopbox Keys | Woocommerce Identifier |
---|---|
sku |
|
imageurl |
|
description |
|
mrp |
|
dimensionwidth |
|
dimensionheight |
|
dimensionlenght |
|
weight |
|
hsnc | Attribute as selected in app settings |
taxcode |
|
properties.{Woo}_slug |
|
properties.{Woo}_sku |
|
dimensionUnit | cm |
brand |
|
type | base |
Mark Product Availability:
POST https://{workspace}.myeshopbox.com/product-engine/api/v2/productListing/bulk
Request Body
{
"channelCode": "CH1234",
"availability": true,
"productMap": [
{
"ESIN": {
"sellersku": "sku",
"productId_variantId/productId": "key"
},
"ESIN1" :{
"sellersku": "sku",
"productId_variantId/productId": "key"
}
}
]
}
Similarly if there are updates in fields in Eshopbox workspace, corresponding product should be updated in Woocommerce catalog then will update it in Woocommerce whenever will receieve event from of update product from WMS by the productId will update it in woocommerce also.
Update Product API in woocommerce
In request body will mention the fields which need to be updated in woocommerce
PUT https://woo-briskly-different-dinosaur.wpcomstaging.com/wp-json/wc/v3/products/<product_id>
-u consumer_key:consumer_secret
-H "Content-Type: application/json"
-d '
{
"sku": "trouser",
"regular_price": "180"
}
Response
{
"id": 84,
"name": "Trouser",
"slug": "trouser",
"permalink": "https://woo-briskly-different-dinosaur.wpcomstaging.com/product/trouser/",
"date_created": "2023-12-21T18:40:19",
"date_created_gmt": "2023-12-21T13:10:19",
"date_modified": "2023-12-27T15:39:29",
"date_modified_gmt": "2023-12-27T10:09:29",
"type": "simple",
"status": "publish",
"featured": false,
"catalog_visibility": "visible",
"description": "Trouser",
"short_description": "",
"sku": "trouser",
"price": "99",
"regular_price": "180",
"sale_price": "99",
"date_on_sale_from": null,
"date_on_sale_from_gmt": null,
"date_on_sale_to": null,
"date_on_sale_to_gmt": null,
"on_sale": true,
"purchasable": true,
"total_sales": 1,
"virtual": false,
"downloadable": false,
"downloads": [],
"download_limit": -1,
"download_expiry": -1,
"external_url": "",
"button_text": "",
"tax_status": "taxable",
"tax_class": "",
"manage_stock": true,
"stock_quantity": 26,
"backorders": "no",
"backorders_allowed": false,
"backordered": false,
"low_stock_amount": null,
"sold_individually": false,
"weight": "",
"dimensions": {
"length": "",
"width": "",
"height": ""
},
"shipping_required": true,
"shipping_taxable": true,
"shipping_class": "",
"shipping_class_id": 0,
"reviews_allowed": true,
"average_rating": "0",
"rating_count": 0,
"upsell_ids": [],
"cross_sell_ids": [],
"parent_id": 0,
"purchase_note": "",
"categories": [
{
"id": 1374,
"name": "Men",
"slug": "men"
}
],
"tags": [],
"images": [],
"attributes": [],
"default_attributes": [],
"variations": [],
"grouped_products": [],
"menu_order": 0,
"price_html": "<del aria-hidden=\"true\"><span class=\"woocommerce-Price-amount amount\"><bdi><span class=\"woocommerce-Price-currencySymbol\">₹</span>180.00</bdi></span></del> <ins><span class=\"woocommerce-Price-amount amount\"><bdi><span class=\"woocommerce-Price-currencySymbol\">₹</span>99.00</bdi></span></ins>",
"related_ids": [
77,
24,
60,
27,
70
],
"meta_data": [
{
"id": 754,
"key": "_last_editor_used_jetpack",
"value": "classic-editor"
},
{
"id": 758,
"key": "_product_addons",
"value": []
},
{
"id": 759,
"key": "_product_addons_exclude_global",
"value": "0"
},
{
"id": 775,
"key": "group_of_quantity",
"value": ""
},
{
"id": 776,
"key": "minimum_allowed_quantity",
"value": ""
},
{
"id": 777,
"key": "maximum_allowed_quantity",
"value": ""
},
{
"id": 778,
"key": "minmax_do_not_count",
"value": "no"
},
{
"id": 779,
"key": "minmax_cart_exclude",
"value": "no"
},
{
"id": 780,
"key": "minmax_category_group_of_exclude",
"value": "no"
},
{
"id": 785,
"key": "_wpas_done_all",
"value": "1"
},
{
"id": 800,
"key": "_wpcom_is_markdown",
"value": "1"
}
],
"stock_status": "instock",
"has_options": false,
"post_password": "",
"permalink_template": "https://woo-briskly-different-dinosaur.wpcomstaging.com/product/%pagename%/",
"generated_slug": "trouser",
"bundled_by": [],
"bundle_stock_status": "instock",
"bundle_stock_quantity": 26,
"bundle_virtual": false,
"bundle_layout": "",
"bundle_add_to_cart_form_location": "",
"bundle_editable_in_cart": false,
"bundle_sold_individually_context": "",
"bundle_item_grouping": "",
"bundle_min_size": "",
"bundle_max_size": "",
"bundled_items": [],
"bundle_sell_ids": [],
"jetpack_publicize_connections": [],
"jetpack_sharing_enabled": true,
"jetpack_likes_enabled": true,
"brands": [
{
"id": 1377,
"name": "ray",
"slug": "ray"
}
],
"_links": {
"self": [
{
"href": "https://woo-briskly-different-dinosaur.wpcomstaging.com/wp-json/wc/v3/products/84"
}
],
"collection": [
{
"href": "https://woo-briskly-different-dinosaur.wpcomstaging.com/wp-json/wc/v3/products"
}
]
}
}
Delete Product if it is deleted in Woocommerce Mark it unavailble in Eshopbox.
In case we recieved event for delete product through webhook on delete delivery url.
Response:
{
"id": 794,
"name": "Premium Quality",
"slug": "premium-quality-19",
"permalink": "https://example.com/product/premium-quality-19/",
"date_created": "2017-03-23T17:01:14",
"date_created_gmt": "2017-03-23T20:01:14",
"date_modified": "2017-03-23T17:01:14",
"date_modified_gmt": "2017-03-23T20:01:14",
"type": "simple",
"status": "deleted",
"featured": false,
"catalog_visibility": "visible",
"description": "<p>Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo.</p>\n",
"short_description": "<p>Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas.</p>\n",
"sku": "",
"price": "24.54",
"regular_price": "24.54",
"sale_price": "",
"date_on_sale_from": null,
"date_on_sale_from_gmt": null,
"date_on_sale_to": null,
"date_on_sale_to_gmt": null,
"price_html": "<span class=\"woocommerce-Price-amount amount\"><span class=\"woocommerce-Price-currencySymbol\">$</span>24.54</span>",
"on_sale": false,
"purchasable": true,
"total_sales": 0,
"virtual": false,
"downloadable": false,
"downloads": [],
"download_limit": -1,
"download_expiry": -1,
"external_url": "",
"button_text": "",
"tax_status": "taxable",
"tax_class": "",
"manage_stock": false,
"stock_quantity": null,
"stock_status": "instock",
"backorders": "no",
"backorders_allowed": false,
"backordered": false,
"sold_individually": false,
"weight": "",
"dimensions": {
"length": "",
"width": "",
"height": ""
},
"shipping_required": true,
"shipping_taxable": true,
"shipping_class": "",
"shipping_class_id": 0,
"reviews_allowed": true,
"average_rating": "0.00",
"rating_count": 0,
"related_ids": [
479,
387,
22,
463,
396
],
"upsell_ids": [],
"cross_sell_ids": [],
"parent_id": 0,
"purchase_note": "",
"categories": [
{
"id": 9,
"name": "Clothing",
"slug": "clothing"
},
{
"id": 14,
"name": "T-shirts",
"slug": "t-shirts"
}
],
"tags": [],
"images": [
{
"id": 792,
"date_created": "2017-03-23T14:01:13",
"date_created_gmt": "2017-03-23T20:01:13",
"date_modified": "2017-03-23T14:01:13",
"date_modified_gmt": "2017-03-23T20:01:13",
"src": "https://example.com/wp-content/uploads/2017/03/T_2_front-4.jpg",
"name": "",
"alt": ""
},
{
"id": 793,
"date_created": "2017-03-23T14:01:14",
"date_created_gmt": "2017-03-23T20:01:14",
"date_modified": "2017-03-23T14:01:14",
"date_modified_gmt": "2017-03-23T20:01:14",
"src": "https://example.com/wp-content/uploads/2017/03/T_2_back-2.jpg",
"name": "",
"alt": ""
}
],
"attributes": [],
"default_attributes": [],
"variations": [],
"grouped_products": [],
"menu_order": 0,
"meta_data": [],
"_links": {
"self": [
{
"href": "https://example.com/wp-json/wc/v3/products/794"
}
],
"collection": [
{
"href": "https://example.com/wp-json/wc/v3/products"
}
]
}
}
We will pass the data to taskqueue and fetch all the connectionId with channeldata details and pass it in pubsub and delete/mark unavailable the product on Eshopbox.
In case of product is deleted ,mark it as unavailable by calling unavailability API.
Mark Product UnAvailability:
POST https://{workspace}.myeshopbox.com/product-engine/api/v2/productListing
Request Body
{
"channelCode": "CH1234",
"availability": false,
"productMap": [
{
"ESIN": {
"sellersku": "sku",
"productId_variantId/productId": "key"
},
"ESIN1" :{
"sellersku": "sku",
"productId_variantId/productId": "key"
}
}
]
}
CRON to Create Product :
GET https://mayurkarwa123.wpcomstaging.com/wp-json/wc/v3/products?modified_after=2024-03-01T06:00:31
We pass modified_after date in parameter to sync the product if their is any update in that, which will be the latestsynctimestamp in Eshopbox.
Step 1: Cron Endpoint /_ah/api/esb/v1/woocommerce/productupdate/sync
Use-case: It fetches the active connectionIds:
SELECT channels.connectionId FROM channels WHERE integrationType= 18
Fetch the Connections data for all connectionId’s where stepId for product Update Sync is on.Push the data to taskqueue.
SELECT
ie_appinstall_connection.id AS connectionId,
ie_appinstall_connection.accessToken AS accessToken,
ie_appinstall_connection.inputFields,
ie_app_automation_steps.id AS appAutomationStepId,
ie_app_automation_steps.appId,
ie_app_automation_steps_config.isActive,
ie_app_automation_steps_config.otherDetails AS otherDetails,
ie_app_automation_steps_config.latestSyncTimeStamp AS latestSyncTimeStamp,
ie_app.clientId AS appClientId,
ie_app.userName AS appWmsUserName,
ie_appinstall_connection.isActive AS appIsActive
FROM
ie_appinstall_connection
LEFT JOIN
ie_app_installation ON ie_app_installation.appInstallationId = ie_appinstall_connection.appInstallationId
LEFT JOIN
ie_app ON ie_app.appId = ie_app_installation.appId
LEFT JOIN
ie_app_automation_steps ON ie_app_automation_steps.appId = ie_app.appId
LEFT JOIN
ie_app_automation_steps_config ON ie_app_automation_steps_config.connectionId = ie_appinstall_connection.id
AND ie_app_automation_steps_config.appAutomationStepId = ie_app_automation_steps.id
WHERE
ie_appinstall_connection.id IN (:connectionIds)
AND ie_app_automation_steps.id = :stepId
AND ie_app_automation_steps_config.isActive = 1;
Step 3:TaskQueue Listener: /_ah/api/esb/v1/productupdate/cron/listener
For Active connectionId it fetches their respective channel data
for that connection run the below query to fetch the channel Data
Fetches channel data from cache, if not in cache it fetches data from Database.
.String cacheKey = connection_channeldata + connectionId;
SELECT
accounts.account_slug AS accountSlug,
channels.connectionId AS connectionId,
channels.externalChannelId AS externalChannelId,
external_wms_channels.locationId AS locationId,
warehouses.externalWarehouseId AS externalWareHouseId
FROM
channels
LEFT JOIN
external_wms_channels ON channels.id = external_wms_channels.channel_id
LEFT JOIN
warehouses ON warehouses.id = external_wms_channels.warehouse_id
LEFT JOIN
accounts ON channels.account_id = accounts.id
LEFT JOIN
channel_account_mapping ON channel_account_mapping.external_wms_channel_id = external_wms_channels.id
WHERE
channels.connectionId = :connectionId
AND channel_account_mapping.enrollmentStatus = 'ACTIVE';
Push the connectionchannel data in the Taskqueue
Use-case: It listens and prepares woocommerce product update Sync url to fetch product update Details :
Woocommerce URL:
https://mayurkarwa123.wpcomstaging.com/wp-json/wc/v3/products?modified_after=2024-03-01T06:00:31
Response :
Pagination will be applied per page will fetch 10 response until we do not received empty response.
[
{
"id": 18,
"name": "trouser",
"slug": "trouser",
"permalink": "https://mayurkarwa123.wpcomstaging.com/product/trouser/",
"date_created": "2024-01-02T15:44:22",
"date_created_gmt": "2024-01-02T10:14:22",
"date_modified": "2024-03-01T11:49:31",
"date_modified_gmt": "2024-03-01T06:19:31",
"type": "simple",
"status": "publish",
"featured": false,
"catalog_visibility": "visible",
"description": "",
"short_description": "",
"sku": "newtrouser",
"price": "400",
"regular_price": "500",
"sale_price": "400",
"date_on_sale_from": null,
"date_on_sale_from_gmt": null,
"date_on_sale_to": null,
"date_on_sale_to_gmt": null,
"on_sale": true,
"purchasable": true,
"total_sales": 6,
"virtual": false,
"downloadable": false,
"downloads": [],
"download_limit": -1,
"download_expiry": -1,
"external_url": "",
"button_text": "",
"tax_status": "taxable",
"tax_class": "",
"manage_stock": true,
"stock_quantity": 72,
"backorders": "no",
"backorders_allowed": false,
"backordered": false,
"low_stock_amount": null,
"sold_individually": false,
"weight": "",
"dimensions": {
"length": "",
"width": "",
"height": ""
},
"shipping_required": true,
"shipping_taxable": true,
"shipping_class": "",
"shipping_class_id": 0,
"reviews_allowed": true,
"average_rating": "0.00",
"rating_count": 0,
"upsell_ids": [
15
],
"cross_sell_ids": [],
"parent_id": 0,
"purchase_note": "",
"categories": [],
"tags": [],
"images": [],
"attributes": [
{
"id": 0,
"name": "HSN",
"slug": "HSN",
"position": 0,
"visible": true,
"variation": false,
"options": [
"1224"
]
}
],
"default_attributes": [],
"variations": [],
"grouped_products": [],
"menu_order": 0,
"price_html": "<del aria-hidden=\"true\"><span class=\"woocommerce-Price-amount amount\"><bdi><span class=\"woocommerce-Price-currencySymbol\">₹</span>500.00</bdi></span></del> <ins><span class=\"woocommerce-Price-amount amount\"><bdi><span class=\"woocommerce-Price-currencySymbol\">₹</span>400.00</bdi></span></ins>",
"related_ids": [],
"meta_data": [
{
"id": 42,
"key": "_created_via",
"value": "post-new"
},
{
"id": 43,
"key": "_last_editor_used_jetpack",
"value": "classic-editor"
},
{
"id": 66,
"key": "_wpas_done_all",
"value": "1"
}
],
"stock_status": "instock",
"has_options": false,
"post_password": "",
"jetpack_publicize_connections": [],
"jetpack_likes_enabled": true,
"jetpack_sharing_enabled": true,
"jetpack-related-posts": [],
"_links": {
"self": [
{
"href": "https://mayurkarwa123.wpcomstaging.com/wp-json/wc/v3/products/18"
}
],
"collection": [
{
"href": "https://mayurkarwa123.wpcomstaging.com/wp-json/wc/v3/products"
}
]
}
}
]
Before creating product in Eshopbox we have to check that if attributes.variation= true and variation list is not empty then call the API for each variations.
Variant cases:
If in products response we get key type=”variable” and also “attributes.variations” is “true” then, iterate through each variations and fetch the product details for each
"variations": [
64,
63,
62
]
Iterate through each variationId and call API for each variantId
variations API for each variationId
https://woo-briskly-different-dinosaur.wpcomstaging.com/wp-json/wc/v3/products/<product_id>/
To Create or Update Product -
Step 1 : Check if product exist or not in Eshopbox based on “active” inventoryItem Id from listing table and if it exist then update the Product else Create new Product in Eshopbox.
We will pass the list of itemId to check the status of itemId which we receive
SELECT * FROM listings WHERE itemID = 'SDL490996946' AND channel_id = 2710 AND STATUS = "ACTIVE"
Case 1 : if record exist from the above query, then update the Product in Eshopbox.
Update Product API:
PUT : https://{workspace}.myeshopbox.com/product-engine/api/v1/products/{sku}
Request Body:
{
"imageUrl": "https://cdn.filestackcontent.com/hdYluVCqSADCASjjjcuaeC",
"mrp": 1499.0,
"unitPrice": 799.0,
"hsnCode": "6101112",
"weight": 167.0,
"dimensionLength": 5.0,
"dimensionWidth": 5.0,
"dimensionHeight": 5.0,
"dimensionUnit": "cm"
}'
Case
Will get sku from listing table for respective itemId which is ESIN in Workspace.
Will call Get product API with esin.
https://{workspace}.auperator.co/product-engine/api/v1/products?fields=weight_dimension_status&ids=45HY03FRI2B
Response :
{
"45HY03FRI2B": {
"weight_dimension_status": "unverified"
}
}
If weight_dimension_status
= inverification/verified in two status we can not update the weight dimension in such cases will be notified of such a mismatch in the product availability section of dimension
Case 2 : Else,
Case 2 i) : Else, check product exist in Eshopbox or not,
https://{workspace}.myeshopbox.com/product-engine/api/v1/products
If product exist will get Esin in response and mark the product available in Eshopbox.
{
"87162143127": {
"esin": "0SGAT12SG25F",
"brand": "Kapas Kraft"
},
"623731HSHS": {
"esin": "7HASI6ASDJ8S",
"brand": "Kapas Kraft"
}
}
Mark Product Availability:
POST https://{workspace}.myeshopbox.com/product-engine/api/v2/productListing/bulk
Request Body
{
"channelCode": "CH1234",
"availability": true,
"productMap": [
{
"ESIN": {
"sellersku": "sku",
"productId_variantId/productId": "key"
},
"ESIN1" :{
"sellersku": "sku",
"productId_variantId/productId": "key"
}
}
]
}
We will save the mark available response body and when will create the products will together mark it as avaialble.
ii) : If product does not exist in Eshopbox create product.
Check the configuration of product sync for that connection saved in otherDetails which are fetched already and saved in channel Object.
"otherDetails":
{
"taxCode" : {
"WOO_CLASS1":"ESBHH1",
"WOO_CLASS2":"ESBHH1",
"WOO_CLASS3":"ESBHH2"
},
}
Create a Product:
POST https://{workspace}.myeshopbox.com/product-engine/api/v1/products
Mapping for creating product in WMS
Eshopbox Keys | Woocommerce Identifier |
---|---|
sku |
|
imageurl |
In case of variable product, use |
description |
|
mrp |
|
dimensionwidth |
|
dimensionheight |
|
dimensionlenght |
|
weight |
|
hsnc | Attribute as selected in app settings |
taxcode |
|
properties.{Woo}_slug |
|
properties.{Woo}_sku |
|
dimensionUnit | cm |
brand |
|
type | base |
Mark Product Availability:
POST https://{workspace}.myeshopbox.com/product-engine/api/v2/productListing/bulk
Request Body
{
"channelCode": "CH1234",
"availability": true,
"productMap": [
{
"ESIN": {
"sellersku": "sku",
"productId_variantId/productId": "key"
},
"ESIN1" :{
"sellersku": "sku",
"productId_variantId/productId": "key"
}
}
]
}
In case of Delete Cron will mark the product Unavailable in Eshopbox by calling unavailable API.
If grouped products are to be fetched, in case of grouped product :
Grouped Product -
We have option of grouped Product in Woocommerce , In which seller can grouped 2-3 products together and create a product.
when we create order the behvaiour of grouped products -
"line_items": [
{
"id": 12,
"name": "Demo Product 1",
"product_id": 74,
"variation_id": 0,
"quantity": 2,
"tax_class": "",
"subtotal": "800.00",
"subtotal_tax": "0.00",
"total": "800.00",
"total_tax": "0.00",
"taxes": [],
"meta_data": [],
"sku": "groupdemosku",
"price": 400,
"image": {
"id": "75",
"src": "https://i0.wp.com/mayurkarwa123.wpcomstaging.com/wp-content/uploads/2024/03/organicproducts1-1.jpg?fit=500%2C329&ssl=1"
},
"parent_name": null
}
We get line_items in response where we do not get the individual products details.
But if we will be fetching the Grouped Products in Eshopbox then,
API to fetch Grouped Product -
https://mayurkarwa123.wpcomstaging.com/wp-json/wc/v3/products/
If type = grouped
Response :
{
"id": 74,
"name": "Demo Product 1",
"slug": "demo-product-1",
"permalink": "https://mayurkarwa123.wpcomstaging.com/product/demo-product-1/",
"date_created": "2024-03-04T14:31:42",
"date_created_gmt": "2024-03-04T09:01:42",
"date_modified": "2024-03-04T14:31:42",
"date_modified_gmt": "2024-03-04T09:01:42",
"type": "grouped",
"status": "publish",
"featured": false,
"catalog_visibility": "visible",
"description": "",
"short_description": "",
"sku": "groupdemosku",
"price": "400",
"regular_price": "",
"sale_price": "",
"date_on_sale_from": null,
"date_on_sale_from_gmt": null,
"date_on_sale_to": null,
"date_on_sale_to_gmt": null,
"on_sale": true,
"purchasable": false,
"total_sales": 0,
"virtual": false,
"downloadable": false,
"downloads": [],
"download_limit": -1,
"download_expiry": -1,
"external_url": "",
"button_text": "",
"tax_status": "taxable",
"tax_class": "",
"manage_stock": false,
"stock_quantity": null,
"backorders": "no",
"backorders_allowed": false,
"backordered": false,
"low_stock_amount": null,
"sold_individually": false,
"weight": "",
"dimensions": {
"length": "",
"width": "",
"height": ""
},
"shipping_required": true,
"shipping_taxable": true,
"shipping_class": "",
"shipping_class_id": 0,
"reviews_allowed": true,
"average_rating": "0.00",
"rating_count": 0,
"upsell_ids": [],
"cross_sell_ids": [],
"parent_id": 0,
"purchase_note": "",
"categories": [],
"tags": [],
"images": [
{
"id": 75,
"date_created": "2024-03-04T20:01:31",
"date_created_gmt": "2024-03-04T09:01:31",
"date_modified": "2024-03-04T20:01:31",
"date_modified_gmt": "2024-03-04T09:01:31",
"src": "https://i0.wp.com/mayurkarwa123.wpcomstaging.com/wp-content/uploads/2024/03/organicproducts1-1.jpg?fit=500%2C329&ssl=1",
"name": "organicproducts1-1",
"alt": ""
}
],
"attributes": [],
"default_attributes": [],
"variations": [],
"grouped_products": [
18,
37
],
"menu_order": 0,
"price_html": "<span class=\"woocommerce-Price-amount amount\"><bdi><span class=\"woocommerce-Price-currencySymbol\">₹</span>400.00</bdi></span> – <span class=\"woocommerce-Price-amount amount\"><bdi><span class=\"woocommerce-Price-currencySymbol\">₹</span>2,300.00</bdi></span>",
"related_ids": [],
"meta_data": [
{
"id": 329,
"key": "_created_via",
"value": "post-new"
},
{
"id": 330,
"key": "_last_editor_used_jetpack",
"value": "classic-editor"
},
{
"id": 356,
"key": "_wpas_done_all",
"value": "1"
}
],
"stock_status": "instock",
"has_options": false,
"post_password": "",
"jetpack_publicize_connections": [],
"jetpack_likes_enabled": true,
"jetpack_sharing_enabled": true,
"jetpack-related-posts": [],
"_links": {
"self": [
{
"href": "https://mayurkarwa123.wpcomstaging.com/wp-json/wc/v3/products/74"
}
],
"collection": [
{
"href": "https://mayurkarwa123.wpcomstaging.com/wp-json/wc/v3/products"
}
]
}
}
If type = grouped , then will check for key “grouped_products
“ where will get the products which are grouped.
"grouped_products": [
18,
37
]
Product API :
https://mayurkarwa123.wpcomstaging.com/wp-json/wc/v3/products/37
Will call the product API of Woocommerce for each product_id listed in grouped_products ,fetch the product details and will check is it available in Eshopbox if not create the product in Eshopbox.