I am trying to create a WooCommerce extension so that I can fetch products through API and store them in my WordPress store. I have been successful in storing simple products. But i'm stuck at creating variable products or any other type.
I haven't created the API yet as need to be sure of the format it needs to be in, but can be easily achieved in format as described in this link
Here is my working code for simple products :
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');
$body = wp_remote_retrieve_body($api_response);
/****** $data will be replaced by my API response data *********/
$data = [
'name' => 'Premium Quality',
'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' => '.jpg',
'position' => 0
],
[
'src' => '.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 );
}
}
UPDATE
I have looked into default WooCommerce Code and found out the class WC_REST_Product_Variations_Controller. Looks like this will solve my problem. Will update again if this works.
I am trying to create a WooCommerce extension so that I can fetch products through API and store them in my WordPress store. I have been successful in storing simple products. But i'm stuck at creating variable products or any other type.
I haven't created the API yet as need to be sure of the format it needs to be in, but can be easily achieved in format as described in this link
Here is my working code for simple products :
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 will be replaced by my API response data *********/
$data = [
'name' => 'Premium Quality',
'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 );
}
}
UPDATE
I have looked into default WooCommerce Code and found out the class WC_REST_Product_Variations_Controller. Looks like this will solve my problem. Will update again if this works.
After a lot of searching and banging my head everywhere I have successfully implemented to add WooCommerce products through Rest API. Here is my complete working code for reference :-
$api_response = wp_remote_get('www.myapi.com');
$body = wp_remote_retrieve_body($api_response);
/****** API not ready yet...working on it *******/
$data = [
'type' => 'variable',
'description' => 'Trying it out for real',
'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' => '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'
]
],
'variations' => [
[
'regular_price' => '29.98',
'attributes' => [
[
'slug'=>'color',
'name'=>'Color',
'option'=>'Black'
]
]
],
[
'regular_price' => '69.98',
'attributes' => [
[
'slug'=>'color',
'name'=>'Color',
'option'=>'Green'
]
]
]
]
];
$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;
// The created product must have variations
// If it doesn't, it's the new WC3+ API which forces us to build those manually
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'),
)
)
);
}
here I have registered api rest route create createProduct and defined below how to create wc product using api and here I have used base64 images for products image upload and created a separate function for base64 image upload
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("Product Created Successfully", $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("Variation not found", "Invalid Variation 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("Error saving variation", "Unable to save variation");
}
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("No variations found for this product.");
}
$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("Product not found or is not a variable product.");
}
}
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'] . '/' . $hashed_filename, $decoded) === false) {
return $this->errorResponse('file_save_failed', 'Failed to save the file.');
}
$attachment = array(
'post_mime_type' => 'image/' . $file_type,
'post_title' => basename($hashed_filename),
'post_content' => '',
'post_status' => 'inherit',
'guid' => $upload_dir['url'] . '/' . basename($hashed_filename)
);
$attach_id = wp_insert_attachment($attachment, $upload_dir['path'] . '/' . $hashed_filename);
$attach_data = wp_generate_attachment_metadata($attach_id, $upload_dir['path'] . '/' . $hashed_filename);
wp_update_attachment_metadata($attach_id, $attach_data);
return $attach_id;
} else {
return $this->errorResponse('invalid_base64', 'Invalid Base64 image format.');
}
}
its the best way to create a woo commerce product with variations you can create or use product id to update product details here is the json data for this api use it with postman to see how it works
{
"name": "Variable Product",
"status": "publish",
"catalog_visibility": "visible",
"description": "This is a variable product description.",
"short_description": "Short description of the product.",
"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": {
"Color": ["Red", "Blue", "Green"],
"Size": ["Small", "Medium", "Large"]
},
"variations": [
{
"attributes": {
"Color": "Red",
"Size": "Small"
},
"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": {
"Color": "Blue",
"Size": "Medium"
},
"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..." //image data url
}
]
}