how i can retrieve all woocommerce orders in new custom plugin - php

i'm creating a new custom plugin and need to retrieve all woocommerce orders
i tried to use : wc_get_orders() function to retrieve all woocommerce orders but i got
Uncaught Error: Call to undefined function wc_get_orders()
and did this :
require_once '../woocommerce/includes/wc-order-functions.php';
but i got :
require_once(../woocommerce/includes/wc-order-functions.php): failed to open stream:
how i can retrieve all woocommerce orders

WooCommerce already provided API to get all orders https://example.com/wp-json/wc/v3/orders
For more details please see the documentation
If you want function based instead of REST API then, please do like this:
You should call your order function into the action hook woocommerce_after_register_post_type to work properly. So please enclose your function call like this:
add_action(
'woocommerce_after_register_post_type',
function() {
$orders = wc_get_orders( array( 'numberposts' => -1 ) );
var_dump( $orders );
}
);
Then you can loop through the object and fetch all the necessary details for e.g.
foreach ( $orders->get_items() as $item_id => $item ) {
$product_id = $item->get_product_id();
$variation_id = $item->get_variation_id();
$product = $item->get_product();
$name = $item->get_name();
$quantity = $item->get_quantity();
$subtotal = $item->get_subtotal();
$total = $item->get_total();
$tax = $item->get_subtotal_tax();
$taxclass = $item->get_tax_class();
$taxstat = $item->get_tax_status();
$allmeta = $item->get_meta_data();
$somemeta = $item->get_meta( '_whatever', true );
$type = $item->get_type();
}
For more details please check this article.

Related

PHP to take data from WCFM Order meta, and push into AST plugin

While im pretty hopeless at php, i feel like im getting close on this one, i just cant quite lock it in
So we have 2 plugins in the mix here WCFM & AST
In WCFM, a vendor adds a tracking number and carrier this is store in the order meta data with a meta keys of
wcfm_tracking_code
AND
wcfm_tracking_url
i found this hook elesewhere that allows me to fire a set of things to happen, once the tracking has been submitted into the system
“wcfm_after_order_mark_shipped” (Parameters -> $order_id, $order_item_id, $tracking_code, $tracking_url)
so now i want to take the above 2 order meta datas and push them into another plugin called AST
They code they provide to push data into thier system is:
<?php if ( class_exists( 'WC_Advanced_Shipment_Tracking_Actions' ) ) {
$order_id = '123'; //Replace with your order id
$tracking_provider = 'USPS'; //Replace with your shipping provider
$tracking_number = '123123'; //Replace with your tracking number
$date_shipped = '2020-06-22'; ////Replace with your shipped date
$status_shipped = 1; // 0=no,1=shipped,2=partial shipped(if partial shipped order status is enabled)
$sku = 't-shirt,blue-jeans'; //the line item (product) SKU
$qty = '1,1'; //the line item (product) quantity
if ( function_exists( 'ast_insert_tracking_number' ) ) {
ast_insert_tracking_number( $order_id, $tracking_number, $tracking_provider, $date_shipped, $status_shipped, $sku, $qty );
}
}
SO using both codes provided, can anyone show me how i can take the metadata input from WCFM and push it into AST?
Ive hired someone on upwork, and they cant even figure it out, but it seems so straightforward.
This is the code we have,it pushes the data in but it comes in looking like this
Instead of this like it should
add_action( 'wcfm_after_order_mark_shipped', 'testwr', 99, 6 );
function testwr( $order_id, $order_item_id, $tracking_code, $tracking_url, $product_id, $wcfm_tracking_data ) {
$order = wc_get_order( $order_id );
$data['order_id'] = $order_id;
$data['tracking_provider'] = $tracking_url;
$data['wcfm_tracking_code'] = $wcfm_tracking_data['wcfm_tracking_code'];
$data['date_shipped'] = $order->order_date;
$data['status_shipped'] = 1;
extract($data);
foreach ($order->get_items() as $item) {
$product = wc_get_product($item->get_product_id());
$item_quantity[] = $item->get_quantity();
$item_sku[] = $product->get_sku();
}
if( $item_sku ) {
$data['sku'] = implode( ",",$item_sku );
}
$tracking_url = $tracking_url . "/" . $tracking_code;
$url = "<a href='".$tracking_url."'>test</a>";
$data['qty'] = implode( ",",$item_quantity );
$test = ast_insert_tracking_number( $order_id, $tracking_url, $tracking_url, $date_shipped, $status_shipped, $sku, $qty);
var_dump($test);
print_r($tracking_code);
print_r($data);
print_r($wcfm_tracking_data);
var_dump($order_item_id);
//ast_insert_tracking_number
die();
}
Kudos to anyone willing to give this a try and some time
Regards

Get used coupon codes and related discount amounts from WooCommerce orders

I need to insert in a custom plugin the code to get the name of the discount codes I enter in the settings, the discount obtained with the code and the total.
Based on Get coupon data from WooCommerce orders answer code, I have inserted the following code:
$order = wc_get_order( $order_id );
// GET THE ORDER COUPON ITEMS
$order_items = $order->get_items('coupon');
// print_r($order_items); // For testing
// LOOP THROUGH ORDER COUPON ITEMS
foreach( $order_items as $item_id => $item ){
// Retrieving the coupon ID reference
$coupon_post_obj = get_page_by_title( $item->get_name(), OBJECT, 'shop_coupon' );
$coupon_id = $coupon_post_obj->ID;
// Get an instance of WC_Coupon object (necessary to use WC_Coupon methods)
$coupon = new WC_Coupon($coupon_id);
## Filtering with your coupon custom types
if( $coupon->is_type( 'fixed' ) || $coupon->is_type( 'percent' ) || $coupon->is_type( 'fixed_product' ) ){
// Get the Coupon discount amounts in the order
$order_discount_amount = wc_get_order_item_meta( $item_id, 'discount_amount', true );
$order_discount_tax_amount = wc_get_order_item_meta( $item_id, 'discount_amount_tax', true );
## Or get the coupon amount object
$coupons_amount = $coupons->get_amount();
}
}
$confirmation = str_ireplace("{order_items}", $order_items, $confirmation);
But the only information it brings back to me, when I do an echo is the word "array".
What am I doing wrong? Any help?
Try the following instead, that will add a coma separated string of applied coupon codes with their respective discount amount:
$order = wc_get_order( $order_id ); // If needed
$output = array(); // Initializing
// loop through order items "coupon"
foreach( $order->get_items('coupon') as $item_id => $item ){
// Get the coupon array data in an unprotected array
$data = $item->get_data();
// Format desired coupon data for output
$output[] = $data['code'] . ': ' . strip_tags( wc_price( $data['discount'] + $data['discount_tax'] ) );
}
$confirmation = str_ireplace("{order_items}", implode(', ', $output), $confirmation);

Get the product ID in WooCommerce 3+ Order items

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.

Getting order data after successful checkout hook

In WooCommerce, I would like to send a request to an API once the customer has successfully checked out. Its basically a website where the client is selling online courses (Like udemy).
When the customer checks out, I would like to send an API request and enroll the user for that particular course. I have tried several WooCommerce hooks but none worked for me.
This is the code that I'm using:
add_action('woocommerce_checkout_order_processed', 'enroll_student', 10, 1);
function enroll_student($order_id)
{
echo $order_id;
echo "Hooked";
}
I am writing this code for a plugin and to make it easier, I am currently using Cash on Delivery method.
Can anyone point me out where I am going wrong because when I checkout I cant see the message "hooked" that I am printing nor the $order_id?
It takes me to the success page and doesn't show these two things that I am printing.
Update 2 Only For Woocommerce 3+ (added restriction to execute the code only once)
add_action('woocommerce_thankyou', 'enroll_student', 10, 1);
function enroll_student( $order_id ) {
if ( ! $order_id )
return;
// Allow code execution only once
if( ! get_post_meta( $order_id, '_thankyou_action_done', true ) ) {
// Get an instance of the WC_Order object
$order = wc_get_order( $order_id );
// Get the order key
$order_key = $order->get_order_key();
// Get the order number
$order_key = $order->get_order_number();
if($order->is_paid())
$paid = __('yes');
else
$paid = __('no');
// Loop through order items
foreach ( $order->get_items() as $item_id => $item ) {
// Get the product object
$product = $item->get_product();
// Get the product Id
$product_id = $product->get_id();
// Get the product name
$product_id = $item->get_name();
}
// Output some data
echo '<p>Order ID: '. $order_id . ' — Order Status: ' . $order->get_status() . ' — Order is paid: ' . $paid . '</p>';
// Flag the action as done (to avoid repetitions on reload for example)
$order->update_meta_data( '_thankyou_action_done', true );
$order->save();
}
}
Code goes in function.php file of your active child theme (or theme) or also in any plugin file.
Related thread:
Get Order items and WC_Order_Item_Product in WooCommerce 3
How to get WooCommerce order details
The code is tested and works.
Updated (to get the product Id from Orders items as asked in your comment)
May be you could use woocommerce_thankyou hook instead, that will display on order-received page your echoed code, this way:
add_action('woocommerce_thankyou', 'enroll_student', 10, 1);
function enroll_student( $order_id ) {
if ( ! $order_id )
return;
// Getting an instance of the order object
$order = wc_get_order( $order_id );
if($order->is_paid())
$paid = 'yes';
else
$paid = 'no';
// iterating through each order items (getting product ID and the product object)
// (work for simple and variable products)
foreach ( $order->get_items() as $item_id => $item ) {
if( $item['variation_id'] > 0 ){
$product_id = $item['variation_id']; // variable product
} else {
$product_id = $item['product_id']; // simple product
}
// Get the product object
$product = wc_get_product( $product_id );
}
// Ouptput some data
echo '<p>Order ID: '. $order_id . ' — Order Status: ' . $order->get_status() . ' — Order is paid: ' . $paid . '</p>';
}
Code goes in function.php file of your active child theme (or theme) or also in any plugin file.
The code is tested and works.
Then you can use all class WC_Abstract_Order methods on the $order object.
Related:
How to get WooCommerce order details
Get Order items and WC_Order_Item_Product in WooCommerce 3
How to get Customer details from Order in WooCommerce?
Rather than 'woocommerce_thankyou' hook, 'woocommerce_checkout_order_processed' hook is the relevant hook. 'woocommerce_checkout_order_processed' hook will be called only once and you will not need to add meta for each product and make additional calls to keep check for code to run only once. As, 'woocommerce_thankyou' can be called multiple times that is each time thankyou page loads.
Replace add_action('woocommerce_thankyou', 'enroll_student', 10, 1);
with
add_action('woocommerce_checkout_order_processed', 'enroll_student', 10, 1);
and remove meta code and checks. Updated code is
add_action('woocommerce_checkout_order_processed', 'enroll_student', 10, 1);
function enroll_student( $order_id ) {
// Getting an instance of the order object
$order = wc_get_order( $order_id );
if($order->is_paid())
$paid = 'yes';
else
$paid = 'no';
// iterating through each order items (getting product ID and the product object)
// (work for simple and variable products)
foreach ( $order->get_items() as $item_id => $item ) {
if( $item['variation_id'] > 0 ){
$product_id = $item['variation_id']; // variable product
} else {
$product_id = $item['product_id']; // simple product
}
// Get the product object
$product = wc_get_product( $product_id );
}
// Ouptput some data
echo '<p>Order ID: '. $order_id . ' — Order Status: ' . $order->get_status() . ' — Order is paid: ' . $paid . '</p>';
}
you can get the order items of an order by
// Getting an instance of the order object
$order = new WC_Order( $order_id );
$items = $order->get_items();
//Loop through them, you can get all the relevant data:
foreach ( $items as $item ) {
$product_name = $item['name'];
$product_id = $item['product_id'];
$product_variation_id = $item['variation_id'];
}

Woocommerce - Add Coupon is not deducting totals

I am creating my order like so:
$order = wc_create_order();
$product = wc_get_product( $_POST["product"] );
$order->add_product( $product, 1 );
$kupon = new WC_Coupon( $_POST["coupon"] );
$amount = $kupon->get_discount_amount( $product->price );
$order->add_coupon( $_POST["coupon"], $amount, $amount );
$order->calculate_shipping();
$order->calculate_totals();
If you take a closer look, I am adding a coupon code dynamicaly with add_coupon function from WC_Order class. Everythings works perfectly, the order is added to database with correct product, quantites, and ALSO the coupon is added - but the problem is that coupon is not "applied" to the total. It is not deducting the totals price. Here is the image:
While adding a product to an Order, we should pass an argument containing subtotal and total like this:
$args = array(
"totals" => array('subtotal' => $item["price"],
'total' => $item["price"] - $coupon_discount)
);
$order->add_product( $product, 1, $args);
Where $product is Woocommerce product. Hope this helps somebody.
Here is the solution that worked in my case for modifying order line items then applying a discount afterward - $order is a WC_Order object:
$order_total = $order->get_total()
$coupon_code = $this->get_coupon_code( $order );
$coupon = new WC_Coupon( $coupon_code );
$coupon_type = $coupon->discount_type;
$coupon_amount = $coupon->coupon_amount;
$final_discount = 0;
// You must calculate the discount yourself! I have not found a convenient method outside the WC_Cart context to do this for you.
$final_discount = $coupon_amount * ( $order_total / 100 );
$order->add_coupon( $coupon_code, $final_discount, 0 );
$order->set_total( $final_discount );
Here is the method to retrieve the coupon code for a WC_Order object. In my case I know there will never be more then 1 coupon per order so you may want to adjust it to accommodate more:
public function get_coupon_code( $subscription ) {
$coupon_used = '';
if( $subscription->get_used_coupons() ) {
$coupons_count = count( $subscription->get_used_coupons() );
foreach( $subscription->get_used_coupons() as $coupon) {
$coupon_used = $coupon;
break;
}
}
if ( $coupon_used !== '' ) {
return $coupon_used;
} else {
return false;
}
}

Categories