Changeset 3493435
- Timestamp:
- 03/28/2026 03:39:15 PM (5 days ago)
- Location:
- api-isarud/trunk
- Files:
-
- 2 added
- 10 deleted
- 4 edited
-
api-isarud-tr_TR.mo (added)
-
api-isarud-tr_TR.po (added)
-
api-isarud.php (modified) (1 diff)
-
assets/banner-772x250.png (deleted)
-
assets/icon-128x128.png (deleted)
-
assets/icon-256x256.png (deleted)
-
assets/logo-gif.gif (deleted)
-
assets/screenshot-1.png (deleted)
-
assets/screenshot-2.png (deleted)
-
assets/screenshot-3.png (deleted)
-
assets/screenshot-4.png (deleted)
-
assets/screenshot-5.png (deleted)
-
assets/screenshot-6.png (deleted)
-
isarud-cloud-sync.php (modified) (20 diffs)
-
readme-tr_TR.txt (modified) (1 diff)
-
readme.txt (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
api-isarud/trunk/api-isarud.php
r3491997 r3493435 17 17 if (!defined('ABSPATH')) exit; 18 18 19 define('ISARUD_VERSION', '6. 0.4');19 define('ISARUD_VERSION', '6.1.0'); 20 20 define('ISARUD_DIR', plugin_dir_path(__FILE__)); 21 21 define('ISARUD_URL', plugin_dir_url(__FILE__)); -
api-isarud/trunk/isarud-cloud-sync.php
r3490819 r3493435 2 2 /** 3 3 * Isarud Cloud Sync — isarud.com API v2 entegrasyonu 4 * WP Plugin v 3.04 * WP Plugin v6.1.0 5 5 */ 6 6 if (!defined('ABSPATH')) exit; … … 17 17 18 18 public function __construct() { 19 // Cloud sync on cron20 19 add_action('isarud_cloud_sync_hook', [$this, 'run_cloud_sync']); 21 22 // Sync on new order (after screening)23 20 add_action('woocommerce_new_order', [$this, 'sync_order_to_cloud'], 40, 1); 24 21 25 // Schedule cloud sync cron if enabled26 22 if (get_option('isarud_cloud_enabled') === 'yes') { 27 23 if (!wp_next_scheduled('isarud_cloud_sync_hook')) { … … 31 27 } 32 28 33 /**34 * Get the marketplace API key for cloud sync35 */36 29 private function get_cloud_key(): string { 37 30 return get_option('isarud_cloud_api_key', ''); 38 31 } 39 32 40 /**41 * Check if cloud sync is enabled and configured42 */43 33 public function is_enabled(): bool { 44 34 return get_option('isarud_cloud_enabled') === 'yes' && !empty($this->get_cloud_key()); 45 35 } 46 36 47 /**48 * API request to isarud.com49 */50 37 private function api_request(string $endpoint, array $data = [], string $method = 'POST'): array { 51 38 $key = $this->get_cloud_key(); … … 82 69 } 83 70 84 /**85 * Connect this WP site to isarud.com86 * Called when user saves cloud settings with Bearer token auth87 */88 71 public function connect_site(string $bearer_token): array { 89 72 $response = wp_remote_post('https://isarud.com/api/v2/marketplace/connect', [ … … 108 91 if (!empty($body['success']) && !empty($body['platform']['api_key'])) { 109 92 update_option('isarud_cloud_api_key', $body['platform']['api_key']); 110 update_option('isarud_api_key', $bearer_token); // Screening için user API key93 update_option('isarud_api_key', $bearer_token); 111 94 update_option('isarud_cloud_enabled', 'yes'); 112 95 update_option('isarud_cloud_platform_id', $body['platform']['id']); … … 114 97 } 115 98 116 // Already connected — might have api_key from before117 99 if (isset($body['error']) && strpos($body['error'], 'already connected') !== false) { 118 100 return ['success' => true, 'message' => 'Already connected']; … … 122 104 } 123 105 124 /**125 * Sync all WooCommerce products to isarud.com126 */127 106 public function sync_products(): array { 128 107 if (!$this->is_enabled() || !class_exists('WooCommerce')) { … … 139 118 140 119 foreach ($wc_products as $product) { 141 // Base product entry (WooCommerce)142 120 $products_data[] = [ 143 121 'external_id' => (string)$product->get_id(), … … 155 133 ]; 156 134 157 // Per-marketplace entries158 135 foreach ($marketplaces as $mp) { 159 136 $barcode = get_post_meta($product->get_id(), '_isarud_barcode', true) ?: $product->get_sku(); … … 177 154 } 178 155 179 // Send in chunks of 100180 156 $total_synced = 0; 181 157 $total_failed = 0; … … 200 176 } 201 177 202 /**203 * Sync recent orders to isarud.com204 */205 178 public function sync_orders(): array { 206 179 if (!$this->is_enabled() || !class_exists('WooCommerce')) { … … 226 199 } 227 200 228 // Send in chunks of 100229 201 $total_synced = 0; 230 202 $total_failed = 0; … … 249 221 } 250 222 251 /**252 * Sync single order to cloud (called on woocommerce_new_order)253 */254 223 public function sync_order_to_cloud(int $order_id): void { 255 224 if (!$this->is_enabled()) return; … … 263 232 } 264 233 265 /**266 * Format WC order for API267 */268 234 private function format_order($order): array { 269 235 return [ … … 286 252 287 253 /** 288 * Run full cloud sync (products + orders) — called by cron 254 * Sync extended data: settings, customers, abandoned carts, einvoices 255 */ 256 public function sync_extended_data(): array { 257 if (!$this->is_enabled()) { 258 return ['error' => 'Cloud sync not enabled']; 259 } 260 261 $results = []; 262 263 $results['settings'] = $this->sync_settings(); 264 $results['customers'] = $this->sync_customers(); 265 $results['abandoned_carts'] = $this->sync_abandoned_carts(); 266 $results['einvoices'] = $this->sync_einvoices(); 267 268 update_option('isarud_cloud_last_extended_sync', current_time('mysql')); 269 270 return $results; 271 } 272 273 private function sync_settings(): array { 274 $option_keys = [ 275 'isarud_b2b_settings', 276 'isarud_currency_settings', 277 'isarud_tcmb_rates', 278 'isarud_segment_settings', 279 'isarud_einvoice_settings', 280 'isarud_popup_settings', 281 'isarud_popup_campaigns', 282 'isarud_cart_recovery_settings', 283 'isarud_email_marketing_settings', 284 'isarud_email_log', 285 'isarud_upsell_settings', 286 'isarud_upsell_rules', 287 ]; 288 289 $settings = []; 290 foreach ($option_keys as $key) { 291 $value = get_option($key, null); 292 if ($value !== null) { 293 $settings[] = [ 294 'key' => $key, 295 'value' => is_array($value) ? $value : json_decode($value, true), 296 ]; 297 } 298 } 299 300 if (empty($settings)) { 301 return ['success' => true, 'synced' => 0, 'message' => 'No settings to sync']; 302 } 303 304 $result = $this->api_request('settings/sync', ['settings' => $settings]); 305 306 return $result; 307 } 308 309 private function sync_customers(): array { 310 if (!class_exists('WooCommerce')) { 311 return ['success' => true, 'synced' => 0, 'message' => 'WooCommerce not active']; 312 } 313 314 $segment_settings = get_option('isarud_segment_settings', []); 315 $b2b_settings = get_option('isarud_b2b_settings', []); 316 317 $customers_query = new \WC_Customer_Query([ 318 'limit' => 500, 319 'orderby' => 'date_created', 320 'order' => 'DESC', 321 ]); 322 323 $wc_customers = $customers_query->get_customers(); 324 325 if (empty($wc_customers)) { 326 return ['success' => true, 'synced' => 0, 'message' => 'No customers']; 327 } 328 329 $customers_data = []; 330 foreach ($wc_customers as $customer) { 331 $customer_id = $customer->get_id(); 332 $order_count = (int)$customer->get_order_count(); 333 $total_spent = (float)$customer->get_total_spent(); 334 335 $segment = $this->determine_segment($customer_id, $order_count, $total_spent, $segment_settings); 336 337 $b2b_discount = 0; 338 $company = $customer->get_billing_company(); 339 if (!empty($b2b_settings['enabled']) && $b2b_settings['enabled'] === 'yes') { 340 $b2b_discount = (float)get_user_meta($customer_id, '_isarud_b2b_discount', true); 341 } 342 343 $customers_data[] = [ 344 'external_id' => $customer_id, 345 'email' => $customer->get_email(), 346 'name' => trim($customer->get_first_name() . ' ' . $customer->get_last_name()), 347 'company' => $company ?: null, 348 'segment' => $segment, 349 'discount_rate' => $b2b_discount, 350 'total_orders' => $order_count, 351 'total_spent' => $total_spent, 352 'meta' => [ 353 'billing_country' => $customer->get_billing_country(), 354 'billing_city' => $customer->get_billing_city(), 355 'phone' => $customer->get_billing_phone(), 356 'date_created' => $customer->get_date_created() ? $customer->get_date_created()->format('Y-m-d H:i:s') : null, 357 ], 358 ]; 359 } 360 361 $total_synced = 0; 362 $total_failed = 0; 363 364 foreach (array_chunk($customers_data, 100) as $chunk) { 365 $result = $this->api_request('customers/sync', ['customers' => $chunk]); 366 if (isset($result['error'])) { 367 $total_failed += count($chunk); 368 } else { 369 $total_synced += $result['synced'] ?? 0; 370 $total_failed += $result['failed'] ?? 0; 371 } 372 } 373 374 return ['success' => true, 'synced' => $total_synced, 'failed' => $total_failed]; 375 } 376 377 private function determine_segment(int $customer_id, int $order_count, float $total_spent, array $settings): string { 378 $vip_threshold = (float)($settings['vip_min_spent'] ?? 5000); 379 $loyal_threshold = (int)($settings['loyal_min_orders'] ?? 5); 380 $risk_days = (int)($settings['risk_inactive_days'] ?? 180); 381 382 if ($total_spent >= $vip_threshold) return 'vip'; 383 if ($order_count >= $loyal_threshold) return 'loyal'; 384 if ($order_count === 1) return 'one_time'; 385 if ($order_count === 0) return 'new'; 386 387 $last_order_date = get_user_meta($customer_id, '_last_order_date', true); 388 if ($last_order_date) { 389 $days_since = (int)((time() - strtotime($last_order_date)) / 86400); 390 if ($days_since > $risk_days) return 'churned'; 391 if ($days_since > ($risk_days / 2)) return 'at_risk'; 392 } 393 394 return 'regular'; 395 } 396 397 private function sync_abandoned_carts(): array { 398 global $wpdb; 399 $table = $wpdb->prefix . 'isarud_abandoned_carts'; 400 401 if ($wpdb->get_var("SHOW TABLES LIKE '{$table}'") !== $table) { 402 return ['success' => true, 'synced' => 0, 'message' => 'Abandoned carts table not found']; 403 } 404 405 $carts = $wpdb->get_results("SELECT * FROM {$table} ORDER BY updated_at DESC LIMIT 500"); 406 407 if (empty($carts)) { 408 return ['success' => true, 'synced' => 0, 'message' => 'No abandoned carts']; 409 } 410 411 $carts_data = []; 412 foreach ($carts as $cart) { 413 $cart_items = maybe_unserialize($cart->cart_contents ?? ''); 414 if (is_string($cart_items)) { 415 $cart_items = json_decode($cart_items, true); 416 } 417 418 $carts_data[] = [ 419 'external_id' => (int)$cart->id, 420 'session_id' => $cart->session_id ?? null, 421 'email' => $cart->email ?? null, 422 'customer_name' => $cart->customer_name ?? null, 423 'cart_total' => (float)($cart->cart_total ?? 0), 424 'cart_items' => is_array($cart_items) ? $cart_items : null, 425 'status' => $cart->status ?? 'abandoned', 426 'emails_sent' => (int)($cart->emails_sent ?? 0), 427 'last_email_at' => $cart->last_email_at ?? null, 428 'recovered_at' => $cart->recovered_at ?? null, 429 'cart_date' => $cart->created_at ?? $cart->updated_at ?? null, 430 ]; 431 } 432 433 $total_synced = 0; 434 $total_failed = 0; 435 436 foreach (array_chunk($carts_data, 100) as $chunk) { 437 $result = $this->api_request('abandoned-carts/sync', ['carts' => $chunk]); 438 if (isset($result['error'])) { 439 $total_failed += count($chunk); 440 } else { 441 $total_synced += $result['synced'] ?? 0; 442 $total_failed += $result['failed'] ?? 0; 443 } 444 } 445 446 return ['success' => true, 'synced' => $total_synced, 'failed' => $total_failed]; 447 } 448 449 private function sync_einvoices(): array { 450 global $wpdb; 451 $table = $wpdb->prefix . 'isarud_einvoices'; 452 453 if ($wpdb->get_var("SHOW TABLES LIKE '{$table}'") !== $table) { 454 return ['success' => true, 'synced' => 0, 'message' => 'Einvoices table not found']; 455 } 456 457 $invoices = $wpdb->get_results("SELECT * FROM {$table} ORDER BY created_at DESC LIMIT 500"); 458 459 if (empty($invoices)) { 460 return ['success' => true, 'synced' => 0, 'message' => 'No einvoices']; 461 } 462 463 $invoices_data = []; 464 foreach ($invoices as $inv) { 465 $gib_response = $inv->gib_response ?? null; 466 if (is_string($gib_response)) { 467 $gib_response = json_decode($gib_response, true); 468 } 469 470 $invoices_data[] = [ 471 'external_id' => (int)$inv->id, 472 'order_id' => (int)($inv->order_id ?? 0), 473 'invoice_number' => $inv->invoice_number ?? null, 474 'invoice_type' => $inv->invoice_type ?? 'einvoice', 475 'customer_name' => $inv->customer_name ?? null, 476 'customer_tax_id' => $inv->tax_id ?? $inv->customer_tax_id ?? null, 477 'total' => (float)($inv->total ?? 0), 478 'currency' => $inv->currency ?? 'TRY', 479 'status' => $inv->status ?? 'draft', 480 'gib_response' => is_array($gib_response) ? $gib_response : null, 481 'invoice_date' => $inv->invoice_date ?? $inv->created_at ?? null, 482 ]; 483 } 484 485 $total_synced = 0; 486 $total_failed = 0; 487 488 foreach (array_chunk($invoices_data, 100) as $chunk) { 489 $result = $this->api_request('einvoices/sync', ['einvoices' => $chunk]); 490 if (isset($result['error'])) { 491 $total_failed += count($chunk); 492 } else { 493 $total_synced += $result['synced'] ?? 0; 494 $total_failed += $result['failed'] ?? 0; 495 } 496 } 497 498 return ['success' => true, 'synced' => $total_synced, 'failed' => $total_failed]; 499 } 500 501 /** 502 * Run full cloud sync (products + orders + extended) — called by cron 289 503 */ 290 504 public function run_cloud_sync(): void { … … 293 507 $this->sync_products(); 294 508 $this->sync_orders(); 509 $this->sync_extended_data(); 295 510 296 511 update_option('isarud_cloud_last_sync', current_time('mysql')); … … 298 513 299 514 /** 300 * Get margin for marketplace (delegates to main plugin)515 * Manual trigger for extended sync only 301 516 */ 517 public function run_extended_sync_now(): array { 518 if (!$this->is_enabled()) { 519 return ['error' => 'Cloud sync not enabled']; 520 } 521 522 return $this->sync_extended_data(); 523 } 524 302 525 private function apply_margin(float $price, string $mp): float { 303 526 $plugin = Isarud_Plugin::instance(); 304 527 if (method_exists($plugin, 'sync_stock_public')) { 305 // Use reflection or direct DB query306 528 global $wpdb; 307 529 $row = $wpdb->get_row($wpdb->prepare( … … 318 540 } 319 541 320 /**321 * Get sync status for display322 */323 542 public function get_status(): array { 324 543 return [ … … 328 547 'last_product_sync' => get_option('isarud_cloud_last_product_sync', ''), 329 548 'last_order_sync' => get_option('isarud_cloud_last_order_sync', ''), 549 'last_extended_sync' => get_option('isarud_cloud_last_extended_sync', ''), 330 550 ]; 331 551 } 332 552 333 /**334 * Disconnect from isarud.com335 */336 553 public function disconnect(): void { 337 554 delete_option('isarud_cloud_api_key'); … … 341 558 delete_option('isarud_cloud_last_product_sync'); 342 559 delete_option('isarud_cloud_last_order_sync'); 560 delete_option('isarud_cloud_last_extended_sync'); 343 561 wp_clear_scheduled_hook('isarud_cloud_sync_hook'); 344 562 } -
api-isarud/trunk/readme-tr_TR.txt
r3492097 r3493435 5 5 Tested up to: 6.9 6 6 Requires PHP: 8.0 7 Stable tag: 6. 0.47 Stable tag: 6.1.0 8 8 License: GPLv2 or later 9 9 -
api-isarud/trunk/readme.txt
r3492097 r3493435 5 5 Tested up to: 6.9 6 6 Requires PHP: 8.0 7 Stable tag: 6. 0.47 Stable tag: 6.1.0 8 8 License: GPLv2 or later 9 9
Note: See TracChangeset
for help on using the changeset viewer.