apiservice = syncBasalamContainer()->get(ApiServiceManager::class); $this->validator = $validator ?: new CreateProductDataValidator(); } public function createProductInBasalam($productData, $productId) { $productData = apply_filters('sync_basalam_product_data_before_create', $productData, $productId); $this->ValidCreateProductData($productData, $productId); do_action('sync_basalam_before_create_product_api', $productId, $productData); $vendorId = syncBasalamSettings()->getSettings(SettingsConfig::VENDOR_ID); $url = sprintf(Endpoints::PRODUCT_CREATE, $vendorId); $maxDescriptionRetries = 3; $descriptionRetry = 0; while (true) { try { $request = $this->apiservice->post($url, $productData); break; } catch (RetryableException $e) { throw $e; } catch (NonRetryableException $e) { if ($descriptionRetry < $maxDescriptionRetries && $this->stripForbiddenDescription($e, $productData, $productId, $descriptionRetry)) { $descriptionRetry++; continue; } throw $e; } catch (\Exception $e) { throw new \Exception(esc_html($e->getMessage())); } } if ($request['status_code'] != 201 && isset($request['status_code'])) { $body = $request['body'] ?? ''; if (is_string($body)) $responseData = json_decode($body, true); else $responseData = $body; if (!is_array($responseData)) $responseData = []; if ($responseData && isset($responseData['messages'][0])) { $message = $responseData['messages'][0]['message'] ?? 'خطای نامشخص'; $field = $responseData['messages'][0]['fields'][0] ?? ''; } else { $message = 'درخواست با تایم اوت مواجه شد.'; $field = ''; } $errorMessage = 'فرایند اضافه کردن محصول ناموفق بود: ' . esc_html($message); if ($field) $errorMessage .= ' (فیلد: ' . esc_html($field) . ')'; throw new \Exception(esc_html($errorMessage)); } if (is_wp_error($request)) { $body = $request['body'] ?? ''; if (is_string($body)) $responseData = json_decode($body, true); else $responseData = $body; $message = $responseData[0]['message'] ?? 'خطای نامشخص'; throw new \Exception('درخواست موفقیت آمیز نبود: ' . esc_html($message)); } $responseData = json_decode($request['body'], true); if (isset($responseData['id'])) { if (isset($responseData['variants'])) { $product = wc_get_product($productId); if ($product && $product->is_type('variable')) { $wcVariations = []; $attributes = $product->get_attributes(); foreach ($product->get_children() as $variationId) { $variation = wc_get_product($variationId); $attributeValues = []; foreach ($attributes as $attributeName => $attribute) { if ($attribute->get_variation()) { $cleanAttributeName = str_replace('attribute_', '', $attributeName); $value = $variation->get_attribute($cleanAttributeName); $value = urldecode($value); $value = trim($value); $value = mb_strtolower($value, 'UTF-8'); $value = str_replace(['ي', 'ك'], ['ی', 'ک'], $value); $value = str_replace(['-', '_', '–', '—'], ' ', $value); $value = preg_replace('/\s+/', ' ', $value); if (!empty($value)) { $attributeValues[] = $value; } } } if (!empty($attributeValues)) { $key = implode("_", $attributeValues); $wcVariations[$key] = $variationId; } } $syncBasalamVariations = []; foreach ($responseData['variants'] as $variant) { $attributeValues = []; if (!empty($variant['properties'])) { foreach ($variant['properties'] as $property) { $val = trim($property['value']['title']); $val = mb_strtolower($val, 'UTF-8'); $val = str_replace(['ي', 'ك'], ['ی', 'ک'], $val); $val = str_replace(['-', '_', '–', '—'], ' ', $val); $val = preg_replace('/\s+/', ' ', $val); if (!empty($val)) { $attributeValues[] = $val; } } } if (!empty($attributeValues)) { $key = implode("_", $attributeValues); $syncBasalamVariations[$key] = $variant['id']; } } $variationMapping = []; foreach ($wcVariations as $key => $wcVarId) { if (isset($syncBasalamVariations[$key])) { $variationMapping[$wcVarId] = $syncBasalamVariations[$key]; update_post_meta($wcVarId, 'sync_basalam_variation_id', $syncBasalamVariations[$key]); } } } } update_post_meta($productId, ProductMetaKey::basalamProductId(), $responseData['id']); update_post_meta($productId, ProductMetaKey::basalamProductStatus(), 2976); update_post_meta($productId, ProductMetaKey::basalamProductSyncStatus(), 'synced'); $result = [ 'success' => true, 'message' => 'محصول با موفقیت به باسلام اضافه شد.', 'status_code' => 200, 'basalam_id' => $responseData['id'], ]; do_action('sync_basalam_after_create_product_api', $productId, $responseData, $result); return $result; } throw new \Exception("فرایند اضافه کردن محصول ناموفق بود"); } private function stripForbiddenDescription(NonRetryableException $e, array &$productData, int $productId, int $attempt): bool { if (!isset($productData['description']) || !is_string($productData['description'])) return false; $values = DescriptionErrorSanitizer::extractDescriptionValues($e->getResponseData()); if (empty($values)) return false; $cleaned = DescriptionErrorSanitizer::sanitize($productData['description'], $values); if ($cleaned === $productData['description']) return false; $productData['description'] = $cleaned; return true; } private function ValidCreateProductData(array $productData, int $productId): void { $validation = $this->validator->validate($productData, $productId); if (!$validation['valid']) { throw NonRetryableException::invalidData(esc_html($validation['message'])); } } }