Change payment gateway option based on cart total in Woocommerce checkout - php

For my woocommerce shop, i have this filter in functions.php. It force 3DS with "woocommerce Stripe Gateway" plugin.
add_filter('wc_stripe_require_3ds','__return_true');
It work great.
I would like this filter to be active only for order over 50€.
I tried with this but it doesn't work, the order is validated without 3DS.
$minsecure = 50;
$order = new WC_Order( $order_id );
$total = $order->get_total();
if($total>$minsecure) {
add_filter('wc_stripe_require_3ds','__return_true');
}
I also try to get the cart amount instead of the order amount, but I don't know which one to get for the filter to be active between the time of the "order" click and the confirmation page.
Any help is appreciated.

I would go for this to check if the price of the order is over 50
if( WC()->cart->subtotal > 50 )
So the snippet would look like
add_action('woocommerce_cart_updated', 'wc_stripe_require_3ds', 90);
function wc_stripe_require_3ds ( $cart ){
if( WC()->cart->subtotal > 50 ) {
add_filter('wc_stripe_require_3ds','__return_true');
}
}
Have a try.

Related

WooCommerce: hook for admin edited orders

Good morning. I have a single custom function which should be triggered when:
an order is created or modified from frontend
an order is created or modified from backend (admin mode), in any way: refunds, products added or removed, coupon applied, order notes inserted, order action changed, etc.
In the 1st case I'm using add_action('woocommerce_checkout_order_processed', 'calcolo_corrispettivi', 10, 1). Works fine.
In the 2nd case I've tried using add_action('save_post', 'calcolo_corrispettivi', 10, 1). It crashes when triggered by non "order" type posts.
Full code:
add_action('woocommerce_checkout_order_processed', 'calcolo_corrispettivi', 10, 1);
add_action('save_post', 'calcolo_corrispettivi', 10, 1);
// Not enough for all possible 'edit' actions:
// add_action('woocommerce_order_refunded', 'calcolo_corrispettivi', 10, 1);
function calcolo_corrispettivi ( $order_id ) {
$order = wc_get_order( $order_id );
$order_refunds = $order->get_refunds();
$totale_EP = 0;
$totale_altri = 0;
foreach ( $order->get_items() as $item_id => $item) {
$prodotto = $item->get_product();
$editrice = $prodotto->get_attribute('pa_casa-editrice');
if ($editrice == "EP") {
$totale_EP = $totale_EP + $item->get_subtotal() - $order->get_total_refunded_for_item( $item_id );
}
else {
$totale_altri = $totale_altri + $item->get_subtotal() - $order->get_total_refunded_for_item( $item_id );
}
}
update_post_meta($order_id, 'totale_EP', $totale_EP);
update_post_meta($order_id, 'totale_altri', $totale_altri);
}
Is there any specific woocommerce hook for admin updated orders?
Thank you.
Update. I've also tried using woocommerce_process_shop_order_meta, as suggested below, following this question. The solution works only if I press "Update" button under "Order action":
Admin order edit page - Update button
But, for instance, if I change the quantity of a product, the order gets updated without pressing the "Update" button, and so without running my custom function:
Admin order edit page - Update single product quantity
Solution. These hooks worked for me:
Order modified by admin on backend page: woocommerce_saved_order_items (as shown here)
Note added: woocommerce_order_note_added
Refund: woocommerce_order_refunded

Woocommerce update stock by ID after payment

I created a custom product type for WooCommerce. With this product type it is possible to connect an other product that is exist by ID.
WooCommerce reduce the stock quantity automatically if an order is placed and the payment is successful.
For example I added a product with ID 4082 to the cart with a quantity from 3.
After place this order WooCommerce updated the stock from product 4082 with -3.
Ok back to my custom product type. As I said it is possible to connect another product by ID.
For example I connect product 4082 with product ID 10988.
If a customer add product 4082 to the cart and placed the order I want reduce the stock quantity from product ID 10988 and not from 4082.
<?php
add_action('woocommerce_checkout_order_processed', 'stocktest');
function stocktest($order_id){
$order = wc_get_order( $order_id );
$order_item = $order->get_items();
foreach( $order_item as $product ) {
//for the topic I programmed the IDs hardcoded
if($product->ID == '4082'){
wc_update_product_stock( 10998, $product['qty'], 'decrease', '' );
}
}
}
?>
I tried the code above and the stock from ID 10998 is correctly decreased but also the stock from ID 4082 is decreased.
Do I use the wrong hook? And how can I make the function correctly?
Hope somebody can help me with this.
Thanks a lot
Does wc_update_product_stock( 4082, $product['qty'], 'increase', '' ); not work?
That way, the stock should be adjusted for the 4082 product.
Also, there might be a potential issue with your snippet. The $product variable refers to the product object of 4082 product, not the 10998 product.
Maybe try something like this?
<?php
add_action('woocommerce_checkout_order_processed', 'stocktest');
function stocktest($order_id){
$order = wc_get_order( $order_id );
$order_item = $order->get_items();
foreach( $order_item as $product ) {
//for the topic I programmed the IDs hardcoded
if($product->ID == '4082'){
$connected_qty = get_post_meta( 10988, '_stock', true );
wc_update_product_stock( 10998, $connected_qty, 'decrease', '' );
wc_update_product_stock( 4082, $product['qty'], 'increase', '' );
}
}
}
?>
Instead of using the custom field query, you could use the WC_Product class:
$connected_product = wc_get_product(10998);
$connected_qty = $connected_product->get_stock_quantity();
I did some research on your question. WooCommerce called a lot of functions to update the stock af order / payment. If an order is placed the items become an status reduce_stock yes or no.
If is yes go further and update the stock of this item. After this WooCommerce created the e-mails and ordernotes.
All this functions worked together please be careful with changing the code in the file wc-stock-functions.php
If you want change and try something do this for example on a local testserver.
This are some functions in the file
<?php
wc_maybe_reduce_stock_levels();
wc_maybe_increase_stock_levels();
wc_reduce_stock_levels();
wc_trigger_stock_change_notifications();
?>

Can I change the order WooCommerce Coupons are applied programmatically?

I am developing a Woocommerce shop and want to offer all members (users logged in) 20% off their Total.
I have created a coupon called "twentypercent_off" and I am programmatically applying this using a custom function and a hook in my functions.php.
This works well.
In WC settings I have checked "Calculate coupon discounts sequentially" and this works almost as I would expect.
However what I would like is that my "twentypercent_off" is always applied last in cases where there are multiple coupons.
No matter what I have attempted to do (loop through all coupons on current order, remove all coupons, add them back in the order I desire) I find that Woo-commerce seems to always apply them in the order of monetary savings.
For example if the customer orders $100 worth of products and they have a coupon for $25 and also qualified to receive 20% off total.
I would like the total to calculate as (100 -25) * 0.8 = $60
but WC is calculating as such (100 * 0.8) - 25 = $55
I tried the following but it made no difference:
if ( is_user_logged_in() ) {
$Coupon_code = 'twentypercent_off';
$Current_Coupons = WC()->cart->get_coupons();
$Non_Prog_Coupons=array();
// loop through all current coupons
foreach( $Current_Coupons as $code => $coupon ){
if($code==$coupon_code){
WC()->cart->remove_coupon( $code );
} else {
WC()->cart->remove_coupon( $code );
$Non_Prog_Coupons[]=$code; // array of non-programmatically added coupons
}
}
// loop through non-programmatically added coupons
foreach( $Non_Prog_Coupons as $x => $code ){
WC()->cart->add_discount( $code ); // add them again
}
// add programmatically added coupon last !
WC()->cart->add_discount($Coupon_code);
}
return;
The only possible solution I have come across is to apply the 20% discount as a negative fee, which is not suitable for our purposes and would be an absolute last resort
Any ideas on how to achieve this would be greatly appreciated

woocommerce change price in checkout and cart page

With woocommerce, in my website I'd like to add in the cart page a select input where the user can select a value between two options, and depending on this value I will change the price.
so far, I could get the total and change it using this :
function action_woocommerce_before_cart_totals( ) {
global $woocommerce;
$woocommerce->cart->total = $woocommerce->cart->total*0.25;
var_dump( $woocommerce->cart->total);};
The issue is that when I go to checkout page it doesn't take the total calculated in functions.php
Thanks for helping me.
You can use woocommerce_review_order_before_order_total hook too at the same time, to display your custom price in checkout, this way:
add_action( 'woocommerce_review_order_before_order_total', 'custom_cart_total' );
add_action( 'woocommerce_before_cart_totals', 'custom_cart_total' );
function custom_cart_total() {
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return;
WC()->cart->total *= 0.25;
//var_dump( WC()->cart->total);
}
The 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.
Payment gateway always uses $order->get_total() variable to fetch cart grand total. So in order to tweak use this filter woocommerce_order_amount_total
for your function if you do follow below steps. Your payment gateway always shows the total you tweaked.
add_filter( 'woocommerce_order_amount_total', 'custom_cart_total' );
function custom_cart_total($order_total) {
return $order_total *= 0.25;
}

How do I automatically set WooCommerce Product to draft if sold out

I tried using the 'Hide if sold out' option in Woocommerce. But I am using a different plugin to display my products (GridFX Masonry Gallery) and it is still showing the sold out products. Is there a way to change the product to draft when the last item has been purchased and is sold out? Is there a snippet to do this?
The previous answer by Maha Dev cannot work.
In a theme functions file the get_stock_quantity() method doesn't exist unless you call the product data using wc_get_product.
Using set_post_type will change the actual type of the post, not it's status, you need to use wp_update_post and set the post status.
This is the code I ended up using:
/*
* Unpublish products after purchase
*/
function lbb_unpublish_prod($order_id) {
$order = new WC_Order( $order_id );
$all_products = $order->get_items();
foreach ($all_products as $product){
$product_object = wc_get_product($product['product_id']);
// This will only work if stock management has been enabled
if( ! $product_object->get_stock_quantity() ) {
wp_update_post(array(
'ID' => $product['product_id'],
'post_status' => 'draft'
));
}
}
}
add_action( 'woocommerce_thankyou', 'lbb_unpublish_prod', 10, 1 );
Better way is to set product stock (1 in your case). Select 'Hide out of stock products'. It will hide out of stock products. But if you actually want to hide ordered products then see my code below:
//functions.php
add_action( 'woocommerce_thankyou', 'your_func', 10, 1 );
function your_func($order_id) {
$order = new WC_Order( $order_id );
$all_products = $order->get_items();
foreach ($all_products as $product){
// This will only work if stock management has been enabled
if( ! $product->get_stock_quantity() )
set_post_type ($product['product_id'], 'draft');
}
}
This will hide all the products added in the cart for order. You can customize this function as you want.

Categories