false); $sku = sanitize_text_field($_POST['sku']); $profile_id = MiraviaCore::get_profile_by_product($sku); LOG::add("Profile encontrado {$profile_id} -> {$sku}"); if($profile_id) { $id_remote = sanitize_text_field($_POST['id_remote']); $id_local = wc_get_product_id_by_sku($sku); $existe = MiraviaCore::get_product_miravia($id_local); if(!$existe) { $_product = wc_get_product($id_local); //Save product data $wpdb->insert($wpdb->prefix.'miravia_products', array( 'id_woocommerce' => $id_local, 'sku' => $_product->get_sku() ?: $id_local, 'id_miravia' => $id_remote, 'profile_id' => $profile_id, 'stock' => $_product->get_regular_price(), 'price' => $_product->get_regular_price(), 'sale_price' => $_product->get_sale_price(), )); LOG::add("Conectando producto ({$id_local}) remoto {$sku} con {$id_remote} con el profile {$profile_id}"); update_post_meta($id_local, '_miravia_product_id', $id_remote); update_post_meta($id_local, '_miravia_sync_date', time()); $res['ok'] = true; }else{ $res['alert'] = "This product exist"; } } wp_send_json($res); } function miravia_print_label() { $id = sanitize_text_field($_POST['id']); $package_id = sanitize_text_field($_POST['package_id']); $account_id = get_post_meta($id, '_miravia_account_id', true); $labelResult = false; $account = MiraviaCore::get_accounts($account_id); $link = new MiraviaLink($account['token']); if($account_id) { $labelResult = $link->getShippingLabel($package_id); } wp_send_json($labelResult); } function miravia_get_brands() { $token = MiraviaCore::get_miravia_account_default(); if($token) { $token = $token['token']; $link = new MiraviaCategory($token); $brands = $link->getBrands(); }else{ $brands = []; } wp_send_json($brands); } function miravia_packed_order(){ $id = sanitize_text_field($_POST['id']); $account_id = get_post_meta($id, '_miravia_account_id', true); $order_miravia_id = get_post_meta($id, '_miravia_order_id', true); if($account_id) { $account = MiraviaCore::get_accounts($account_id); $link = new MiraviaLink($account['token']); $resultPack = false; list($order, $items) = MiraviaCore::get_order_woocommerce($id); $resultPack = $link->orderPack($order_miravia_id, array('products' => $items)); update_post_meta($id, '_miravia_packed_result', $resultPack); }else{ LOG::add("{$id} no ha sido importado, no tiene ID de Cuenta", false, 'pack_order'); LOG::add([$_POST, $account_id], false, 'pack_order'); } wp_send_json($resultPack); } function miravia_check_job() { $id = sanitize_text_field($_POST['id']); LOG::add("DEBUG: Checking job status for ID: {$id}"); if($id) { $apiKey = sanitize_text_field($_POST['token']); LOG::add("DEBUG: Using API token: " . substr($apiKey, 0, 10) . "..."); $link = new MiraviaLink($apiKey); $result = $link->getFeedInfo($id); LOG::add("DEBUG: Feed info API response: " . json_encode($result)); if($result and isset($result['result']['processing_status'])) { LOG::add("DEBUG: Feed processing status: " . $result['result']['processing_status']); if($result['result']['processing_status'] == 'DONE') { LOG::add("DEBUG: Feed completed, processing individual product results..."); if(isset($result['response']) && is_array($result['response'])) { foreach($result['response'] as $sku => $value) { LOG::add("DEBUG: Processing product SKU: {$sku}, Status: " . $value['status']); if($value['status'] == 'FAIL') { $errorMsg = ''; if(isset($value['detail']['message']['errorDetail']) and count($value['detail']['message']['errorDetail']) > 0) { $errorMsg = $value['detail']['message']['errorDetail'][0]['message']; LOG::add("DEBUG: Product {$sku} FAILED with error detail: {$errorMsg}"); MiraviaCore::set_error_product_job($sku, $id, $errorMsg); }elseif(isset($value['detail']['message']['errorMsg'])) { $errorMsg = $value['detail']['message']['errorMsg']; LOG::add("DEBUG: Product {$sku} FAILED with error message: {$errorMsg}"); MiraviaCore::set_error_product_job($sku, $id, $errorMsg); }else{ LOG::add("DEBUG: Product {$sku} FAILED but no error details found"); LOG::add("DEBUG: Full error data: " . json_encode($value)); } }else{ //Controlar los updates if(!isset($value['id'])) { $value['id'] = false; } LOG::add("DEBUG: Product {$sku} SUCCESS with Miravia ID: " . $value['id']); MiraviaCore::set_id_miravia_product_job($sku, $id, $value['id']); } } } else { LOG::add("DEBUG: No product responses found in completed feed"); } } elseif($result['result']['processing_status'] == 'IN_PROGRESS') { LOG::add("DEBUG: Feed still IN_PROGRESS - queue position or time remaining not specified by API"); } elseif($result['result']['processing_status'] == 'FAILED') { LOG::add("DEBUG: Feed FAILED at API level"); if(isset($result['result']['error_message'])) { LOG::add("DEBUG: Feed error message: " . $result['result']['error_message']); } } } else { LOG::add("DEBUG: Invalid or empty feed info response"); LOG::add("DEBUG: API Last Error: " . $link->last_error); } if($result) { // MiraviaCore::set_status_job($id, $result['result']['processing_status']); wp_send_json(array('status' => $result['result']['processing_status'])); }else{ LOG::add("DEBUG: Returning false status due to API failure"); wp_send_json(array('status' => false)); } } else { LOG::add("DEBUG: No job ID provided"); wp_send_json(array('status' => false)); } }function miravia_cancel_job() { $id = sanitize_text_field($_POST['id']); if($id) { $apiKey = sanitize_text_field($_POST['token']); $link = new MiraviaLink($apiKey); $result = $link->cancelFeed($id); LOG::add($result, false, 'result_cancel_job'); if($result and $result['success']) { MiraviaCore::clear_job($id); wp_send_json(array('success' => true)); }else{ MiraviaCore::clear_job($id); wp_send_json(array('error' => true, 'message' => 'You can cancel this job, products unlock locally')); } } } function miravia_request_notify() { MiraviaCore::request_notify(sanitize_text_field($_POST['token']), sanitize_text_field($_POST['message'])); } function miravia_download_order($id = false, $token = false) { $id = $id ?: sanitize_text_field($_POST['id']); $apiKey = $token ?: sanitize_text_field($_POST['token']); $existe = MiraviaCore::order_exist($id); if(count($existe) > 0) { LOG::add("Order {$id} exists"); return; } $link = new MiraviaLink($apiKey); $order_from_miravia = $link->getOrder($id); $order_from_miravia['data']['account_id'] = sanitize_text_field($_POST['account_id']); $miravia_order = new MVOrder(); $miravia_order->create($order_from_miravia['data']); } function miravia_notify(){ LOG::add('Datos recibidos de notificación', false, 'notify'); // LOG::add($_REQUEST, false, 'notify'); if(isset($_GET['seller'])) { $idPedido = false; $action = sanitize_text_field($_GET['message']); if(sanitize_text_field($_GET['miravia_action']) == 'notify') { if(str_contains($action, 'neworder-')) { $idPedido = substr($action, 9); $action = 'neworder'; } switch($action) { case 'update_stock': $profiles = MiraviaCore::get_profiles_by_seller(sanitize_text_field($_GET['seller'])); foreach($profiles as $k => $p) { $this->send_stock_price_miravia($p['id'], false); } //update_option('miravia_notify_' . $action . '_in', time()); break; case 'neworder': if($idPedido) { if(isset($_GET['status']) and sanitize_text_field($_GET['status']) == 'pending') { $account = MiraviaCore::get_miravia_account_default(sanitize_text_field($_GET['seller']), 'userid'); $this->miravia_download_order($idPedido, $account['token']); }else{ LOG::add("Order status is ".sanitize_text_field($_GET['status'])." => {$idPedido}"); } } break; default: LOG::add("Action notify no recognized"); break; } }elseif(sanitize_text_field($_GET['miravia_action']) == 'feed') { MiraviaCore::procesarFeed(); }elseif(sanitize_text_field($_GET['miravia_action']) == 'stock_sresync') { $accounts = MiraviaCore::resync_stock(); if($accounts) { foreach($accounts as $a) { MiraviaCore::request_notify($a['token'], 'update_stock'); } } } wp_send_json(array('success' => true), 200); die(); } wp_send_json(array('success' => false), 400); die(); } function send_products_miravia() { $profile = sanitize_text_field($_POST['profile']); LOG::add("DEBUG: Starting send_products_miravia for profile {$profile}"); if ( !current_user_can( 'manage_woocommerce' ) ) { exit; } $result = array( 'id' => 0, 'error' => false, 'message' => '' ); $accounts = MiraviaCore::accounts_by_profile($profile); LOG::add("DEBUG: Found " . count($accounts) . " accounts for profile {$profile}"); LOG::add("DEBUG: Accounts data: " . json_encode($accounts)); $product = MiraviaCore::get_products_by_profile($profile); LOG::add("DEBUG: Found " . count($product) . " products for profile {$profile}"); if($product) { foreach($accounts as $a) { LOG::add("DEBUG: Processing account: " . json_encode($a)); //Enviar los productos con cada una de las cuentas de usuario registrados en el profile. //Comprobar el producto si no se ha enviado LOG::add("DEBUG: Checking products for jobs and categorizing..."); $productsToSend = array( 'update' => array(), 'create' => array() ); if($product){ foreach($product as $k => $p) { LOG::add("DEBUG: Checking product ID {$p->id}, SKU: {$p->sku}, Miravia ID: {$p->id_miravia}"); $isOnJob = MiraviaCore::check_product_onjob($p->id); LOG::add("DEBUG: Product {$p->id} is on job: " . ($isOnJob ? 'YES' : 'NO')); if($isOnJob) { LOG::add("DEBUG: Removing product {$p->id} from queue (already in job)"); unset($product[$k]); }else{ if($product and $product[$k]->id_miravia != 0 and $product[$k]->id_miravia != '' and $product[$k]->id_miravia != '0') { $product[$k]->created = 1; array_push($productsToSend['update'], $product[$k]); LOG::add("DEBUG: Product {$p->id} marked for UPDATE (existing Miravia ID: {$p->id_miravia})"); }else{ array_push($productsToSend['create'], $product[$k]); LOG::add("DEBUG: Product {$p->id} marked for CREATE (no Miravia ID)"); } } } } //Check after check on job LOG::add("DEBUG: After job check - Products to send: CREATE=" . count($productsToSend['create']) . ", UPDATE=" . count($productsToSend['update'])); LOG::add("DEBUG: Remaining products count: " . count($product)); if(count($product) == 0) { LOG::add("DEBUG: No products to send - all are in job queue"); wp_send_json(array('error' => true, 'message' => 'All products is on job, please wait to complete this before send again.')); wp_die(); } if(count($productsToSend['create']) > 0) { LOG::add("DEBUG: Processing CREATE feed for " . count($productsToSend['create']) . " products"); $link = new MiraviaLink($a['token']); $feed = new MiraviaFeed(); $feed->setProducts($productsToSend['create']); //Apply Rules LOG::add("DEBUG: Applying filters for account {$a['id']}, profile {$profile}"); $feed = MiraviaCore::applyFilter($feed, $a['id'], $profile); $productJson = $feed->getJsonCreate(); LOG::add("DEBUG: Generated CREATE JSON payload: " . substr(json_encode($productJson), 0, 500) . "..."); if(MIRAVIA_DEBUG == '0') { LOG::add("DEBUG: Sending CREATE feed to Miravia API..."); $result = $link->sendFeed($productJson); LOG::add("DEBUG: CREATE feed API response: " . json_encode($result)); if(isset($result['feed_result']) and $result['feed_result']['success']) { LOG::add("DEBUG: CREATE feed successful, setting job for products"); MiraviaCore::set_job_product(array_column($productsToSend['create'], 'id'), $profile, $result['feed_result']['result']); } else { LOG::add("DEBUG: CREATE feed FAILED - Response: " . json_encode($result)); if(isset($link->last_error)) { LOG::add("DEBUG: API Last Error: " . $link->last_error); } } } else { LOG::add("DEBUG: Debug mode active - CREATE feed not sent"); } } else { LOG::add("DEBUG: No products for CREATE feed"); } if(count($productsToSend['update']) > 0) { LOG::add("DEBUG: Processing UPDATE feed for " . count($productsToSend['update']) . " products"); $link = new MiraviaLink($a['token']); $feed = new MiraviaFeed(); $feed->setProducts($productsToSend['update']); //Apply Rules LOG::add("DEBUG: Applying filters for UPDATE feed - account {$a['id']}, profile {$profile}"); $feed = MiraviaCore::applyFilter($feed, $a['id'], $profile); $productJsonUpdate = $feed->getJsonUpdate(); LOG::add("DEBUG: Generated UPDATE JSON payload: " . substr(json_encode($productJsonUpdate), 0, 500) . "..."); if(MIRAVIA_DEBUG == '0') { LOG::add("DEBUG: Sending UPDATE feed to Miravia API..."); $result = $link->sendFeed($productJsonUpdate, 'update'); LOG::add("DEBUG: UPDATE feed API response: " . json_encode($result)); if(isset($result['feed_result']) and $result['feed_result']['success']) { LOG::add("DEBUG: UPDATE feed successful, setting job for products"); MiraviaCore::set_job_product(array_column($productsToSend['update'], 'id'), $profile, $result['feed_result']['result']); } else { LOG::add("DEBUG: UPDATE feed FAILED - Response: " . json_encode($result)); if(isset($link->last_error)) { LOG::add("DEBUG: API Last Error: " . $link->last_error); } } } else { LOG::add("DEBUG: Debug mode active - UPDATE feed not sent"); } } else { LOG::add("DEBUG: No products for UPDATE feed"); } if(MIRAVIA_DEBUG == '1') { wp_send_json(array('error' => true, 'message' => 'Debug Active', 'update' => $productJsonUpdate, 'create' => $productJson, 'initData' => $productsToSend)); die(); } LOG::add("Enviando " . count($product) . " productos con token {$a['token']}"); LOG::add($result); } } wp_send_json($product); wp_die(); } function send_stock_price_miravia($profile = false, $returnValue = true) { if(!$profile) { $profile = sanitize_text_field($_POST['profile']); } LOG::add("Enviando productos del perfil {$profile}"); if ($returnValue and !current_user_can( 'manage_woocommerce' ) ) { exit; } $result = array( 'id' => 0, 'error' => false, 'message' => '' ); $accounts = MiraviaCore::accounts_by_profile($profile); $product = MiraviaCore::get_products_by_profile($profile, true); $isOnlyStock = get_option('miravia_only_stock', '0') == '1'; if($product) { foreach($accounts as $a) { //Enviar los productos con cada una de las cuentas de usuario registrados en el profile. //Comprobar el producto si no se ha enviado foreach($product as $k => $p) { if(MiraviaCore::check_product_onjob($p->id)) { unset($product[$k]); } } //Check after check on job if(count($product) == 0) { wp_send_json(array('error' => true, 'message' => 'All products is on job, please wait to complete this before send again.')); wp_die(); } $link = new MiraviaLink($a['token']); $feed = new MiraviaFeed(); $feed->setProducts($product); //Apply Rules $feed = MiraviaCore::applyFilter($feed, $a['id'], $profile); $stockJson = $feed->getJsonUpdateStock($isOnlyStock); if(MIRAVIA_DEBUG == '1') { wp_send_json($stockJson); die(); } $result = $link->updateStock($stockJson); if(isset($result['feed_result']) and $result['feed_result']['success']) { MiraviaCore::set_job_product(array_column($product, 'id'), $profile, $result['feed_result']['result']); } } } if($returnValue) { wp_send_json($product); wp_die(); } } function miravia_create_profile() { $apiKey = sanitize_text_field($_REQUEST['api_key']); $link = new MiraviaLink($apiKey); $sellerInfo = $link->getSellerInfo(admin_url('admin-ajax.php?action=miravia_notify')); if($sellerInfo) { if(!MiraviaCore::get_accounts($sellerInfo['seller_id'], 'userid')) { $profile = MiraviaCore::add_account(array( 'name' => $sellerInfo['seller_name'], 'token' => $apiKey, 'userid' => $sellerInfo['seller_id'], 'lang' => $sellerInfo['country'], 'email' => $sellerInfo['email'], 'config' => '{short_code: "'.$sellerInfo['short_code'].'"}', )); } } wp_redirect( admin_url('admin.php?page=miravia_settings&subpage=accounts') ); wp_send_json(array('ok' => true)); } function disconnect_product_miravia(){ if ( !current_user_can( 'manage_woocommerce' ) ) { exit; } $id = $_POST['id']; LOG::add("Desconectando producto {$id} de miravia"); update_post_meta($id, '_miravia_product_id', 0); update_post_meta($id, '_miravia_sync_date', 0); wp_send_json(array('ok' => true)); } function miravia_authorize() { LOG::add("Solicitando autorización a Miravia"); $link = new MiraviaLink(); $register_link = $link->getRegisterUrl(admin_url('admin-ajax.php?action=miravia_create_profile')); LOG::add("Register link is " . $register_link); wp_redirect( $register_link ); wp_send_json(array('ok' => true)); } function miravia_upload_product() { if ( !current_user_can( 'manage_woocommerce' ) ) { exit; } $result = array( 'id' => 0, 'error' => false, 'message' => '' ); $id = sanitize_text_field($_POST['id']); $product = new MVProduct($id, 2); wp_send_json($product); wp_die(); $response = $product->send(); if(isset($response['item_id'])) { //Producto subido update_post_meta($id, '_miravia_product_id',$response['item_id']); update_post_meta($id, '_miravia_sync_date',time()); $result['id'] = $response['item_id']; }else{ $result['error'] = true; $result['message'] = $response['errors'][0]['message']; } wp_send_json($result); wp_die(); } function test_miravia_api_connection() { if (!current_user_can('manage_options')) { wp_die('Unauthorized'); } if (!wp_verify_nonce($_POST['nonce'], 'test_miravia_api')) { wp_send_json_error('Invalid nonce'); return; } // Check if direct API is enabled if (get_option('miravia_direct_api', '0') !== '1') { wp_send_json_error('Direct API access is not enabled'); return; } try { require_once plugin_dir_path(__FILE__) . 'shared/MiraviaSdk.php'; $sdk = new MiraviaSdk(); if (!$sdk->isConfigured()) { wp_send_json_error('SDK not configured. Please check your API credentials.'); return; } $test_result = $sdk->testConnection(); if ($test_result['success']) { wp_send_json_success(['message' => $test_result['message']]); } else { wp_send_json_error($test_result['error']); } } catch (Exception $e) { wp_send_json_error('Connection test failed: ' . $e->getMessage()); } } function debug_miravia_credentials() { if (!current_user_can('manage_options')) { wp_die('Unauthorized'); } $app_key = get_option('miravia_app_key', ''); $secret_key = get_option('miravia_secret_key', ''); $access_token = get_option('miravia_access_token', ''); echo "

Current Miravia Credentials:

"; echo "

App Key: " . esc_html(substr($app_key, 0, 10)) . "..." . " (length: " . strlen($app_key) . ")

"; echo "

Secret Key: " . esc_html(substr($secret_key, 0, 10)) . "..." . " (length: " . strlen($secret_key) . ")

"; echo "

Access Token: " . esc_html(substr($access_token, 0, 20)) . "..." . " (length: " . strlen($access_token) . ")

"; wp_die(); } function miravia_update_product() { if ( !current_user_can( 'manage_woocommerce' ) ) { exit; } $result = array( 'id' => 0, 'error' => false, 'message' => '' ); $id = sanitize_text_field($_POST['id']); $product = new MVProduct($id); $response = $product; if(is_array($response) and count($response) == 0) { //Producto subido update_post_meta($id, '_miravia_sync_date',time()); $result['id'] = $id; }else{ $result['error'] = true; $result['message'] = $response['errors'][0]['message']; } wp_send_json($result); wp_die(); } // NEW FEED API METHODS function miravia_submit_single_product_feed() { if (!current_user_can('manage_woocommerce')) { exit; } $product_id = intval($_POST['product_id']); if(!$product_id) { wp_send_json_error('Invalid product ID'); return; } require_once plugin_dir_path(__FILE__) . 'class.feed-manager.php'; $feedManager = new MiraviaFeedManager(); $result = $feedManager->submitSingleProduct($product_id); if($result['success']) { wp_send_json_success($result); } else { wp_send_json_error($result['error']); } } function miravia_submit_bulk_products_feed() { if (!current_user_can('manage_woocommerce')) { exit; } $product_ids = $_POST['product_ids'] ?? []; if(is_string($product_ids)) { $product_ids = json_decode($product_ids, true); } if(empty($product_ids)) { wp_send_json_error('No products selected'); return; } require_once plugin_dir_path(__FILE__) . 'class.feed-manager.php'; $feedManager = new MiraviaFeedManager(); $result = $feedManager->submitProducts(array_map('intval', $product_ids)); if($result['success']) { wp_send_json_success($result); } else { wp_send_json_error($result['error']); } } function miravia_update_job_status() { if (!current_user_can('manage_woocommerce')) { exit; } $job_id = intval($_POST['job_id']); if(!$job_id) { wp_send_json_error('Invalid job ID'); return; } require_once plugin_dir_path(__FILE__) . 'class.feed-manager.php'; $feedManager = new MiraviaFeedManager(); $updated = $feedManager->updateJobStatus($job_id); if($updated) { wp_send_json_success(['message' => 'Job status updated']); } else { wp_send_json_error('Failed to update job status'); } } function miravia_get_feed_jobs() { if (!current_user_can('manage_woocommerce')) { exit; } $page = max(1, intval($_GET['page'] ?? 1)); $limit = 20; $offset = ($page - 1) * $limit; $status = sanitize_text_field($_GET['status'] ?? ''); require_once plugin_dir_path(__FILE__) . 'class.feed-manager.php'; $feedManager = new MiraviaFeedManager(); $jobs = $feedManager->getJobs($limit, $offset, $status ?: null); $total = $feedManager->getJobCount($status ?: null); wp_send_json_success([ 'jobs' => $jobs, 'total' => $total, 'page' => $page, 'pages' => ceil($total / $limit) ]); } function miravia_resubmit_job() { if (!current_user_can('manage_woocommerce')) { exit; } $job_id = intval($_POST['job_id']); if(!$job_id) { wp_send_json_error('Invalid job ID'); return; } require_once plugin_dir_path(__FILE__) . 'class.feed-manager.php'; $feedManager = new MiraviaFeedManager(); $result = $feedManager->resubmitJob($job_id); if($result['success']) { wp_send_json_success($result); } else { wp_send_json_error($result['error']); } } } $APIMIRAVIA = new APIMIRAVIA(); }