diff --git a/admin/class-informatiq-sp-admin.php b/admin/class-informatiq-sp-admin.php index 2f01942c..112e2a66 100644 --- a/admin/class-informatiq-sp-admin.php +++ b/admin/class-informatiq-sp-admin.php @@ -840,47 +840,29 @@ class Informatiq_SP_Admin { } foreach ( $google_products_raw as $gp ) { - // Index by offerId (direct field). + // Index by offerId (top-level field). if ( ! empty( $gp['offerId'] ) ) { $google_products['offer_' . $gp['offerId']] = $gp; } - // Index by gtin (direct field). - if ( ! empty( $gp['gtin'] ) ) { - $google_products['gtin_' . $gp['gtin']] = $gp; - } - - // Also check nested attributes structure (new Merchant API format). - if ( ! empty( $gp['attributes']['offerId'] ) ) { - $google_products['offer_' . $gp['attributes']['offerId']] = $gp; - } - if ( ! empty( $gp['attributes']['gtin'] ) ) { - $google_products['gtin_' . $gp['attributes']['gtin']] = $gp; - } - - // Check productId which might contain the identifier. - if ( ! empty( $gp['productId'] ) ) { - // productId format is usually: online:en:US:SKU or channel:language:country:offerId - $parts = explode( ':', $gp['productId'] ); - if ( count( $parts ) >= 4 ) { - $extracted_offer = $parts[ count( $parts ) - 1 ]; - $google_products['offer_' . $extracted_offer] = $gp; + // Index by GTIN - check attributes.gtin which is an ARRAY. + if ( ! empty( $gp['attributes']['gtin'] ) && is_array( $gp['attributes']['gtin'] ) ) { + foreach ( $gp['attributes']['gtin'] as $gtin_value ) { + $google_products['gtin_' . $gtin_value] = $gp; } } - // Check name field which contains full resource path. - if ( ! empty( $gp['name'] ) ) { - // name format: accounts/{account}/products/{product_id} - // product_id format: online~en~US~SKU - if ( preg_match( '/products\/(.+)$/', $gp['name'], $matches ) ) { - $product_id = $matches[1]; - $parts = explode( '~', $product_id ); - if ( count( $parts ) >= 4 ) { - $extracted_offer = $parts[ count( $parts ) - 1 ]; - $google_products['offer_' . $extracted_offer] = $gp; - } + // Also check attributes.gtins (alternative field name). + if ( ! empty( $gp['attributes']['gtins'] ) && is_array( $gp['attributes']['gtins'] ) ) { + foreach ( $gp['attributes']['gtins'] as $gtin_value ) { + $google_products['gtin_' . $gtin_value] = $gp; } } + + // Index by MPN if available. + if ( ! empty( $gp['attributes']['mpn'] ) ) { + $google_products['mpn_' . $gp['attributes']['mpn']] = $gp; + } } // Get WooCommerce in-stock products (limit to 50 for performance). @@ -921,10 +903,12 @@ class Informatiq_SP_Admin { $match_type = 'gtin'; } - // Get Google price. + // Get Google price (nested in attributes in new Merchant API). $google_price = null; if ( $google_product ) { - if ( isset( $google_product['price']['amountMicros'] ) ) { + if ( isset( $google_product['attributes']['price']['amountMicros'] ) ) { + $google_price = (float) $google_product['attributes']['price']['amountMicros'] / 1000000; + } elseif ( isset( $google_product['price']['amountMicros'] ) ) { $google_price = (float) $google_product['price']['amountMicros'] / 1000000; } } diff --git a/includes/class-informatiq-sp-google-api.php b/includes/class-informatiq-sp-google-api.php index ed52d439..ecfaf3a3 100644 --- a/includes/class-informatiq-sp-google-api.php +++ b/includes/class-informatiq-sp-google-api.php @@ -300,9 +300,16 @@ class Informatiq_SP_Google_API { } // Fallback: Use product's own price as reference. + // Price is nested inside attributes in the new Merchant API. + if ( isset( $product['attributes']['price']['amountMicros'] ) ) { + $price = (float) $product['attributes']['price']['amountMicros'] / 1000000; + $this->logger->warning( "No competitive data available for SKU={$sku}, using own price as reference" ); + return $price; + } + // Also check top-level price (in case API changes). if ( isset( $product['price']['amountMicros'] ) ) { $price = (float) $product['price']['amountMicros'] / 1000000; - $this->logger->warning( "No competitive data available for SKU={$sku}, using own price as reference" ); + $this->logger->warning( "No competitive data available for SKU={$sku}, using own price as reference (top-level)" ); return $price; } @@ -347,15 +354,31 @@ class Informatiq_SP_Google_API { return $product; } - // Check if SKU matches Google's GTIN (for stores where SKU is the barcode). - if ( isset( $product['gtin'] ) && $product['gtin'] === $sku ) { - $this->logger->info( "Product matched by GTIN={$sku} (SKU used as barcode)" ); - return $product; + // Check if SKU matches Google's GTIN array (for stores where SKU is the barcode). + // GTIN is stored in attributes.gtin as an array. + if ( ! empty( $product['attributes']['gtin'] ) && is_array( $product['attributes']['gtin'] ) ) { + if ( in_array( $sku, $product['attributes']['gtin'], true ) ) { + $this->logger->info( "Product matched by attributes.gtin={$sku} (SKU used as barcode)" ); + return $product; + } } - // Check if separate GTIN field matches. - if ( ! empty( $gtin ) && isset( $product['gtin'] ) && $product['gtin'] === $gtin ) { - return $product; + // Also check attributes.gtins (alternative field). + if ( ! empty( $product['attributes']['gtins'] ) && is_array( $product['attributes']['gtins'] ) ) { + if ( in_array( $sku, $product['attributes']['gtins'], true ) ) { + $this->logger->info( "Product matched by attributes.gtins={$sku} (SKU used as barcode)" ); + return $product; + } + } + + // Check if separate GTIN parameter matches. + if ( ! empty( $gtin ) ) { + if ( ! empty( $product['attributes']['gtin'] ) && is_array( $product['attributes']['gtin'] ) ) { + if ( in_array( $gtin, $product['attributes']['gtin'], true ) ) { + $this->logger->info( "Product matched by GTIN parameter={$gtin}" ); + return $product; + } + } } } }