Changeset 3334077
- Timestamp:
- 07/25/2025 09:26:21 AM (6 months ago)
- Location:
- w2s-sync
- Files:
-
- 39 added
- 5 edited
-
tags/1.2 (added)
-
tags/1.2/admin (added)
-
tags/1.2/admin/views (added)
-
tags/1.2/admin/views/class-w2ssyn-admin-page.php (added)
-
tags/1.2/assets (added)
-
tags/1.2/assets/css (added)
-
tags/1.2/assets/css/style.css (added)
-
tags/1.2/assets/image (added)
-
tags/1.2/assets/image/Customer.png (added)
-
tags/1.2/assets/image/Order.png (added)
-
tags/1.2/assets/image/Power-03.png (added)
-
tags/1.2/assets/image/Power-04.png (added)
-
tags/1.2/assets/image/Product.png (added)
-
tags/1.2/assets/js (added)
-
tags/1.2/assets/js/script.js (added)
-
tags/1.2/includes (added)
-
tags/1.2/includes/class-w2ssyn-hooks.php (added)
-
tags/1.2/includes/class-w2ssyn-swi-connector.php (added)
-
tags/1.2/includes/installation (added)
-
tags/1.2/includes/installation/class-w2ssyn-install.php (added)
-
tags/1.2/includes/installation/class-w2ssyn-uninstall.php (added)
-
tags/1.2/includes/modules (added)
-
tags/1.2/includes/modules/class-w2ssyn-auditlogs.php (added)
-
tags/1.2/includes/modules/class-w2ssyn-swi-config.php (added)
-
tags/1.2/includes/modules/class-w2ssyn-swi-customer-sync.php (added)
-
tags/1.2/includes/modules/class-w2ssyn-swi-mapping.php (added)
-
tags/1.2/includes/modules/class-w2ssyn-swi-order-sync.php (added)
-
tags/1.2/includes/modules/class-w2ssyn-swi-product-sync.php (added)
-
tags/1.2/includes/modules/class-w2ssyn-swi-shopify-authentication.php (added)
-
tags/1.2/includes/modules/class-w2ssyn-swi-sync-helper.php (added)
-
tags/1.2/includes/modules/class-w2ssyn-swi-woocommerce-authentication.php (added)
-
tags/1.2/readme.txt (added)
-
tags/1.2/screenshot-1.png (added)
-
tags/1.2/screenshot-2.png (added)
-
tags/1.2/screenshot-3.png (added)
-
tags/1.2/screenshot-4.png (added)
-
tags/1.2/screenshot-5.png (added)
-
tags/1.2/screenshot-6.png (added)
-
tags/1.2/w2s-sync.php (added)
-
trunk/assets/css/style.css (modified) (1 diff)
-
trunk/includes/modules/class-w2ssyn-swi-customer-sync.php (modified) (1 diff)
-
trunk/includes/modules/class-w2ssyn-swi-order-sync.php (modified) (1 diff)
-
trunk/readme.txt (modified) (5 diffs)
-
trunk/w2s-sync.php (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
w2s-sync/trunk/assets/css/style.css
r3326131 r3334077 19 19 margin-right: 5px; 20 20 } 21 .custom-dates{21 #custom-dates{ 22 22 display: none; 23 margin-left: 40px; 24 margin-top: 10px; 23 25 } 24 26 .smack-button-group-button{ -
w2s-sync/trunk/includes/modules/class-w2ssyn-swi-customer-sync.php
r3326131 r3334077 154 154 155 155 public static function w2ssyn_shopify_to_woo_create_customers($w2ssyn_woo_base_url, $w2ssyn_consumer_key, $w2ssyn_consumer_secret, $w2ssyn_shopify_base_url, $w2ssyn_shopify_token) 156 { 157 global $wpdb; 158 W2SSYN_SWI_Audit_Log::w2ssyn_log_sync_action('customer', 'create', 'success', 'Starting Shopify to WooCommerce customer sync...'); 159 160 // Fetch field mappings from the database 161 $w2ssyn_field_mappings = $wpdb->get_results("SELECT shopify_field, woocommerce_field FROM {$wpdb->prefix}w2ssyn_field_mappings WHERE entity_type = 'customer'", OBJECT_K); 162 163 // Convert mappings to an associative array 164 $w2ssyn_mappings = array(); 165 foreach ($w2ssyn_field_mappings as $w2ssyn_mapping) { 166 $w2ssyn_mappings[$w2ssyn_mapping->shopify_field] = $w2ssyn_mapping->woocommerce_field; 167 } 168 169 // Fetch Shopify customers 170 $w2ssyn_shopify_url = "{$w2ssyn_shopify_base_url}customers.json?limit=250"; 171 $w2ssyn_shopify_url = W2SSYN_Sync_Helper::w2ssyn_add_date_filter($w2ssyn_shopify_url, 'customer'); 172 $w2ssyn_shopify_response = wp_remote_get( 173 $w2ssyn_shopify_url, 174 array( 175 'headers' => array( 176 'Content-Type' => 'application/json', 177 'X-Shopify-Access-Token' => $w2ssyn_shopify_token, 178 ), 179 'timeout' => 30, 180 'sslverify' => false, 181 ) 182 ); 183 184 if (is_wp_error($w2ssyn_shopify_response)) { 185 W2SSYN_SWI_Audit_Log::w2ssyn_log_sync_action('customer', 'create', 'failure', 'Shopify API Error: ' . $w2ssyn_shopify_response->get_error_message()); 186 return; 187 } 188 189 $w2ssyn_shopify_customers = json_decode(wp_remote_retrieve_body($w2ssyn_shopify_response), true)['customers'] ?? array(); 190 191 if (empty($w2ssyn_shopify_customers)) { 192 W2SSYN_SWI_Audit_Log::w2ssyn_log_sync_action('customer', 'create', 'failure', 'No Shopify customers found.'); 193 return; 194 } 195 196 // Loop through Shopify customers 197 foreach ($w2ssyn_shopify_customers as $w2ssyn_shopify_customer) { 198 $w2ssyn_shopify_customer_id = $w2ssyn_shopify_customer['id']; 199 200 // Check if the customer exists in the local database 201 $w2ssyn_existing_customer = $wpdb->get_row($wpdb->prepare("SELECT * FROM {$wpdb->prefix}w2ssyn_customers WHERE shopify_customer_id = %s", $w2ssyn_shopify_customer_id)); 156 { 157 global $wpdb; 158 159 W2SSYN_SWI_Audit_Log::w2ssyn_log_sync_action('customer', 'create', 'success', 'Starting Shopify to WooCommerce customer sync...'); 160 161 $w2ssyn_shopify_headers = array( 162 'Content-Type' => 'application/json', 163 'X-Shopify-Access-Token' => $w2ssyn_shopify_token, 164 ); 165 166 $w2ssyn_shopify_url = "{$w2ssyn_shopify_base_url}customers.json?limit=250"; 167 $w2ssyn_response = wp_remote_get($w2ssyn_shopify_url, [ 168 'headers' => $w2ssyn_shopify_headers, 169 'timeout' => 30, 170 'sslverify' => false, 171 ]); 172 173 if (is_wp_error($w2ssyn_response)) { 174 W2SSYN_SWI_Audit_Log::w2ssyn_log_sync_action('customer', 'create', 'failure', 'Shopify API Error: ' . $w2ssyn_response->get_error_message()); 175 return; 176 } 177 178 $w2ssyn_customers = json_decode(wp_remote_retrieve_body($w2ssyn_response), true)['customers'] ?? []; 179 180 if (empty($w2ssyn_customers)) { 181 W2SSYN_SWI_Audit_Log::w2ssyn_log_sync_action('customer', 'create', 'failure', 'No Shopify customers found.'); 182 return; 183 } 184 185 foreach ($w2ssyn_customers as $w2ssyn_customer) { 186 $w2ssyn_existing_customer = $wpdb->get_row($wpdb->prepare( 187 "SELECT * FROM {$wpdb->prefix}w2ssyn_customers WHERE shopify_customer_id = %s", 188 $w2ssyn_customer['id'] 189 )); 190 191 if ($w2ssyn_existing_customer) { 192 $w2ssyn_woo_customer_id = $w2ssyn_existing_customer->woocommerce_customer_id; 193 194 $w2ssyn_check_url = "{$w2ssyn_woo_base_url}customers/{$w2ssyn_woo_customer_id}?consumer_key={$w2ssyn_consumer_key}&consumer_secret={$w2ssyn_consumer_secret}"; 195 $w2ssyn_check_response = wp_remote_get($w2ssyn_check_url, ['sslverify' => false]); 196 197 if (!is_wp_error($w2ssyn_check_response) && wp_remote_retrieve_response_code($w2ssyn_check_response) == 200) { 198 W2SSYN_SWI_Audit_Log::w2ssyn_log_sync_action('customer', 'create', 'success', 'WooCommerce customer exists, skipping ID: ' . $w2ssyn_customer['id']); 199 continue; 200 } else { 201 $w2ssyn_existing_customer = null; 202 W2SSYN_SWI_Audit_Log::w2ssyn_log_sync_action('customer', 'create', 'warning', 'WooCommerce customer missing, will recreate ID: ' . $w2ssyn_customer['id']); 203 } 204 } 205 206 $w2ssyn_woo_payload = [ 207 'email' => $w2ssyn_customer['email'], 208 'first_name' => $w2ssyn_customer['first_name'] ?? '', 209 'last_name' => $w2ssyn_customer['last_name'] ?? '', 210 ]; 211 212 $w2ssyn_create_url = "{$w2ssyn_woo_base_url}customers?consumer_key={$w2ssyn_consumer_key}&consumer_secret={$w2ssyn_consumer_secret}"; 213 $w2ssyn_create_response = wp_remote_post($w2ssyn_create_url, [ 214 'body' => json_encode($w2ssyn_woo_payload), 215 'headers' => ['Content-Type' => 'application/json'], 216 'sslverify' => false, 217 'timeout' => 30, 218 ]); 219 220 $w2ssyn_create_body = json_decode(wp_remote_retrieve_body($w2ssyn_create_response), true); 221 222 if (!is_wp_error($w2ssyn_create_response) && isset($w2ssyn_create_body['id'])) { 223 $w2ssyn_woo_customer_id = $w2ssyn_create_body['id']; 224 225 W2SSYN_SWI_Audit_Log::w2ssyn_log_sync_action('customer', 'create', 'success', 'Created WooCommerce customer: ' . $w2ssyn_customer['email']); 202 226 203 227 if ($w2ssyn_existing_customer) { 204 // Check if the WooCommerce customer still exists 205 $w2ssyn_woo_customer_id = $w2ssyn_existing_customer->woocommerce_customer_id; 206 $w2ssyn_woo_check_url = "{$w2ssyn_woo_base_url}customers/{$w2ssyn_woo_customer_id}?consumer_key=$w2ssyn_consumer_key&consumer_secret=$w2ssyn_consumer_secret"; 207 $w2ssyn_woo_check_response = wp_remote_get($w2ssyn_woo_check_url, array('sslverify' => false)); 208 209 if (is_wp_error($w2ssyn_woo_check_response) || wp_remote_retrieve_response_code($w2ssyn_woo_check_response) == 404) { 210 W2SSYN_SWI_Audit_Log::w2ssyn_log_sync_action('customer', 'create', 'failure', 'WooCommerce customer missing, recreating ID: ' . $w2ssyn_shopify_customer_id); 211 $w2ssyn_existing_customer = null; // Force recreation 212 } else { 213 W2SSYN_SWI_Audit_Log::w2ssyn_log_sync_action('customer', 'create', 'success', 'WooCommerce customer exists, skipping ID: ' . $w2ssyn_shopify_customer_id); 214 continue; 215 } 216 } 217 218 // Map Shopify customer data to WooCommerce format dynamically 219 $w2ssyn_woo_customer = array(); 220 foreach ($w2ssyn_mappings as $w2ssyn_shopify_field => $w2ssyn_woo_field) { 221 if (isset($w2ssyn_shopify_customer[$w2ssyn_shopify_field])) { 222 $w2ssyn_woo_customer[$w2ssyn_woo_field] = $w2ssyn_shopify_customer[$w2ssyn_shopify_field]; 223 } 224 } 225 226 // Handle address if available 227 if (!empty($w2ssyn_shopify_customer['default_address'])) { 228 $w2ssyn_woo_customer['billing'] = array( 229 'address_1' => $w2ssyn_shopify_customer['default_address']['address1'] ?? '', 230 'address_2' => $w2ssyn_shopify_customer['default_address']['address2'] ?? '', 231 'city' => $w2ssyn_shopify_customer['default_address']['city'] ?? '', 232 'state' => $w2ssyn_shopify_customer['default_address']['province'] ?? '', 233 'postcode' => $w2ssyn_shopify_customer['default_address']['zip'] ?? '', 234 'country' => $w2ssyn_shopify_customer['default_address']['country'] ?? '', 235 'phone' => $w2ssyn_shopify_customer['default_address']['phone'] ?? '', 236 ); 237 } 238 239 W2SSYN_SWI_Audit_Log::w2ssyn_log_sync_action('customer', 'create', 'success', 'Creating WooCommerce Customer for ID: ' . $w2ssyn_shopify_customer_id); 240 241 // Create customer in WooCommerce 242 $w2ssyn_woo_create_url = "{$w2ssyn_woo_base_url}customers?consumer_key=$w2ssyn_consumer_key&consumer_secret=$w2ssyn_consumer_secret"; 243 $w2ssyn_woo_post_response = wp_remote_post( 244 $w2ssyn_woo_create_url, 245 array( 246 'headers' => array('Content-Type' => 'application/json'), 247 'body' => json_encode($w2ssyn_woo_customer), 248 'method' => 'POST', 249 'timeout' => 30, 250 'sslverify' => false, 251 ) 228 $wpdb->update( 229 $wpdb->prefix . 'w2ssyn_customers', 230 ['woocommerce_customer_id' => $w2ssyn_woo_customer_id], 231 ['id' => $w2ssyn_existing_customer->id] 232 ); 233 } else { 234 $wpdb->insert( 235 $wpdb->prefix . 'w2ssyn_customers', 236 [ 237 'shopify_customer_id' => $w2ssyn_customer['id'], 238 'woocommerce_customer_id' => $w2ssyn_woo_customer_id, 239 'first_name' => $w2ssyn_customer['first_name'] ?? '', 240 'last_name' => $w2ssyn_customer['last_name'] ?? '', 241 'email' => $w2ssyn_customer['email'] ?? '', 242 'address' => json_encode($w2ssyn_customer['addresses'] ?? []), 243 ] 244 ); 245 } 246 } else { 247 W2SSYN_SWI_Audit_Log::w2ssyn_log_sync_action( 248 'customer', 249 'create', 250 'failure', 251 'Failed to create WooCommerce customer: ' . $w2ssyn_customer['email'] . ' - ' . wp_remote_retrieve_body($w2ssyn_create_response) 252 252 ); 253 254 $w2ssyn_woo_response_raw = wp_remote_retrieve_body($w2ssyn_woo_post_response); 255 $w2ssyn_woo_post_body = json_decode($w2ssyn_woo_response_raw, true); 256 257 if (is_wp_error($w2ssyn_woo_post_response)) { 258 W2SSYN_SWI_Audit_Log::w2ssyn_log_sync_action('customer', 'create', 'failure', 'WooCommerce API Error: ' . $w2ssyn_woo_post_response->get_error_message()); 259 } elseif (empty($w2ssyn_woo_post_body['id'])) { 260 W2SSYN_SWI_Audit_Log::w2ssyn_log_sync_action('customer', 'create', 'failure', 'WooCommerce response error: ' . json_encode($w2ssyn_woo_post_body)); 261 } else { 262 W2SSYN_SWI_Audit_Log::w2ssyn_log_sync_action('customer', 'create', 'success', 'Successfully created WooCommerce customer for ID: ' . $w2ssyn_shopify_customer_id); 263 $w2ssyn_woo_customer_id = $w2ssyn_woo_post_body['id']; 264 265 // Update or insert new record in DB 266 $wpdb->replace( 267 $wpdb->prefix . 'w2ssyn_customers', 268 array( 269 'shopify_customer_id' => $w2ssyn_shopify_customer_id, 270 'woocommerce_customer_id' => $w2ssyn_woo_customer_id, 271 'first_name' => $w2ssyn_woo_customer['first_name'] ?? '', 272 'last_name' => $w2ssyn_woo_customer['last_name'] ?? '', 273 'email' => $w2ssyn_woo_customer['email'] ?? '', 274 'address' => json_encode($w2ssyn_woo_customer['billing'] ?? array()), 275 ) 276 ); 277 } 278 279 // Optional delay to prevent hitting API rate limits 280 sleep(2); 281 } 282 283 W2SSYN_SWI_Audit_Log::w2ssyn_log_sync_action('customer', 'create', 'success', 'Shopify to WooCommerce customer sync completed.'); 284 } 253 } 254 255 sleep(2); // Prevent rate limits 256 } 257 258 W2SSYN_SWI_Audit_Log::w2ssyn_log_sync_action('customer', 'create', 'success', 'Shopify to WooCommerce customer sync completed.'); 259 } 260 285 261 286 262 -
w2s-sync/trunk/includes/modules/class-w2ssyn-swi-order-sync.php
r3326131 r3334077 233 233 if (is_wp_error($w2ssyn_woo_order_response) || wp_remote_retrieve_response_code($w2ssyn_woo_order_response) === 404) { 234 234 // If the WooCommerce order does not exist, create it 235 235 $w2ssyn_order_data = array( 236 'status' => $w2ssyn_order_status, 237 'customer_id' => $w2ssyn_customer_id, 238 'line_items' => $w2ssyn_line_items, 239 'total' => $w2ssyn_order_total, 240 'shipping' => array( 241 'address' => array( 242 'line1' => $w2ssyn_shopify_order['shipping_address']['address1'] ?? '', 243 'line2' => $w2ssyn_shopify_order['shipping_address']['address2'] ?? '', 244 'city' => $w2ssyn_shopify_order['shipping_address']['city'] ?? '', 245 'state' => $w2ssyn_shopify_order['shipping_address']['province'] ?? '', 246 'postcode' => $w2ssyn_shopify_order['shipping_address']['zip'] ?? '', 247 'country' => $w2ssyn_shopify_order['shipping_address']['country'] ?? '', 248 ), 249 ), 250 ); 251 252 // 2. Send it to WooCommerce 253 $w2ssyn_order_response = wp_remote_post( 254 "{$w2ssyn_woo_base_url}orders", 255 array( 256 'method' => 'POST', 257 'headers' => array( 258 'Content-Type' => 'application/json', 259 'Authorization' => 'Basic ' . base64_encode("{$w2ssyn_woo_consumer_key}:{$w2ssyn_woo_consumer_secret}"), 260 ), 261 'body' => json_encode($w2ssyn_order_data), 262 'sslverify' => false, 263 'timeout' => 60, 264 ) 265 ); 266 267 // 3. Log the response 268 $code = wp_remote_retrieve_response_code($w2ssyn_order_response); 269 $body = wp_remote_retrieve_body($w2ssyn_order_response); 270 271 // 4. On success, save the new order ID 272 if ( $code === 201 ) { 273 $data = json_decode($body, true); 274 if ( ! empty($data['id']) ) { 275 $wpdb->update( 276 $w2ssyn_table_name, 277 [ 'woocommerce_order_id' => $data['id'] ], 278 [ 'shopify_order_id' => $w2ssyn_shopify_order_id ] 279 ); 280 } 281 } 236 282 // Prepare line items for WooCommerce order from Shopify data 237 283 $w2ssyn_line_items = array(); -
w2s-sync/trunk/readme.txt
r3329693 r3334077 1 === W2S -Sync===1 === W2S Sync – WooCommerce to Shopify Integration === 2 2 Contributors: smackcoders, smacksupport 3 3 Donate link: https://www.smackcoders.com/contact-us.html 4 4 Requires at least: 5.0 5 5 Tested up to: 6.8 6 Version: 1. 16 Version: 1.2 7 7 Requires PHP: 7.2 8 Stable tag: 1. 18 Stable tag: 1.2 9 9 Author: smackcoders 10 10 Author URI: https://www.smackcoders.com … … 21 21 [youtube https://www.youtube.com/watch?v=1-tuqBcU0RM&t=52s] 22 22 23 == Authentication – How to Connect Your Stores == 24 25 To begin syncing, you need to securely connect your WooCommerce and Shopify stores by generating API credentials for both platforms: 26 27 - **WooCommerce**: Generate Consumer Key and Secret from your WordPress admin. 28 - **Shopify**: Create a private app to get your Admin API access token. 29 30 Follow the step-by-step guide here: 31 [Authentication Setup Guide](https://www.smackcoders.com/documentation/woocommerce-to-shopify-integration/woocommerce-to-shopify-integration-authentication-setup) 32 33 Once connected, visual indicators (Green, Yellow, Red) show the status of your authentication. 34 23 35 **Key Benefits:** 24 - Bi-directional sync between WooCommerce and Shopify 25 - One-time migration or continuous data synchronization 26 - Supports syncing of Products, Orders, and Customers 27 - Easy authentication with WooCommerce API keys and Shopify access token 28 - Schedule syncs: On Save, Hourly, Daily, Weekly, or within a custom date range 29 - Auto field mapping and customizable sync actions (Create, Update, Delete) 30 - Visual indicators for successful authentication and sync status 31 - Audit Log for detailed activity tracking and debugging 36 - **Bi-Directional Sync** 37 Sync data both ways: WooCommerce → Shopify, Shopify → WooCommerce, or keep both stores in sync at the same time. 38 - **Real-Time & Scheduled Sync** 39 Trigger sync instantly on product save or set automatic sync intervals — hourly, daily, weekly, or within a custom date range. 40 - **Sync Key Data Types** 41 Support for syncing Products, Orders, and Customers. Choose whether to Create, Update, or Delete data. 42 - **Auto Field Mapping** 43 WooCommerce and Shopify fields are automatically matched — reduce setup effort and avoid mismatches. 44 - **Audit Log** 45 View a full history of all sync activities, including timestamps, success/failure status, and detailed actions. 46 - **One-Time or Continuous Use** 47 Use W2S for a single migration or leave it running for continuous integration between your platforms. 48 - **Local Data & Secure Credentials** 49 Your credentials are stored locally in WordPress and are only used to connect to your own stores. No external services involved. 32 50 33 51 **How It Works:** … … 59 77 60 78 = Can I schedule a nightly sync? = 61 Yes —choose **Daily** under Schedule Sync. Ensure WP-Cron is active.79 Yes choose **Daily** under Schedule Sync. Ensure WP-Cron is active. 62 80 63 81 = Does this support Shopify → WooCommerce product sync? = … … 104 122 105 123 == Changelog == 124 = 1.2 = 125 * Bug fixes 106 126 = 1.1 = 107 127 * Bug fix … … 112 132 == Upgrade Notice == 113 133 114 = 1. 1=134 = 1.2 = 115 135 Upgrade now to get latest update. 116 136 apps-fileview.texmex_20250501.00_p3 -
w2s-sync/trunk/w2s-sync.php
r3326131 r3334077 1 1 <?php 2 2 3 /** 3 4 * Plugin Name: W2S-Sync 4 5 * Plugin URI: https://www.smackcoders.com/ 5 6 * Description: A custom Shopify-WooCommerce integration plugin for WordPress that enables two-way synchronization of customers, products, and orders. It features automated scheduling, configurable sync settings, secure API authentication, detailed audit logs, and customizable field mappings—ensuring seamless data consistency across both eCommerce platforms. 6 * Version: 1. 07 * Version: 1.2 7 8 * Requires at least: 6.0 8 9 * Requires PHP: 7.4
Note: See TracChangeset
for help on using the changeset viewer.