{"id":362573,"date":"2026-09-04T19:12:48","date_gmt":"2026-09-04T19:12:48","guid":{"rendered":"https:\/\/wordpress.org\/plugins\/cosmetic-wholesale-sync\/"},"modified":"2026-09-04T19:12:33","modified_gmt":"2026-09-04T19:12:33","slug":"cosmetic-wholesale-sync","status":"publish","type":"plugin","link":"https:\/\/wordpress.org\/plugins\/cosmetic-wholesale-sync\/","author":22025808,"comment_status":"closed","ping_status":"closed","template":"","meta":{"version":"1.0.1","stable_tag":"1.0.1","tested":"7.1","requires":"6.0","requires_php":"7.4","requires_plugins":null,"header_name":"Cosmetic Wholesale Sync","header_author":"Cosmetic Wholesale","header_description":"Catalog feed + hourly stock\/price. Paid Woo orders POST to Cosmetic Wholesale (wallet). Images are not imported.","assets_banners_color":"989898","last_updated":"2026-09-04 19:12:33","external_support_url":"","external_repository_url":"","donate_link":"https:\/\/cosmeticwholesale.eu","header_plugin_uri":"","header_author_uri":"https:\/\/cosmeticwholesale.eu","rating":0,"author_block_rating":0,"active_installs":0,"downloads":46,"num_ratings":0,"support_threads":0,"support_threads_resolved":0,"author_block_count":0,"sections":["description","installation","faq","changelog"],"tags":{"1.0.1":{"tag":"1.0.1","author":"juniustech","date":"2026-09-04 19:12:33","revision":3681724}},"upgrade_notice":{"1.0.1":"<p>Stored meta keys were renamed to a longer prefix. Existing orders keep working; no action needed.<\/p>","1.0.0":"<p>First directory release. If you installed an earlier zip as <code>cw-sync<\/code>, deactivate and delete it before installing this one; settings, products and orders are untouched.<\/p>"},"ratings":[],"assets_icons":{"icon-128x128.png":{"filename":"icon-128x128.png","revision":3681724,"resolution":"128x128","location":"assets","locale":"","width":128,"height":128},"icon-256x256.png":{"filename":"icon-256x256.png","revision":3681724,"resolution":"256x256","location":"assets","locale":"","width":256,"height":256}},"assets_banners":{"banner-1544x500.png":{"filename":"banner-1544x500.png","revision":3681724,"resolution":"1544x500","location":"assets","locale":"","width":1544,"height":500},"banner-772x250.png":{"filename":"banner-772x250.png","revision":3681724,"resolution":"772x250","location":"assets","locale":"","width":772,"height":250}},"assets_blueprints":{},"all_blocks":[],"tagged_versions":["1.0.1"],"block_files":[],"assets_screenshots":[],"screenshots":{"1":"Settings: feed URL, token, margin, first import, hourly toggle."}},"plugin_section":[],"plugin_tags":[2777,188934,39071,51032,286],"plugin_category":[45],"plugin_contributors":[268792],"plugin_business_model":[],"class_list":["post-362573","plugin","type-plugin","status-publish","hentry","plugin_tags-catalog","plugin_tags-cosmetics","plugin_tags-dropshipping","plugin_tags-wholesale","plugin_tags-woocommerce","plugin_category-ecommerce","plugin_contributors-juniustech","plugin_committers-juniustech"],"banners":{"banner":"https:\/\/ps.w.org\/cosmetic-wholesale-sync\/assets\/banner-772x250.png?rev=3681724","banner_2x":"https:\/\/ps.w.org\/cosmetic-wholesale-sync\/assets\/banner-1544x500.png?rev=3681724","banner_rtl":false,"banner_2x_rtl":false},"icons":{"svg":false,"icon":"https:\/\/ps.w.org\/cosmetic-wholesale-sync\/assets\/icon-128x128.png?rev=3681724","icon_2x":"https:\/\/ps.w.org\/cosmetic-wholesale-sync\/assets\/icon-256x256.png?rev=3681724","generated":false},"screenshots":[],"raw_content":"<!--section=description-->\n<p>Cosmetic Wholesale Sync connects a WooCommerce shop to a Cosmetic Wholesale dropshipping account.<\/p>\n\n<p>This is the official integration for the Cosmetic Wholesale dropshipping service (https:\/\/cosmeticwholesale.eu), operated by Distraal B.V. in Rotterdam, Netherlands. It is published with their permission and developed by Juniustech. The plugin is free and fully functional; it does nothing until you paste the catalog feed URL and token issued to your approved Cosmetic Wholesale account, because it has no other service to talk to.<\/p>\n\n<p><strong>Catalog<\/strong><\/p>\n\n<ul>\n<li>First import creates missing products (SKU = EAN). Images are not imported.<\/li>\n<li>Hourly job updates stock and sale price for existing SKUs only. It never wipes the catalog on feed failure.<\/li>\n<li>Price formula: <code>regular_price = round(cost \u00d7 (1 + margin%\/100) + fixed, 2)<\/code>.<\/li>\n<\/ul>\n\n<p><strong>Orders<\/strong><\/p>\n\n<ul>\n<li>When a Woo order becomes <code>processing<\/code> (customer paid), the plugin queues a POST to Cosmetic Wholesale using the same catalog feed token (not during checkout HTML).<\/li>\n<li>Insufficient wallet \u2192 Woo stays <code>processing<\/code>; the plugin retries. It does not cancel the customer order.<\/li>\n<li>Tracking from Cosmetic Wholesale is written back; the Woo order can then be completed.<\/li>\n<\/ul>\n\n<p>You need an approved Cosmetic Wholesale dropshipping account. Paste the catalog feed URL and token from your Account page. OMS \/ warehouse credentials are <strong>not<\/strong> stored in this plugin.<\/p>\n\n<h3>External services<\/h3>\n\n<p>This plugin connects to Cosmetic Wholesale (https:\/\/cosmeticwholesale.eu), the dropshipping service the merchant holds an account with. The host used is the one shown on the merchant\u2019s Account page; no address is hard-coded in the plugin.<\/p>\n\n<ol>\n<li><strong>Catalog feed (GET)<\/strong> \u2014 the Feed URL the merchant pastes. Sends <code>Authorization: Bearer &lt;token&gt;<\/code>. Receives a CSV of EAN, title, stock, and cost. Used to create\/update Woo products.<\/li>\n<li><strong>Dropshipping orders (POST\/GET)<\/strong> \u2014 derived from the same host (<code>\/api\/v1\/dropshipping\/orders<\/code>). Sends the paid Woo shipping address (name, street, city, postcode, country, phone, email) and line EANs\/quantities so Cosmetic Wholesale can fulfil the order. Returns order id and later tracking numbers.<\/li>\n<\/ol>\n\n<p>No OMS or WMS passwords are stored or sent. The token is the merchant\u2019s Cosmetic Wholesale catalog token. Data is sent only after the merchant saves settings and a customer pays. Nothing is sent while the Feed URL and token fields are empty.<\/p>\n\n<p>The service is operated by Distraal B.V. (trading as Cosmetic Wholesale), Goudsesingel 103, 3031EE Rotterdam, Netherlands. KVK 95455078, VAT NL867137538B01.<\/p>\n\n<ul>\n<li>Terms and Conditions: https:\/\/cosmeticwholesale.eu\/terms-and-conditions\/<\/li>\n<li>Privacy Policy: https:\/\/cosmeticwholesale.eu\/privacy-policy\/<\/li>\n<li>Dropshipping policies: https:\/\/cosmeticwholesale.eu\/dropshipping\/policies-for-dropshipping\/<\/li>\n<\/ul>\n\n<!--section=installation-->\n<ol>\n<li>Install and activate WooCommerce.<\/li>\n<li>Upload the plugin zip (Plugins \u2192 Add New \u2192 Upload) or install from WordPress.org.<\/li>\n<li>Open WooCommerce \u2192 Cosmetic Wholesale.<\/li>\n<li>Paste Catalog feed URL (no token in the URL) and token from your Cosmetic Wholesale Account.<\/li>\n<li>Set <strong>Margin %<\/strong> and <strong>Margin fixed<\/strong> (the same two numbers as the old 360 plugin). 0 \/ 0 = sell at B2B cost.<\/li>\n<li>Save settings. Run First import (keep the tab open, or use <code>wp cw-sync import<\/code>).<\/li>\n<li>Run Dry run until <code>updated &gt; 0<\/code>. Leave hourly sync on.<\/li>\n<\/ol>\n\n<!--section=faq-->\n<dl>\n<dt id=\"do%20i%20put%20oms%20or%20wms%20passwords%20in%20the%20plugin%3F\"><h3>Do I put OMS or WMS passwords in the plugin?<\/h3><\/dt>\n<dd><p>No. The plugin only talks to Cosmetic Wholesale. Warehouse dispatch is handled server-side.<\/p><\/dd>\n<dt id=\"why%20are%20there%20no%20product%20images%3F\"><h3>Why are there no product images?<\/h3><\/dt>\n<dd><p>First import and hourly sync do not download images. That is intentional (large catalogs). Images can be added later as a separate, infrequent job.<\/p><\/dd>\n<dt id=\"what%20happens%20if%20my%20cosmetic%20wholesale%20wallet%20is%20empty%3F\"><h3>What happens if my Cosmetic Wholesale wallet is empty?<\/h3><\/dt>\n<dd><p>The Woo order stays <code>processing<\/code>. The plugin retries about every 10 minutes after you top up. The customer is not cancelled.<\/p><\/dd>\n<dt id=\"does%20this%20replace%20the%20old%20360%20plugin%3F\"><h3>Does this replace the old 360 plugin?<\/h3><\/dt>\n<dd><p>For catalog + order push to Cosmetic Wholesale, yes. Do not run 360 catalog cron and this plugin hourly job on the same SKUs without a cutover plan.<\/p><\/dd>\n<dt id=\"what%20is%20margin%20%25%20%2F%20margin%20fixed%3F\"><h3>What is Margin % \/ Margin fixed?<\/h3><\/dt>\n<dd><p>They are your retail markup on the B2B feed cost (the same two numbers the 360 plugin used). 0 and 0 sells at cost.<\/p><\/dd>\n<dt id=\"paid%20orders%20never%20reach%20cosmetic%20wholesale\"><h3>Paid orders never reach Cosmetic Wholesale<\/h3><\/dt>\n<dd><p>Order push and the 10-minute wallet retry use WP-Cron. If <code>DISABLE_WP_CRON<\/code> is true and no system cron hits <code>wp-cron.php<\/code>, orders stay queued with no error. Check <strong>Last order retry cron (UTC)<\/strong> on WooCommerce \u2192 Cosmetic Wholesale.<\/p><\/dd>\n\n<\/dl>\n\n<!--section=changelog-->\n<h4>1.0.1<\/h4>\n\n<ul>\n<li>Stored meta keys use the full <code>_cw_sync_<\/code> prefix; keys written by pilot builds are still read.<\/li>\n<\/ul>\n\n<h4>1.0.0<\/h4>\n\n<ul>\n<li>First WordPress.org directory release (catalog sync, hourly stock\/price, paid-order push).<\/li>\n<li>Plugin slug, main file and text domain are <code>cosmetic-wholesale-sync<\/code>.<\/li>\n<li>First-import progress uses an enqueued admin script.<\/li>\n<\/ul>\n\n<h4>0.3.3<\/h4>\n\n<ul>\n<li>Packaged for the WordPress.org directory: folder and main file renamed to <code>cosmetic-wholesale-sync<\/code>, text domain changed to <code>cosmetic-wholesale-sync<\/code> so language packs work.<\/li>\n<li>SKU lookup query documented and marked for the coding standards; behaviour unchanged.<\/li>\n<li>First-import progress uses an enqueued admin script (no inline JavaScript).<\/li>\n<\/ul>\n\n<h4>0.3.2<\/h4>\n\n<ul>\n<li>Tested up to WordPress 7.1 and WooCommerce 11.0.<\/li>\n<li>Admin shows last order-retry cron time (UTC); WP-Cron note when it never runs.<\/li>\n<li>Product titles collapse newlines\/whitespace to a single space.<\/li>\n<li>LICENSE is the full GPL-2.0 text.<\/li>\n<\/ul>\n\n<h4>0.3.1<\/h4>\n\n<ul>\n<li>HPOS + cart\/checkout blocks compatibility declared.<\/li>\n<li>Empty default feed URL (no staging host baked in).<\/li>\n<li>UTF-8-safe title clip; CSV parser uses fgetcsv (quoted newlines, PHP 8.4 escape).<\/li>\n<li>Order push queued off the checkout request; 401\/403 not retried.<\/li>\n<li>Token field no longer echoes the secret into HTML.<\/li>\n<li>uninstall removes cw_sync_order_state.<\/li>\n<\/ul>\n\n<h4>0.3.0<\/h4>\n\n<ul>\n<li>Order push on Woo <code>processing<\/code>.<\/li>\n<li>402 wallet HOLD retry.<\/li>\n<li>Tracking poll \u2192 Woo completed.<\/li>\n<\/ul>\n\n<h4>0.2.2<\/h4>\n\n<ul>\n<li>Catalog first import + hourly stock\/price.<\/li>\n<\/ul>","raw_excerpt":"Pulls Cosmetic Wholesale catalog (stock\/price) into WooCommerce and sends paid orders to your Cosmetic Wholesale account.","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin\/362573","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin"}],"about":[{"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/types\/plugin"}],"replies":[{"embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/comments?post=362573"}],"author":[{"embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wporg\/v1\/users\/juniustech"}],"wp:attachment":[{"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/media?parent=362573"}],"wp:term":[{"taxonomy":"plugin_section","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_section?post=362573"},{"taxonomy":"plugin_tags","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_tags?post=362573"},{"taxonomy":"plugin_category","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_category?post=362573"},{"taxonomy":"plugin_contributors","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_contributors?post=362573"},{"taxonomy":"plugin_business_model","embeddable":true,"href":"https:\/\/wordpress.org\/plugins\/wp-json\/wp\/v2\/plugin_business_model?post=362573"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}