WC_CREATE not setting billing or shipping address - woocommerce

favorite
I am trying to create a new order and my code as follows
{
$products = $_POST['products'];
$shipping_address = $_POST['shipping_address'];
$billing_address = $_POST['billing_address'];
global $woocommerce;
$args = array(
'customer_id' => get_current_user_id(),
);
$order = wc_create_order($args);
foreach ($products as $product) {
$order->add_product(get_product($product['id']), $product['quantity']);
}
$order->set_address($shipping_address, 'shipping');
$order->set_address($billing_address, 'billing');
$order->calculate_totals();
wp_send_json(array("success" => true, "order" => $order));
}
Questions
1.Shipping address and billing address are not updating. (Refer image). I am passing the fields as
https://docs.woocommerce.com/document/tutorial-customising-checkout-fields-using-actions-and-filters/
shown in billing and shipping.
2.I need to have custom field, like (preferred pickup date), how to add that field as meta_data to that order
3.How to get the newly created order_id i.e, successful or error
How to attach coupon to that totals

1, You need to use $order->save(); to save updates you make to the order.
2, Use $order->update_meta_data( 'meta_field', $data ); and don't forget to $order->save();
3, You get the id from $order via $order->get_id();
4, Did not try coupon, but I am sure you will work that out.

Related

How to get orders of a user in Wordpress?

Wordpress Version 5.3.2
Woocommerce Version 3.8.1
To acheive Show user his purchased orders along with order_items (products in the order)
What I have tried
Saw How to get WooCommerce order details , Get some order and order items data in Woocommerce emails ,https://github.com/woocommerce/woocommerce/wiki/wc_get_orders-and-WC_Order_Query
Still couldn't solve my issue.
Error I am facing
Fatal error: Uncaught Error: Call to a member function get_id() on
array
Code
//got the user
$user = wp_get_current_user();
//In my case $user->ID returns 1
$args = array(
'customer_id' => $user->ID,
'status' => 'confirmed',
);
//Since i only want the confirmed orders
$order= wc_get_orders( $args );
$order_id = $order->get_id();
I was struggling a bit more after the accepted solution.
Initially i was getting a complete array of orders, After iterating through that array i found what i was looking for.
$user = wp_get_current_user();
$args = array(
//'customer_id' => $user->ID
'customer_id' => 6
);
$orders = wc_get_orders($args);
foreach($orders as $order){
$order_id = $order->get_id();
echo $order_id . "<br/>";
}
This foreach allowed accessing the order_id i required.
As you can see from the docs, wc_get_orders returns an array or stdClass. The error message tells you that you cannot call get_id of an array, so you have an array. Because the customer you are searching with has multiple confirmed orders. Solution:
//...
$orders = wc_get_orders( $args );
if (!is_array($orders)) $orders = [$orders];
//...

Custom product attributes is blank even though I add it [duplicate]

The products in my clients website require certain attributes which I have added via Products -> Attributes in the Wordpress administration. In this import script I'm coding I need to use the function update_post_meta($post_id, $meta_key, $meta_value) to import the proper attributes and values.
Currently I have the function like so:
update_post_meta( $post_id, '_product_attributes', array());
However I'm not sure how to properly pass along the attributes and their values?
Right so it took me a while to figure it out myself but I finally managed to do this by writing the following function:
// #param int $post_id - The id of the post that you are setting the attributes for
// #param array[] $attributes - This needs to be an array containing ALL your attributes so it can insert them in one go
function wcproduct_set_attributes($post_id, $attributes) {
$i = 0;
// Loop through the attributes array
foreach ($attributes as $name => $value) {
$product_attributes[$i] = array (
'name' => htmlspecialchars( stripslashes( $name ) ), // set attribute name
'value' => $value, // set attribute value
'position' => 1,
'is_visible' => 1,
'is_variation' => 1,
'is_taxonomy' => 0
);
$i++;
}
// Now update the post with its new attributes
update_post_meta($post_id, '_product_attributes', $product_attributes);
}
// Example on using this function
// The attribute parameter that you pass along must contain all attributes for your product in one go
// so that the wcproduct_set_attributes function can insert them into the correct meta field.
$my_product_attributes = array('hdd_size' => $product->hdd_size, 'ram_size' => $product->ram_size);
// After inserting post
wcproduct_set_attributes($post_id, $my_product_attributes);
// Woohay done!
I hope this function will help other people if they need to import multiple attributes pro-grammatically in WooCommerce!
I tried Daniel's answer, and it didn't work for me. It might be that the Wordpress/Woocommerce code has changed since, or perhaps I didn't quite understand how to do it, but either way that code did nothing for me. After a lot of work using it as a base, however, I came up with this snippet of code and put it on my theme's functions.php:
function wcproduct_set_attributes($id) {
$material = get_the_terms( $id, 'pa_material');
$material = $material[0]->name;
// Now update the post with its new attributes
update_post_meta($id, '_material', $material);
}
// After inserting post
add_action( 'save_post_product', 'wcproduct_set_attributes', 10);
With this, I can take what I set as "material" on my WooCommerce install as a custom attribute and add it to the formal meta as _material. This in turn allows me to use another snippet of code so the WooCommerce search function extends to meta fields, meaning I can search for a material in the WooCommerce search field and have all items with that material appear.
I hope this is useful to somebody.
#Daniels's answer works, won't decide on right or wrong, however if you want to add the values as a taxonomy term under attributes you have to adapt the code as below (set is_taxonomy = 1). Otherwise Woocommerce sees it as custom meta field(?). It still adds the value under attributes. This will only work for strings. For values that are arrays the code has to be adapted.
Additionally it uses the wp_set_object_terms that #Anand suggests as well. I was using that, because all the documentation I could find led to believe that had to be used. However if one only uses the wp_set_object_terms then I couldn't see the attributes in the edit product screen. Using the information from both answers and reading on the subject resulted in the solution.
You will need to tweak the code for things such as product variations.
/*
* Save Woocommerce custom attributes
*/
function save_wc_custom_attributes($post_id, $custom_attributes) {
$i = 0;
// Loop through the attributes array
foreach ($custom_attributes as $name => $value) {
// Relate post to a custom attribute, add term if it does not exist
wp_set_object_terms($post_id, $value, $name, true);
// Create product attributes array
$product_attributes[$i] = array(
'name' => $name, // set attribute name
'value' => $value, // set attribute value
'is_visible' => 1,
'is_variation' => 0,
'is_taxonomy' => 1
);
$i++;
}
// Now update the post with its new attributes
update_post_meta($post_id, '_product_attributes', $product_attributes);
}
Then call the function:
$custom_attributes = array('pa_name_1' => $value_1, 'pa_name_2' => $value_2, 'pa_name_3' => $value_3);
save_wc_custom_attributes($post_id, $custom_attributes);
Thank you for posting the code Daniel & Anand. It helped me a great deal.
Don't know if this is the "correct" way to do this... But I needed a function to add ACF repeater fields with a date value as a attribute on post save, so this was the function I came up with:
add_action( 'save_post', 'ed_save_post_function', 10, 3 );
function ed_save_post_function( $post_ID, $post, $update ) {
//print_r($post);
if($post->post_type == 'product')
{
$dates = get_field('course_dates', $post->ID);
//print_r($dates);
if($dates)
{
$date_arr = array();
$val = '';
$i = 0;
foreach($dates as $d)
{
if($i > 0)
{
$val .= ' | '.date('d-m-Y', strtotime($d['date']));
}
else{
$val .= date('d-m-Y', strtotime($d['date']));
}
$i++;
}
$entry = array(
'course-dates' => array(
'name' => 'Course Dates',
'value' => $val,
'position' => '0',
'is_visible' => 1,
'is_variation' => 1,
'is_taxonomy' => 0
)
);
update_post_meta($post->ID, '_product_attributes', $entry);
}
}
}
Hope this helps someone.

Wordpress: save custom billing field in account Billing address

Using Wordpress/Woocommerce.
I have this code which adds a custom billing field in checkout page called: "NIF/CIF". It works fine but its value it not saved in the customer account "Billing Address" data.
Once the customer makes a first order all billing address values are saved in his account: Address, State, Country, etc. But my custom field is not saved.
I guess that in my function is missing a line of code to save its value in the database, but I don't know how to start with this.
/*******************************
CUSTOM BILLING FIELD
*********************************/
add_filter('woocommerce_billing_fields', 'custom_woocommerce_billing_fields');
function custom_woocommerce_billing_fields($fields)
{
$fields['nif_cif'] = array(
'label' => __('NIF/CIF', 'woocommerce'), // Add custom field label
'placeholder' => _x('NIF/CIF', 'placeholder', 'woocommerce'), // Add custom field placeholder
'required' => true, // if field is required or not
'clear' => false, // add clear or not
'type' => 'text', // add field type
'class' => array('my-css') // add class name
);
return $fields;
}
Here is an example of how to save your custom field:
add_action( 'woocommerce_checkout_order_processed', 'prefix_save_field_on_checkout', 11, 2 );
function checkout_order_processed_add_referral_answer( $order_id, $posted ) {
if ( ! isset( $_POST['nif_cif'] ) ) {
return;
}
$order = wc_get_order( $order_id );
// WC < 3.0
update_post_meta( $order->id, 'order_meta_field_name', wc_clean( $_POST['nif_cif'] ) );
// WC > 3.0
$order->add_meta_data( 'order_meta_field_name', wc_clean( $_POST['nif_cif'] ), true );
$order->save();
}
Adding an extra field through 'woocommerce_billing_fields' hook is not enough. you are missing out two things.
Proper validation of NIF/CIF field using
'woocommerce_after_checkout_validation' hook
Saving data in order
using 'woocommerce_checkout_order_processed' hook

How can I show the shipping cost in each product on checkout page. Woocommerce

I need to show shipping cost of each vendor in front of product at checkout page. enter image description here
I tried with
get_post_meta($cart_item['product_id'] , '_wcv_shipping_details', true);
But this return with blank value like:
Array ( [national] => [international] => [handling_fee] => [national_qty_override] => [national_disable] => [national_free] => [international_qty_override] => [international_disable] => [international_free] => )
I think you are trying to access cart object on order details page. Once the order is placed, the cart object will get empty. You will need to get items from the object of order and then fetch shipping cost for each item.
// You can use this piece of code on thank you page (after order is placed)
$order = new WC_Order( $order_id );
$order_item = $order->get_items();
foreach( $order_item as $product ) {
$prodct_name[] = $product['name'];
// here you will get product id and you can use that to get shipping details
get_post_meta($product['product_id'] , '_wcv_shipping_details', true);
}

How to add short description in WooCommerce checkout page

Thanks for reading, Just had a issue regarding WooCommerce, I want to add a short description checkout page of below billing field.
How to add short description in WooCommerce checkout page of below billing field?
I tried add function, custom code but failed with error.
add_filter( 'woocommerce_get_item_data', 'wc_checkout_description_so_27900033', 10, 2 );
function wc_checkout_description_so_27900033( $other_data, $cart_item )
{
$post_data = get_post( $cart_item['product_id'] );
$other_data[] = array( 'name' => 'description', 'value' => $post_data->post_excerpt );
return $other_data;
}
I was used this code but it is showing inner product info table.
There's no real reason to call get_post(). The $product object is stored in the $cart_item array and the $post object is stored inside the $product. This gets the product's excerpt (aka the short description) to show up in the cart and in the checkout. Now, it isn't likely the make the description show up on the order received page, or in the my account area, or in emails, etc since the only place that the woocommerce_get_item_data filter appears is in the cart class.
One thing to take note of, WooCommerce 2.7 is a major rewrite of WooCommerce and $_product->post->post_excerpt will result in PHP notices about directly accessing product properties. So I've suggested both the 2.6 and 2.7 compatible approaches.
add_filter( 'woocommerce_get_item_data', 'wc_checkout_description_so_27900033', 10, 2 );
function wc_checkout_description_so_27900033( $other_data, $cart_item )
{
$_product = $cart_item['data'];
// Use this for WC2.7
//$other_data[] = array( 'name' => 'description', 'value' => $_product->get_short_description() );
// Use this for WC2.6
$other_data[] = array( 'name' => 'description', 'value' => $_product->post->post_excerpt );
return $other_data;
}

Resources