I am trying to get woocommerce thank you page order_id. Using the code below.
But unfortunately I can't get it.
add_action( 'woocommerce_thankyou', 'bbloomer_check_order_product_id');
function bbloomer_check_order_product_id( $order_id ){
$order = new WC_Order( $order_id );
$items = $order->get_items();
foreach ( $items as $item ) {
$product_id = $item['product_id'];
if ( $product_id == XYZ ) {
// do something
}
}
}
This code is outdated for WooCommerce version 3+. You should use instead:
add_action( 'woocommerce_thankyou', 'check_order_product_id', 10, 1);
function check_order_product_id( $order_id ){
# Get an instance of WC_Order object
$order = wc_get_order( $order_id );
# Iterating through each order items (WC_Order_Item_Product objects in WC 3+)
foreach ( $order->get_items() as $item_id => $item_values ) {
// Product_id
$product_id = $item_values->get_product_id();
// OR the Product id from the item data
$item_data = $item_values->get_data();
$product_id = $item_data['product_id'];
# Targeting a defined product ID
if ( $product_id == 326 ) {
// do something
}
}
}
Code goes in function.php file of your active child theme (or theme) or also in any plugin file.
This code is tested and works for WooCommerce version 3+
Reference: How to get WooCommerce order details
I was not satisfied with current answers, as sometimes you need to check multiple products. If you do the same search for each product, it's really a waste, so I put it into a dispatcher format.
add_action('woocommerce_order_status_completed', 'onItemCheckout',10,1);
function onItemCheckout($order_id){
$order = wc_get_order($order_id);
foreach ($order->get_items() as $item_key => $item_values){
$product_id = $item_values->get_product_id();
switch($item_values->get_product_id()){
case 9999 : FreeShipping($order, $product_id); break;
case 1010 : RequireValidation($order, $product_id); break;
default: break;
}
}
}
Alternatively,...
$ItemCheckoutHandler=[];
$ItemCheckoutHandler[9999]='FreeShipping';
$ItemCheckoutHandler[1010]='RequireValidation';
add_action('woocommerce_order_status_completed', 'onItemCheckout',10,1);
function onItemCheckout($order_id){
global $ItemCheckoutHandler;
$order = wc_get_order($order_id);
foreach ($order->get_items() as $item_key => $item_values){
$product_id=$item_values->get_product_id();
$ItemCheckoutHandler[ $product_id ]( $order, $product_id );
} //Call the function assigned to that product id in the array
}
In either case, the assigned functions would take the order object, rather than the id, and the product_id as an argument:
function FreeShipping($order, $product_id){ ... }
function RequireValidation($order, $product_id){ ... }
You can of course customize these inputs to your liking.
Try this, hope it will work
add_action( 'woocommerce_thankyou', 'your_function_name', 10);
function your_function_name($order_id)
{
$order = wc_get_order($order_id);
foreach($order->get_items() as $order_key => $order_value)
{
$product_id = $order_value->get_data()['product_id'];
if($product_id == '123')
{
//do what you wnat and 123 is random product id, you can match product id with other as you want
}
}
}
Thank you.
Related
I use following code to re save the product variations, when there is a paid order on it, but nothing happen
add_action('woocommerce_payment_complete', 'refresh_zero_stock');
function refresh_zero_stock($order_id){
$order = new WC_Order( $order_id );
foreach ($order->get_items() as $item_key => $item ){
$item_quantity = $item->get_quantity();
if($item_quantity == 0){
$product_id = $item->get_product_id();
$product_data = wc_get_product($product_id);
if ($product_data->is_type('variable')){
$handle = new WC_Product_Variable($product_id);
$variations1=$handle->get_children();
foreach ($variations1 as $value) {
$single_variation=new WC_Product_Variation($value);
$single_variation->save();
}
}
}
}
}
what is the problem with this action hook? please help.
The hook is not the problem… The main problem is if( $item->get_quantity() == 0 ){ that is always false, where $item->get_quantity() need to be replaced with the product stock quantity instead. Try the following:
add_action('woocommerce_payment_complete', 'refresh_zero_stock');
function refresh_zero_stock( $order_id ){
$order = wc_get_order( $order_id );
foreach ($order->get_items() as $item ){
$product = $item->get_product(); // Get the current product (object)
// If stock quantity is 0 and if it's a product variation
if ( $product->get_stock_quantity() == 0 && $product->is_type('variation') ){
$parent_product = wc_get_product( $item->get_product_id() ); // Get parent variable product
// Loop through children Ids (variations ids) from the parent variable product
foreach ($parent_product->get_children() as $child_id ) {
$variation = wc_get_product( $child_id ); // Get the product variation from each child Id
$variation->save(); // refresh and save
}
}
}
}
}
Code goes in functions.php file of the active child theme (or active theme). It should better works.
As the hook woocommerce_payment_complete doesn't seems to work, try the following instead based on order status change (Note: this code will run only once for each order):
add_action( 'woocommerce_order_status_changed', 'refresh_zero_stock', 10, 4 );
function refresh_zero_stock( $order_id, $from_status, $to_status, $order ){
$variations_refreshed = $order->get_meta('_variations_refreshed');
if( in_array($to_status, array('processing', 'completed') ) && ! $variations_refreshed ) {
// Loop though order items
foreach ($order->get_items() as $item ){
$product = $item->get_product(); // Get the current product (object)
// If stock quantity is 0 and if it's a product variation
if ( $product->get_stock_quantity() == 0 && $product->is_type('variation') ){
$parent_product = wc_get_product( $item->get_product_id() ); // Get parent variable product
// Loop through children Ids (variations ids) from the parent variable product
foreach ($parent_product->get_children() as $child_id ) {
$variation = wc_get_product( $child_id ); // Get the product variation from each child Id
$variation->save(); // refresh and save
}
}
}
}
// Flag the order to make this code run only once for current order
$order->update_meta_data( '_variations_refreshed', '1' );
}
}
Code goes in functions.php file of the active child theme (or active theme). It could better works.
I find the problem. I have to add
$variation->set_manage_stock(false);
$variation->set_stock_status('outofstock');
before
$variation->save();
i try to slightly modify with +1 check for plugin located here
So , for all Virtual Downloadable Free (price=0,00) & on Backorder products I want Woocommerce to set order status 'Processing'
the result I have with code below - Woocommerce to set order status 'Pending Payment'
Are there any ideas how to switch it to 'Processing':
add_action('woocommerce_checkout_order_processed', 'handmade_woocommerce_order');
function handmade_woocommerce_order( $order_id )
{
$order = wc_get_order($order_id);
foreach ($order->get_items() as $item_key => $item_values):
$product_id = $item_values->get_product_id(); //get product id
//get prodct settings i.e virtual
$virtual_product = get_post_meta($product_id,'_virtual',true);
$downloadable_product = get_post_meta($product_id,'_downloadable',true);
$product_backordered=backorders_allowed($product_id,'_backorders',true);
$price = get_post_meta($product_id,'_regular_price',true);
$virtuald=get_option('hmade_vd');
if($virtuald=='yes' && $downloadable_product=='yes' && $virtual_product=='yes' && $product_backordered=='yes')
{
if($price=='0.00')
{
$order->update_status( 'processing' );
}
}
endforeach;
}
Note 1: use woocommerce_thankyou hook instead
Note 2: To know whether a product is virtual or downloadable you can use the following functions $product->is_virtual(); and $product->is_downloadable(); opposite get_post_meta();
More info: https://docs.woocommerce.com/wc-apidocs/class-WC_Product.html
Note 3: It is better not to perform operations in a foreach loop, use a check afterwards
function handmade_woocommerce_order( $order_id ) {
if( ! $order_id ) return;
// Get order
$order = wc_get_order( $order_id );
// get order items = each product in the order
$items = $order->get_items();
// Set variable
$found = false;
foreach ( $items as $item ) {
// Get product id
$product = wc_get_product( $item['product_id'] );
// Is virtual
$is_virtual = $product->is_virtual();
// Is_downloadable
$is_downloadable = $product->is_downloadable();
// Backorders allowed
$backorders_allowed = $product->backorders_allowed();
if( $is_virtual && $is_downloadable && $backorders_allowed ) {
$found = true;
// true, break loop
break;
}
}
// true
if( $found ) {
$order->update_status( 'processing' );
}
}
add_action('woocommerce_thankyou', 'handmade_woocommerce_order', 10, 1 );
My hooks are in theme folder/functions.php
I want tie hook with product_id from order.
tryin this method but they return nothing.
$product->get_id()
or
$product = wc_get_product( $product_id );
Full code
add_action( 'woocommerce_payment_complete', 'so_payment_complete' );
function so_payment_complete($order_id)
{
$order = wc_get_order($order_id);
$billingEmail = $order->billing_email;
$billingName = $order->billing_first_name;
$product_id = $order->product_id;
if ($product_id == 980) {
......
}
If you use Woocommerce 3.0+ version, then it should be this.
I found the answer with this link: https://wordpress.stackexchange.com/questions/97176/get-product-id-from-order-id-in-woocommerce
In an order can be multiple products, so you have to loop through them. In your code it would look like this:
add_action( 'woocommerce_payment_complete', 'so_payment_complete' );
function so_payment_complete($order_id)
{
$order = wc_get_order($order_id);
$billingEmail = $order->billing_email;
$billingName = $order->billing_first_name;
$items = $order->get_items();
foreach ( $items as $item ) {
$product_name = $item->get_name();
$product_id = $item->get_product_id();
$product_variation_id = $item->get_variation_id();
if ($product_id == 980) {
// ....
}
}
}
First Question: I want to add a user meta after buying a specific product. This specific product defines by ID. How can I achieve this?
add_action( 'woocommerce_thankyou', 'bbloomer_checkout_save_user_meta');
function bbloomer_checkout_save_user_meta( $order_id ) {
$order = wc_get_order( $order_id );
$user_id = $order->get_user_id();
if ( $order->get_total() > 100 ) {
add_user_meta( $user_id, 'custom_checkbox', 'on');
}
}
Second Question: How to remove order info for a specific user using specific product ID? after removing that wc_customer_bought_product() need show return false.
Answer to your first question:
add_action( 'woocommerce_thankyou', 'bbloomer_checkout_save_user_meta');
function bbloomer_checkout_save_user_meta( $order_id ) {
$order = wc_get_order( $order_id );
foreach ($order->get_items() as $key => $item){
$product_id = $item['product_id'];
if ($product_id == 'YOUR PRODUCT ID HERE'){
add_user_meta( $order->get_user_id(), 'product_'.$product_id, 'Bought on Order ID: '.$order->get_id());
}
}
}
In functions.php we have:
add_action( 'woocommerce_order_status_processing', 'mysite_processing', 10, 1);
then inside this function we get order items:
function mysite_processing($order_id) {
$order = wc_get_order( $order_id );
$items = $order->get_items();
foreach ( $items as $item ) {
$product_id = $item->get_product_id();
}
}
After getting the product id, we want to get the category id that product belongs. We already try with get_the_terms and has_term functions, both didn't work.
Solved, added to items for: $product = wc_get_product( $product_id );
Try below code
function mysite_processing($order_id) {
$order = wc_get_order( $order_id );
$items = $order->get_items();
foreach ( $items as $item ) {
$product_id = $item->get_product_id();
$term_list = wp_get_post_terms($product_id,'product_cat',array('fields'=>'ids'));
print_r($term_list);
$cat_id = (int) $term_list[0];
echo $cat_id;
die();
}
}