Добавление продуктов в Woocommerce через WP API

Вопрос или проблема

Я пытаюсь создать расширение WooCommerce, чтобы я мог получать товары через API и сохранять их в своем магазине WordPress. Мне удалось сохранить простые продукты. Но я застрял на создании переменных продуктов или любого другого типа.

Я ещё не создал API, так как нужно быть уверенным в формате, который он должен иметь, но это можно легко сделать в формате, описанном в этой ссылке.

Вот мой рабочий код для простых продуктов:

if (in_array( 'woocommerce/woocommerce.php', apply_filters( 'active_plugins', get_option( 'active_plugins' ) ) )) { 
function create_wc_product_by_api(){
    $api_response = wp_remote_get('www.myapi.com');
    $body = wp_remote_retrieve_body($api_response);

    /****** $data будет заменено данными ответа моего API *********/
    $data = [
        'name' => 'Высокое качество',
        'type' => 'simple',
        'regular_price' => '21.99',
        'description' => 'Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Vestibulum tortor quam, feugiat vitae, ultricies eget, tempor sit amet, ante. Donec eu libero sit amet quam egestas semper. Aenean ultricies mi vitae est. Mauris placerat eleifend leo.',
        'short_description' => 'Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas.',
        'categories' => [
            [
                'id' => 9
            ],
            [
                'id' => 14
            ]
        ],
        'images' => [
            [
                'src' => 'http://demo.woothemes.com/woocommerce/wp-content/uploads/sites/56/2013/06/T_2_front.jpg',
                'position' => 0
            ],
            [
                'src' => 'http://demo.woothemes.com/woocommerce/wp-content/uploads/sites/56/2013/06/T_2_back.jpg',
                'position' => 1
            ]
        ]
    ];

    $wp_rest_request = new WP_REST_Request( 'POST' );
    $wp_rest_request->set_body_params( $data );

    $products_controller = new WC_REST_Products_Controller;

    $wp_rest_response = $products_controller->create_item( $wp_rest_request );

}

}

ОБНОВЛЕНИЕ

Я изучил стандартный код WooCommerce и нашел класс WC_REST_Product_Variations_Controller. Похоже, это решит мою проблему. Буду обновлять, если это сработает.

После долгих поисков и ломания головы мне удалось добавить продукты WooCommerce через Rest API. Вот мой полностью рабочий код для справки:

    $api_response = wp_remote_get('www.myapi.com');
    $body = wp_remote_retrieve_body($api_response);

    /****** API ещё не готов... работаю над этим *******/
    $data = [
        'type' => 'variable',
        'description' => 'Пробуем всерьёз',
        'short_description' => 'Pellentesque habitant.',
        'categories' => [
            [
                'id' => 37
            ],
            [
                'id' => 38
            ]
        ],
        'images' => [
            [
                'src' => 'http://demo.woothemes.com/woocommerce/wp-content/uploads/sites/56/2013/06/T_4_front.jpg',
                'position' => 0
            ]
        ],
        'attributes' => [
            [
                'name' => 'Цвет',
                'position' => 0,
                'visible' => true,
                'variation' => true,
                'options' => [
                    'Черный',
                    'Зелёный'
                ]
            ],
            [
                'name' => 'Размер',
                'position' => 0,
                'visible' => true,
                'variation' => true,
                'options' => [
                    'S',
                    'M'
                ]
            ]
        ],
        'default_attributes' => [
            [
                'name' => 'Цвет',
                'option' => 'Черный'
            ],
            [
                'name' => 'Размер',
                'option' => 'S'
            ]
        ],
        'variations' => [ 
            [
                'regular_price' => '29.98', 
                'attributes' => [ 
                    [
                        'slug'=>'color',
                        'name'=>'Цвет',
                        'option'=>'Черный'
                    ]
                ]   
            ],
            [
                'regular_price' => '69.98',
                'attributes' => [
                    [
                        'slug'=>'color', 
                        'name'=>'Цвет', 
                        'option'=>'Зелёный'
                    ]
                ]
            ] 
        ]
    ];

    $wp_rest_request = new WP_REST_Request( 'POST' );
    $wp_rest_request->set_body_params( $data );
    $products_controller = new WC_REST_Products_Controller;
    $res = $products_controller->create_item( $wp_rest_request );
    $res = $res->data;

    // Созданный продукт должен иметь вариации
    // Если их нет, это новый API WC3+, который заставляет нас создавать их вручную
    if ( !isset( $res['variations'] ) ){
        $res['variations'] = array();
    }
    if ( count( $res['variations'] ) == 0 && count( $data['variations'] ) > 0 ) {
        if ( ! isset( $variations_controler ) ) {
            $variations_controler = new WC_REST_Product_Variations_Controller();
        }
        foreach ( $data['variations'] as $variation ) {

            $wp_rest_request = new WP_REST_Request( 'POST' );
            $variation_rest = array(
                'product_id' => $res['id'],
                'regular_price' => $variation['regular_price'],
                'attributes' => $variation['attributes'],
            );
            $wp_rest_request->set_body_params( $variation_rest );
            $new_variation = $variations_controler->create_item( $wp_rest_request );
            $res['variations'][] = $new_variation->data;
        }
    }

      register_rest_route(
            'custom_api/v1',
            '/createProduct',
            array(
                array(
                    'methods' => 'POST',
                    'callback' => array($this, 'createProduct'),
                )
            )
        );
    }

здесь я зарегистрировал API маршрут createProduct и определил ниже, как создать продукт WooCommerce, используя API; здесь я использовал изображения base64 для загрузки изображений продуктов и создал отдельную функцию для загрузки изображений base64

public function createProduct($request)
{
    $param = $request->get_params();

    if (isset($param['product_id']) && !empty($param['product_id'])) {
        $product = wc_get_product($param['product_id']);
    } else {
        $product = new WC_Product_Variable();
    }

    $product->set_name($param['name']);
    $product->set_status($param['status']);
    $product->set_catalog_visibility($param['catalog_visibility']);
    $product->set_description($param['description']);
    $product->set_short_description($param['short_description']);
    $product->set_sku($param['sku']);
    $product->set_price(0);
    $product->set_regular_price($param['regular_price']);
    $product->set_manage_stock(true);
    $product->set_stock_quantity($param['stock_quantity']);

    if (!empty($param['cat_ids'])) {
        $category_ids = is_array($param['cat_ids']) ? $param['cat_ids'] : json_decode($param['cat_ids'], true);
        $product->set_category_ids($category_ids);
    }

    if (isset($param['image_base64'])) {
        $image_ids = [];
        foreach ((array) $param['image_base64'] as $base64_encode) {
            $attachment_id = $this->upload_image_base64($base64_encode);
            if ($attachment_id) {
                $image_ids[] = $attachment_id;
            }
        }

        if (!empty($image_ids)) {
            $product->set_image_id($image_ids[0]);
            array_shift($image_ids);
            $product->set_gallery_image_ids($image_ids);
        }
    }

    if (isset($param['attributes'])) {
        $attributes = [];
        foreach ($param['attributes'] as $name => $options) {
            $attribute = new WC_Product_Attribute();
            $attribute->set_name($name);
            $attribute->set_options($options);
            $attribute->set_position(1);
            $attribute->set_visible(true);
            $attribute->set_variation(true);
            $attributes[] = $attribute;
        }
        $product->set_attributes($attributes);
    }

    $product->save();

    if (isset($param['variations'])) {
        foreach ($param['variations'] as $variation_data) {
            $this->saveProductVariation($product->get_id(), $variation_data);
        }
    }

    $result = $this->get_variable_product_details($product->get_id());
    return $this->successResponse("Продукт успешно создан", $result);
}

private function saveProductVariation($product_id, $variation_data)
{

    if (isset($variation_data['id'])) {
        $variation = wc_get_product($variation_data['id']);
        if (!$variation || $variation->get_type() !== 'variation') {
            return $this->errorResponse("Вариация не найдена", "Недопустимый ID вариации");
        }
    } else {
        $variation = new WC_Product_Variation();
        $variation->set_parent_id($product_id);
    }

    $variation->set_attributes($variation_data['attributes']);
    $variation->set_sku($variation_data['sku']);
    $variation->set_regular_price($variation_data['regular_price']);
    $variation->set_sale_price($variation_data['sale_price']);
    $variation->set_weight($variation_data['weight']);
    $variation->set_length($variation_data['length']);
    $variation->set_width($variation_data['width']);
    $variation->set_height($variation_data['height']);

    if (!empty($variation_data['image_base64'])) {
        $image_id = $this->upload_profile_image_base64($variation_data['image_base64']);
        $variation->set_image_id($image_id);
    }

    if (isset($variation_data['manage_stock']) && $variation_data['manage_stock']) {
        $variation->set_manage_stock(true);
        $variation->set_stock_quantity($variation_data['stock_quantity']);
        $variation->set_stock_status('instock');
    } else {
        $variation->set_manage_stock(false);
    }

    $variation_id = $variation->save();
    return $variation_id ? $variation_id : $this->errorResponse("Ошибка сохранения вариации", "Невозможно сохранить вариацию");
}

private function get_variable_product_details($product_id)
{
    $product = wc_get_product($product_id);

    if ($product && $product->is_type('variable')) {
        $product_data = array(
            'ID' => $product->get_id(),
            'Name' => $product->get_name(),
            'Description' => $product->get_description(),
            'Short Description' => $product->get_short_description(),
            'SKU' => $product->get_sku(),
            'Price' => $product->get_price(),
            'Stock Status' => $product->get_stock_status(),
            'Attributes' => $product->get_attributes(),
            'Image' => wp_get_attachment_url($product->get_image_id())
        );

        $variation_ids = $product->get_children();
        if (empty($variation_ids)) {
            return $this->errorResponse("Для этого продукта вариации не найдены.");
        }

        $variation_data = array();

        foreach ($variation_ids as $variation_id) {
            $variation_product = wc_get_product($variation_id);
            $variation_data[] = array(
                'Variation ID' => $variation_product->get_id(),
                'Attributes' => $variation_product->get_attributes(),
                'Regular Price' => $variation_product->get_regular_price(),
                'Sale Price' => $variation_product->get_sale_price(),
                'SKU' => $variation_product->get_sku(),
                'Stock Status' => $variation_product->get_stock_status(),
                'Weight' => $variation_product->get_weight(),
                'Height' => $variation_product->get_height(),
                'Width' => $variation_product->get_width(),
                'Length' => $variation_product->get_length()
            );
        }

        $response = array();
        $response['product_data'] = $product_data;
        $response['variation_data'] = $variation_data;

        return $response;
    } else {
        return $this->errorResponse("Продукт не найден или не является переменным продуктом.");
    }
}

public  function upload_image_base64($base64_image)
{
    if (preg_match('/^data:image\/(\w+);base64,/', $base64_image, $type)) {
        $upload_dir         =   wp_upload_dir();
        $base64             =   explode(';base64', $base64_image);
        $decoded            =   base64_decode($base64[1]);
        $filename="profile_image";
        $file_type          =   strtolower($type[1]);;
        $hashed_filename    =   md5($filename . microtime()) . '.' . $file_type;

        if (file_put_contents($upload_dir['path'] . "https://wordpress.stackexchange.com/" . $hashed_filename, $decoded) === false) {
            return $this->errorResponse('file_save_failed', 'Не удалось сохранить файл.');
        }

        $attachment         =   array(
            'post_mime_type' => 'image/' . $file_type,
            'post_title'     =>  basename($hashed_filename),
            'post_content'   => '',
            'post_status'    => 'inherit',
            'guid'           => $upload_dir['url'] . "https://wordpress.stackexchange.com/" . basename($hashed_filename)
        );

        $attach_id = wp_insert_attachment($attachment, $upload_dir['path'] . "https://wordpress.stackexchange.com/" . $hashed_filename);
        $attach_data = wp_generate_attachment_metadata($attach_id, $upload_dir['path'] . "https://wordpress.stackexchange.com/" . $hashed_filename);
        wp_update_attachment_metadata($attach_id, $attach_data);
        return $attach_id;
    } else {
        return $this->errorResponse('invalid_base64', 'Недопустимый формат изображения Base64.');
    }
}

это лучший способ создать продукт WooCommerce с вариациями, вы можете создать или использовать ID продукта для обновления информации о продукте, вот JSON-данные для этого API, используйте его с Postman, чтобы увидеть, как это работает

{
"name": "Переменный продукт",
"status": "publish",
"catalog_visibility": "visible",
"description": "Это описание переменного продукта.",
"short_description": "Краткое описание продукта.",
"sku": "SAMPLE-SKU-001",
"regular_price": "100.00",
"stock_quantity": 10,
"cat_ids": [12, 15],
"image_base64": [
    "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUA...",
    "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUA..."
],
"attributes": {
    "Цвет": ["Красный", "Синий", "Зелёный"],
    "Размер": ["Маленький", "Средний", "Большой"]
},
"variations": [
    {
        "attributes": {
            "Цвет": "Красный",
            "Размер": "Маленький"
        },
        "sku": "VARIATION-RED-SMALL",
        "regular_price": "105.00",
        "sale_price": "95.00",
        "stock_quantity": 5,
        "manage_stock": true,
        "weight": "1.5",
        "length": "10",
        "width": "5",
        "height": "2",
        "image_base64": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUA..."
    },
    {
        "attributes": {
            "Цвет": "Синий",
            "Размер": "Средний"
        },
        "sku": "VARIATION-BLUE-MEDIUM",
        "regular_price": "110.00",
        "sale_price": "100.00",
        "stock_quantity": 8,
        "manage_stock": true,
        "weight": "1.8",
        "length": "12",
        "width": "6",
        "height": "3",
        "image_base64": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUA..." //данные изображения URL
    }
]

}

Ответ или решение

Добавление товаров в WooCommerce через WP API: Подробное руководство

Создание и управление продуктами в WooCommerce с использованием REST API может значительно упростить взаимодействие и автоматизацию процессов в интернет-магазине. Данная статья посвящена решению задачи создания различных типов продуктов, включая переменные продукты, с использованием WP API. В данном контексте мы исследуем использование существующих контроллеров WooCommerce, таких как WC_REST_Products_Controller и WC_REST_Product_Variations_Controller.

Функциональность

Основная цель заключается в том, чтобы через запросы к API добавлять в WooCommerce не только простые, но и переменные продукты. Переменные продукты позволяют создавать несколько вариаций одного товара (например, различие в цвете или размере), что особенно актуально для магазинов с широкой номенклатурой товаров.

Шаги по добавлению продуктов

1. Создание простого продукта

Для создания простого продукта можно использовать следующий код, который задействует WC_REST_Products_Controller:

if (in_array( 'woocommerce/woocommerce.php', apply_filters( 'active_plugins', get_option( 'active_plugins' ) ) )) {
    function create_wc_product_by_api() {
        $api_response = wp_remote_get('www.myapi.com');
        $body = wp_remote_retrieve_body($api_response);

        $data = [
            'name' => 'Premium Quality',
            'type' => 'simple',
            'regular_price' => '21.99',
            'description' => 'Превосходное качество и долговечность.',
            'short_description' => 'Превосходное качество.',
            'categories' => [
                ['id' => 9],
                ['id' => 14]
            ],
            'images' => [
                ['src' => 'http://example.com/image1.jpg', 'position' => 0],
                ['src' => 'http://example.com/image2.jpg', 'position' => 1]
            ]
        ];

        $wp_rest_request = new WP_REST_Request( 'POST' );
        $wp_rest_request->set_body_params( $data );

        $products_controller = new WC_REST_Products_Controller;
        $products_controller->create_item( $wp_rest_request );
    }
}

2. Создание переменного продукта

Создание переменного продукта требует более сложного подхода, поскольку необходимо задать атрибуты и вариации. Сначала вам нужно определить сами атрибуты продукта, а затем создать вариации на их основе.

$data = [
    'type' => 'variable',
    'description' => 'Подробное описание переменного товара.',
    'short_description' => 'Краткое описание.',
    'categories' => [
        ['id' => 37],
        ['id' => 38]
    ],
    'images' => [
        ['src' => 'http://example.com/variable-product.jpg', 'position' => 0]
    ],
    'attributes' => [
        [
            'name' => 'Color',
            'position' => 0,
            'visible' => true,
            'variation' => true,
            'options' => ['Black', 'Green']
        ],
        [
            'name' => 'Size',
            'position' => 0,
            'visible' => true,
            'variation' => true,
            'options' => ['S', 'M']
        ]
    ],
    'default_attributes' => [
        [
            'name' => 'Color',
            'option' => 'Black'
        ],
        [
            'name' => 'Size',
            'option' => 'S'
        ]
    ]
];

$wp_rest_request = new WP_REST_Request( 'POST' );
$wp_rest_request->set_body_params( $data );
$products_controller = new WC_REST_Products_Controller;
$res = $products_controller->create_item( $wp_rest_request );

// Создание вариаций
if (!isset($res['variations'])) {
    $res['variations'] = array();
}
if (count($res['variations']) == 0 && count($data['variations']) > 0) {
    $variations_controller = new WC_REST_Product_Variations_Controller();
    foreach ($data['variations'] as $variation) {
        $wp_rest_request = new WP_REST_Request( 'POST' );
        $variation_rest = [
            'product_id' => $res['id'],
            'regular_price' => $variation['regular_price'],
            'attributes' => $variation['attributes']
        ];
        $wp_rest_request->set_body_params( $variation_rest );
        $variations_controller->create_item( $wp_rest_request );
    }
}

Заключение

Работа с мультитипами продуктов в WooCommerce через REST API требует тщательной настройки данных запросов и детального понимания работы с атрибутами и вариациями. Ключевыми компонентами здесь являются класс контроллера продуктов и контроллер вариаций, которые обеспечивают гибкость и расширяемость системы.

Этот универсальный подход поможет вам не только создавать, но также управлять вариативными продуктами, что даст вашему интернет-магазину гораздо больше возможностей для сегментации и улучшения обслуживания клиентов. Типичная структура данных может быть дополнена индивидуальными атрибутами и вариациями в соответствии с вашими конкретными требованиями бизнеса.

Оцените материал
Добавить комментарий

Капча загружается...