Discount by shipping zone - woocommerce

On Woocommerce, I am trying to apply a coupon based on a specific shipping zone.
There is two shipping zone set:
the coupon should be used for the shipping zone germany ( shipping&zone_id=8 ). Not for all other shipping zones.
I have already tested a snippet that always shows me the coupon. Unfortunately I'm bad at programming.
`// Add / remove coupon based on cosen shipping
add_action( 'woocommerce_before_calculate_totals', 'adding_removing_coupon_shipping_based' );
function adding_removing_coupon_shipping_based( $cart ) {
if (is_admin() && !defined('DOING_AJAX'))
return;
if ( did_action( 'woocommerce_before_calculate_totals' ) >= 2 )
return;
// HERE the specific coupon code
$coupon_code = 'pfand';
$coupon_code = wc_format_coupon_code( $coupon_code );
$chosen_shipping = WC()->session->get('chosen_shipping_methods')[0];
$applied_coupons = $cart->get_applied_coupons();
$is_free = strpos( $chosen_shipping, 'deutschland' ) !== false;
$is_applied = in_array( $coupon_code, $applied_coupons );
if ( $is_applied && $is_free )
$cart->remove_coupon( $coupon_code );
elseif ( ! $is_applied && ! $is_free )
$cart->apply_coupon( $coupon_code );
}

Related

Woocommerce Add Coupon Based on Cart Subtotal

I am trying to add one of three coupons to the cart automatically based on the cart subtotal ($250 or more; $150-249.99; and $75-149.99). This is what I have, but it makes the cart just spin when you update an item quantity in the cart. It seems to work when an additional new item is added to the cart or when an item in the cart is removed. However, when I increased the quantity of one item to move from the smallest discount to the medium discount, the cart page didn't load at all (it was blank). It was still blank even after I went and added a new product to the cart. I had to comment out the action to get it to load the cart.
I'd appreciate any help.
This works, except that when the cart is updated, it just spins. If you refresh, the correct discount displays (and the item count that was changed was updated.) Any idea why it would just spin like this?
add_action( 'woocommerce_before_calculate_totals', 'sbs_auto_add_coupons_total_based', 10, 1 );
function sbs_auto_add_coupons_total_based( $cart ) {
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return;
if ( did_action( 'woocommerce_before_calculate_totals' ) >= 2 )
return;
$coupon_15 = 'dicount15';
$coupon_10 = 'discount10';
$coupon_5 = 'discount5';
$applied_coupons = $cart->get_applied_coupons();
$subtotal = 0;
foreach( $cart->get_cart() as $cart_item ) {
$subtotal += $cart_item['line_subtotal'];
}
if( $subtotal >= 250 && ! in_array($coupon_15, $applied_coupons ) ){
if( in_array($coupon_10, $applied_coupons ) )
$cart->remove_coupon( $coupon_10 );
if( in_array($coupon_5, $applied_coupons ) )
$cart->remove_discount($coupon_5);
$cart->add_discount( $coupon_15 );
}
elseif( $subtotal >= 150 && ! in_array($coupon_10, $applied_coupons ) ) {
if( in_array($coupon_15, $applied_coupons ) )
$cart->remove_coupon( $coupon_15 );
if( in_array($coupon_5, $applied_coupons ) )
$cart->remove_discount($coupon_5);
$cart->add_discount( $coupon_15 );
}
elseif( $subtotal >= 75 && ! in_array($coupon_5, $applied_coupons ) ) {
if( in_array($coupon_15, $applied_coupons ) )
$cart->remove_coupon( $coupon_15 );
if( in_array($coupon_10, $applied_coupons ) )
$cart->remove_discount($coupon_10);
$cart->add_discount( $coupon_5 );
}
else {
if( in_array($coupon_15, $applied_coupons ) )
$cart->remove_coupon( $coupon_15 );
if( in_array($coupon_10, $applied_coupons ) )
$cart->remove_discount($coupon_10);
if( in_array($coupon_5, applied_coupons ) )
$cart->remove_discount($coupon_5);
}
}
/**
Add Coupon Based on Cart Subtotal
*/
add_action( 'woocommerce_before_cart', 'add_coupon_automatically' );
function add_coupon_automatically() {
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return;
// HERE define your subtotal
$subtotal = 100;
// HERE define your coupon code
$coupon_code = '10off';
// HERE define your coupon amount
$coupon_amount = 10;
// HERE define your coupon discount type
$discount_type = 'percent';
// HERE define your coupon description
$coupon_description = '10% off for orders over $100';
// The active coupons
$active_coupons = WC()->cart->get_coupons();
// The cart subtotal
$cart_subtotal = WC()->cart->subtotal;
// If the cart subtotal is greater than $subtotal and the coupon is not already applied
if( $cart_subtotal >= $subtotal && ! isset($active_coupons[$coupon_code]) ) {
// Add the coupon
WC()->cart->add_discount( $coupon_code );
// Display a custom notice
wc_print_notice(
sprintf( '<strong>%s</strong> coupon has been applied!', $coupon_amount . '%' ), 'notice'
);
}
}

Remove Paypal payment if customer chose COD in WooCommerce [duplicate]

I would like to hide some payment method and enable another one when I select a specified “Shipping Method" in flexible Shipping plugin form wpdesk.
I have already tried that code:
add_filter( 'woocommerce_available_payment_gateways', 'gateway_disable_shipping_326' );
function gateway_disable_shipping_326( $available_gateways ) {
global $woocommerce;
if ( !is_admin() ) {
$chosen_methods = WC()->session->get( 'chosen_shipping_methods' );
$chosen_shipping = $chosen_methods[0];
if ( isset( $available_gateways['payment_method_cod'] ) && 0 === strpos( $chosen_shipping, 'flat_rate:6' ) ) {
unset( $available_gateways['payment_method_cod'] );
}
}
return $available_gateways;
}
and this one
function my_custom_available_payment_gateways( $gateways ) {
$chosen_shipping_rates = WC()->session->get( 'chosen_shipping_methods' );
if ( in_array( 'flat_rate:6', $chosen_shipping_rates ) ) :
unset( $gateways['payment_method_cod'] );
endif;
if ( in_array( 'flat_rate:8', $chosen_shipping_rates ) ) :
unset( $gateways['payment_method_przelewy24'] );
endif;
return $gateways;
}
add_filter( 'woocommerce_available_payment_gateways', 'my_custom_available_payment_gateways' );
The link to my website: [www.dajati.pl][1]
The following code example will enable / disable payment gateways based on chosen shipping method.
In this example, we have 3 shipping methods and 3 payment gateways. Each selected shipping method will enable only one different payment gateway.
add_filter( 'woocommerce_available_payment_gateways', 'payment_gateways_based_on_chosen_shipping_method' );
function payment_gateways_based_on_chosen_shipping_method( $available_gateways ) {
// Not in backend (admin) and Not in order pay page
if( is_admin() || is_wc_endpoint_url('order-pay') )
return $available_gateways;
// Get chosen shipping methods
$chosen_shipping_methods = (array) WC()->session->get( 'chosen_shipping_methods' );
if ( in_array( 'flat_rate:12', $chosen_shipping_methods ) )
{
unset( $gateways['bacs'] );
unset( $gateways['cod'] );
}
elseif ( in_array( 'flat_rate:14', $chosen_shipping_methods ) )
{
unset( $gateways['bacs'] );
unset( $gateways['paypal'] );
}
elseif ( in_array( 'free_shipping:10', $chosen_shipping_methods ) )
{
unset( $gateways['cod'] );
unset( $gateways['paypal'] );
}
return $gateways;
}
Code goes in functions.php file of your active child theme (or active theme). Tested and works.
To be able to get the correct shipping method ID you can use your browser inspector, this way:
Since I was looking for solution to this also, and LoicTheAztec's answer were removing all payments, here is a slightly modified working solution.
add_filter( 'woocommerce_available_payment_gateways', 'payment_gateways_based_on_chosen_shipping_method' );
function payment_gateways_based_on_chosen_shipping_method( $available_gateways ) {
// Not in backend (admin) and Not in order pay page
if( is_admin() || is_wc_endpoint_url('order-pay') )
return $available_gateways;
// Get chosen shipping methods
$chosen_shipping_methods = (array) WC()->session->get( 'chosen_shipping_methods' );
if ( in_array( 'flat_rate:12', $chosen_shipping_methods ) )
{
unset( $available_gateways['bacs'] );
unset( $available_gateways['cod'] );
}
elseif ( in_array( 'flat_rate:14', $chosen_shipping_methods ) )
{
unset( $available_gateways['bacs'] );
unset( $available_gateways['paypal'] );
}
elseif ( in_array( 'free_shipping:10', $chosen_shipping_methods ) )
{
unset( $available_gateways['cod'] );
unset( $available_gateways['paypal'] );
}
return $available_gateways;
}
The only difference is that all $gateways had to be changed to $available_gateways, or vice versa.

Auto apply coupon based on WooCommerce cart subtotal in which certain products are excluded

I am using the following code to auto apply a coupon when customer has $100 or more in cart.
add_action( 'woocommerce_checkout_before_order_review' , 'add_coupon_notice' );
function add_coupon_notice() {
$cart_total = WC()->cart->get_subtotal();
$minimum_amount = 100;
$currency_code = get_woocommerce_currency();
wc_clear_notices();
if ( $cart_total < $minimum_amount ) {
WC()->cart->remove_coupon( '20OFF100' );
wc_print_notice( "Get 20% off if you spend more than $$minimum_amount", 'notice' );
} else {
WC()->cart->apply_coupon( '20OFF100' );
wc_print_notice( '20% off $100 or more - Discount Applied!', 'notice' );
}
wc_clear_notices();
}
However, I want to exclude a specific product from this $100 minimum.
The specific product is on sale, and I've checked "Exclude Sale Items" in the coupon admin screen, but the code below is ignoring that.
Why isn't the 'Exclude Sale Items' working, and/or how can I go about this?
The biggest misconception in your code is that even though you checked "Exclude sale items" in the coupon admin screen, that the use of WC()->cart->get_subtotal() does not take this into account.
The solution:
You can use the woocommerce_before_calculate_totals hook
To avoid problems, use a coupon code without capital letters
When going through the cart content, we keep track of the total, except for the excluded products
Based on the current amount threshold and whether or not the coupon code has already been applied, we will display notices
So you get:
function action_woocommerce_before_calculate_totals( $cart ) {
if ( is_admin() && ! defined( 'DOING_AJAX' ) ) return;
if ( did_action( 'woocommerce_before_calculate_totals' ) >= 2 ) return;
// Coupon code
$coupon_code = 'coupon1';
// Total amount threshold
$amount_threshold = 100;
// Targeted product IDs, several can be entered, separated by a comma
$targeted_product_ids = array( 30, 813 );
// Initializing variables
$total_amount = 0;
$applied_coupons = $cart->get_applied_coupons();
// Loop through cart contents
foreach( $cart->get_cart_contents() as $cart_item ) {
// Excluding targeted product IDs
if ( ! in_array( $cart_item['data']->get_id(), $targeted_product_ids ) ) {
// Get the cart total amount
$total_amount += $cart_item['line_total'] + $cart_item['line_tax'];
}
}
// Applying coupon
if ( ! in_array( $coupon_code, $applied_coupons ) && $total_amount >= $amount_threshold ) {
$cart->apply_coupon( $coupon_code );
wc_clear_notices();
wc_add_notice( __( 'Succeeded', 'woocommerce' ), 'notice' );
}
// Buy more
elseif ( ! in_array( $coupon_code, $applied_coupons ) && $total_amount < $amount_threshold ) {
wc_clear_notices();
wc_add_notice( __( 'Buy more', 'woocommerce' ), 'notice' );
}
// Removing coupon
elseif ( in_array( $coupon_code, $applied_coupons ) && $total_amount < $amount_threshold ) {
$cart->remove_coupon( $coupon_code );
wc_clear_notices();
wc_add_notice( __( 'Removed', 'woocommerce' ), 'notice' );
}
}
add_action( 'woocommerce_before_calculate_totals', 'action_woocommerce_before_calculate_totals', 10, 1 );

Woocommerce - update_order_review become 502 after add_discount programmatically

I need some help. I want to implement, add existing coupon to cart when some conditions are fulfilled. I've got nothing wrong with the condition. But, when the function are going to add discount to coupon, the wc-ajax=update_order_review become 502.
However, if I do another things like changing address or something that can re-run update_order_review, it become 200. update_order_review successfully running and coupon is added to cart.
This is my function code so far, and I've copied some code from stackoverflow forum too
add_action('woocommerce_before_calculate_totals', 'discount_based_on_weight_threshold');
function discount_based_on_weight_threshold( $cart ) {
if ( ! defined( 'DOING_AJAX' ) )
return;
// Your settings
$coupon_code = 'freeongkir8krpx'; // Coupon code
// Initializing variables
$applied_coupons = $cart->get_applied_coupons();
$coupon_code = sanitize_text_field( $coupon_code );
$methods = WC()->session->get( 'chosen_shipping_methods' );
$method = isset( $methods[ 0 ] ) ? $methods[ 0 ] : false;
$kupon = new WC_Coupon('freeongkir10k');
if($method !== 'jne_shipping_test'){
if($cart->get_subtotal() <= $kupon->get_minimum_amount()){
$user = wp_get_current_user();
error_log( 'CHECK USER ROLES');
error_log( print_r($user->roles, TRUE) );
if(in_array( 'administrator', (array) $user->roles )){
// Applying coupon
if( ! in_array($coupon_code, $applied_coupons) ){
$cart->add_discount( $coupon_code );
wc_clear_notices();
}
}
} else {
if( in_array($coupon_code, $applied_coupons) ){
$cart->remove_coupon( $coupon_code );
}
}
} else {
if( in_array($coupon_code, $applied_coupons) ){
$cart->remove_coupon( $coupon_code );
}
}
}
When I disable $cart->add_discount( $coupon_code );, it running successfully, so I pretty sure that adding discount is the trigger.
And the flow that I used is
Go to checkout, conditions fulfilled, add_discount error, another function re-run update_order_review, coupon applied.
Change shipping methods, conditions not fulfilled, applied coupon is deleted
Change shipping methods, conditions fulfilled, add_discount error, update_order_review become 502, no other function re-run update_order_review, infinite loading in checkout order review
So any wrong code or flow do I have? or there are any ways to trick the error since it will applied the code if the update_order_review are re-run
Thank you
Do you get any helpful information in your browser console or the wp error log?
If I remember right 502 on AJAX request means the code fails to give you a valid response.
Hm, I don't yet have a helpful answer.
I refactored your code a bit to improve readability.
This should do exactly what your code does.
add_discount() has been renamed apply_coupon() - maybe try that.
<?php
add_action('woocommerce_before_calculate_totals', 'discount_based_on_weight_threshold');
function discount_based_on_weight_threshold( $cart ) {
if ( ! defined( 'DOING_AJAX' ) )
return;
// Your settings
$coupon_code = 'freeongkir8krpx'; // Coupon code
// Initializing variables
$applied_coupons = $cart->get_applied_coupons();
$coupon_code = sanitize_text_field( $coupon_code );
$methods = WC()->session->get( 'chosen_shipping_methods' );
$method = isset( $methods[ 0 ] ) ? $methods[ 0 ] : false;
$kupon = new WC_Coupon('freeongkir10k');
// remove code if already applied
if( in_array($coupon_code, $applied_coupons) ){
$cart->remove_coupon( $coupon_code );
}
if(
$method !== 'jne_shipping_test') &&
$cart->get_subtotal() <= $kupon->get_minimum_amount()
){
$user = wp_get_current_user();
error_log( 'CHECK USER ROLES');
error_log( print_r($user->roles, TRUE) );
if( in_array( 'administrator', (array) $user->roles ) ){
// Applying coupon
$cart->apply_coupon( $coupon_code );
wc_clear_notices();
}
}
}

hide payment gateway on specific shipping method

I have a shipping method which is called " SMSA EXPRESS - CASH ON DELIVERY " .. so when customer chooses this shipping method he should see the cash on delivery option for the payment and not the other options, which are the payments gateways ..
I tried to use this code but it didn't work
add_filter( 'woocommerce_available_payment_gateways', 'bbloomer_gateway_disable_shipping_326' );
function bbloomer_gateway_disable_shipping_326( $available_gateways ) {
if ( ! is_admin() ) {
$chosen_methods = WC()->session->get( 'chosen_shipping_methods' );
$chosen_shipping = $chosen_methods[0];
if ( isset( $available_gateways['cod'] ) && 0 === strpos( $chosen_shipping, 'SMSA_EXPRESS_-_CASH_ON_DELIVERY' ) ) {
unset( $available_gateways['cod'] );
}
}
return $available_gateways;
}

Resources