WooCommerce Hide Payment Gateway for Custom Attribute - wordpress

Just starting in my WordPress/WooCommerce journey.
I found a question on here from a while back asking about restricting payment gateways for a specific attribute selection. I've tried to integrate this into my site and I cannot get it working! I've added the Attribute and Terms, and the slugs are as follows - pay_now_deposit (attr) and pay_now / deposit (terms).
I'm looking to restrict Klarna payments for those paying by deposit, and the code I have is below -
function conditional_payment_gateways( $available_gateways ) {
$in_cart = false;
foreach ( WC()->cart->get_cart_contents() as $key => $values ) {
// See if there is an attribute called 'pa_size' in the cart
// Replace with whatever attribute you want
if (array_key_exists('pa_pay_now_deposit', (array) $values['data']->get_attributes() ) ) {
foreach ($values['data']->get_attributes() as $attribute => $variation);
// Replace 'small' with your value.
if ($variation == 'deposit') $in_cart = true; //edited
}
}
if ( $in_cart ) {
unset($available_gateways['klarna_payments']);
}
else {
unset($available_gateways['cod']);
}
return $available_gateways;
}
Any advice on where I'm going wrong would be greatly appreciated!

Try to add a break statement.
add_filter('woocommerce_available_payment_gateways', 'conditional_payment_gateways', 10, 1);
function conditional_payment_gateways( $available_gateways ) {
$in_cart = false;
foreach ( WC()->cart->get_cart_contents() as $key => $values ) {
if ( array_key_exists( 'pa_pay_now_deposit', (array) $values['data']->get_attributes() ) ) {
foreach ( $values['data']->get_attributes() as $attribute => $variation ){
if ( $variation == 'deposit' ){
$in_cart = true; //edited
break;
}
}
}
if( $in_cart ){
break;
}
}
if ( $in_cart ) {
unset( $available_gateways['klarna_payments'] );
}else {
unset( $available_gateways['cod'] );
}
return $available_gateways;
}

Related

Hide Custom Shipping When Multiple Items are in cart

I added a plugin that creates a shipping method with Id "pisol_extended_flat_shipping:52540" when the product category is "baby-care" and the country is "India" and It's working fine. When someone adds different products from different categories in the cart and one of the categories is "baby-care". then I want to hide the "pisol_extended_flat_shipping:52540" shipping when there are other category products at the checkout along with "baby-care".
I tried this code, but not working
function check_cart_categories() {
$baby_care = false;
$other_categories = false;
foreach ( WC()->cart->get_cart() as $cart_item_key => $cart_item ) {
$product = $cart_item['data'];
if ( has_term( 'baby-care', 'product_cat', $product->id ) ) {
$baby_care = true;
} else {
$other_categories = true;
}
}
return ( $baby_care && $other_categories );
}
add_filter( 'woocommerce_available_shipping_methods', 'hide_pisol_extended_flat_shipping' );
function hide_pisol_extended_flat_shipping( $available_methods ) {
if ( check_cart_categories() ) {
unset( $available_methods['pisol_extended_flat_shipping:52540'] );
}
return $available_methods;
}
Here is the full code:
function check_cart_categories() {
// your logic here...
}
add_filter( 'woocommerce_package_rates', 'hide_pisol_extended_flat_shipping' , 10, 2 );
function hide_pisol_extended_flat_shipping( $rates, $package ) {
if ( check_cart_categories() ) {
unset( $rates['pisol_extended_flat_shipping:52540'] );
}
return $rates;
}
If it doesn't work, try increasing the priority of the hook (I set default 10). Some plugins are also using this hook and could interfere.

Hide payment method if specific variation selected is blocking plugins [duplicate]

In Woocommerce, i want to hide the credit card payment option if a specific product variation is in the cart. Please help.
Thanks.
This is what i have working now. I assigned a separate shipping class to each variation i want to disable a specific payment method at checkout. But it would be much easier if i coud target specific attribute values, so i don't have to assign a shipping class.
<?php
add_filter('woocommerce_available_payment_gateways', 'conditional_payment_gateways', 10, 1);
function conditional_payment_gateways( $available_gateways ) {
$shipping_class_target = 106; // the shipping class ID assigned to specific variations
$in_cart = false;
foreach ( WC()->cart->get_cart_contents() as $key => $values ) {
if ( $values[ 'data' ]->get_shipping_class_id() == $shipping_class_target ) {
$in_cart = true;
break;
}
}
if ( $in_cart ) {
unset($available_gateways['cod']); // unset 'cod'
}
else {
unset($available_gateways['bacs']); // unset 'bacs'
}
return $available_gateways;
}
If you are looking to check the variations for each item in the cart, you have to lookup the attributes $product->get_attributes() and then loop through those and get the array key and value for each.
In this example, I used
Size (pa_size) and Small
add_filter('woocommerce_available_payment_gateways', 'conditional_payment_gateways', 10, 1);
function conditional_payment_gateways( $available_gateways ) {
$in_cart = false;
foreach ( WC()->cart->get_cart_contents() as $key => $values ) {
// See if there is an attribute called 'pa_size' in the cart
// Replace with whatever attribute you want
if (array_key_exists('pa_size', (array) $values['data']->get_attributes() ) ) {
foreach ($values['data']->get_attributes() as $attribute => $variation);
// Replace 'small' with your value.
if ($variation == 'small') $in_cart = true; //edited
}
}
if ( $in_cart ) {
unset($available_gateways['cod']); // unset 'cod'
}
else {
unset($available_gateways['bacs']); // unset 'bacs'
}
return $available_gateways;
}

How to find out the cheapest shipping method and change the shipping label in woocommerce?

So here's what I need to do: find out the cheapest shipping method and change the "Free Shipping" method label to "Free Shipping" + "Cheapest method label". This way the customer will be able to know what is the shipping method used for the free shipping.
First I thought about global variables.. then used the wp_options, but I am not certain if the wp_options are user shared or user-specific data.
Would you have any good ideas or corrections on the following code, which by the way isn't working? Thanks!
add_filter( 'woocommerce_shipping_chosen_method', 'wf_default_shipping_method', 10 );
function wf_default_shipping_method( $method ) {
$the_cheapest_cost = 1000000;
$packages = WC()->shipping()->get_packages()[0]['rates'];
foreach ( array_keys( $packages ) as $key ) {
if ( ( $packages[$key]->cost > 0 ) && ( $packages[$key]->cost < $the_cheapest_cost ) ) {
$the_cheapest_cost = $packages[$key]->cost;
$transport_label = $packages[$key]->label;
$method_id = $packages[$key]->id;
}
}
if(get_option('atransport')){
update_option('atransport', $transport_label);
}else{
add_option('atransport', $transport_label);
}
return $method_id;
}
add_filter( 'woocommerce_package_rates', 'change_shipping_methods_label_names', 20, 2 );
function change_shipping_methods_label_names( $rates, $package ) {
$transport = get_option('atransport');
foreach( $rates as $rate_key => $rate ) {
if ( __( 'Free Shipping', 'woocommerce' ) == $rate->label ){
$rates[$rate_key]->label = __( 'FreeShipping -' . $transport, 'woocommerce' ); // New label name
}
}
delete_option('atransport');
return $rates;
}
You can iterate a loop of $rates and get the cheapest method. then based on the found cheapest method you can change the label. code will go in your active theme functions.php file.
add_filter( 'woocommerce_package_rates', 'hide_other_shipping_when_free_is_available', 100, 1 );
function hide_other_shipping_when_free_is_available( $rates ) {
$cheapest_method = '';
// Loop through shipping rates
if ( is_array( $rates ) ) {
foreach ( $rates as $key => $rate ) {
// Set variables when the rate is cheaper than the one saved
if ( empty( $cheapest_method ) || $rate->cost < $cheapest_method->cost ) {
$cheapest_method = $rate;
}
}
}
// Return the cheapest rate when possible
if ( ! empty( $cheapest_method ) ) {
$free = array();
foreach ( $rates as $rate_id => $rate ) {
if ( $rate->id === $cheapest_method->id ) {
if ( __( 'Free Shipping', 'woocommerce' ) == $rate->label ){
$rates[ $rate_id ] = $rate;
// Here we append the labbelled saved price formated display
$rates[ $rate_id ]->label = 'Free Shipping '.$rates[ $rate_id ]->label;
break; // stop the loop
}
}
}
return $rates;
}
return $rates;
}
Tested and works

Disable payment gateway when specific products in WooCommerce cart

I want to unset the payment method 'bacs' for the product ID 6197.
I have tried the code below, but this does not have the desired result.
add_filter( 'woocommerce_available_payment_gateways', 'wp_unset_gateway_by_id', 10, 2 );`
function wp_unset_gateway_by_id( $available_gateways, $products) {
global $woocommerce;
$unset = false;
$product_ids = array('6197');
if( in_array( $product->get_id(), $product_ids ) || ( $product->is_type('variation') && in_array( $product->get_parent_id(), $product_ids ) ) ){
unset( $available_gateways['bacs'] );
return $available_gateways;
}
}
I believe I am doing something wrong, but I am relatively new to this. Any advice would be appreciated.
$products is not passed as argument to the woocommerce_available_payment_gateways filter hook
Apply it in the following way:
function filter_woocommerce_available_payment_gateways( $payment_gateways ) {
// Not on admin
if ( is_admin() ) return $payment_gateways;
// The targeted product ids (several can be added, separated by a comma)
$targeted_ids = array( 6197 );
// Flag
$found = false;
// WC Cart
if ( WC()->cart ) {
// Loop through cart items
foreach ( WC()->cart->get_cart() as $cart_item ) {
if ( array_intersect( $targeted_ids, array( $cart_item['product_id'], $cart_item['variation_id'] ) ) ) {
$found = true;
break;
}
}
}
// True
if ( $found ) {
// Bacs
if ( isset( $payment_gateways['bacs'] ) ) {
unset( $payment_gateways['bacs'] );
}
}
return $payment_gateways;
}
add_filter( 'woocommerce_available_payment_gateways', 'filter_woocommerce_available_payment_gateways', 10, 1 );

Woocommerce force free shipping if you are admin

I currently have free shipping on items over $75, but if an admin login and place an order. I want the admin to have free shipping regardless if the cart is not over $75. I've been trying to use the following code, but it's not triggering it. Am I doing something wrong?
add_filter( 'woocommerce_package_rates', 'show_free_shipping', 10, 2 );
function show_free_shipping( $rates, $package ) {
global $current_user;
$free = array();
foreach ( $rates as $rate_id => $rate ) {
if ( 'free_shipping' === $rate->method_id ) {
if ($current_user->ID) {
$user_roles = $current_user->roles;
$user_role = array_shift($user_roles);
if ($user_role == 'administrator') {
$free[ $rate_id ] = $rate;
break;
}
}
}
}
return ! empty( $free ) ? $free : $rates;
//return $rates;
}
the filter woocommerce_package_rates is used after that the free shipping is set has "not available" because the minimum is not reached.
to make the free shipping available again, you can use the filter woocommerce_shipping_free_shipping_is_available
https://docs.woocommerce.com/wc-apidocs/source-class-WC_Shipping_Free_Shipping.html#200-202
try this :
add_filter("woocommerce_shipping_free_shipping_is_available"
, function ($is_available, $package, $method)
{
$current_user = wp_get_current_user();
if (in_array("administrator", $current_user->roles)) {
$is_available = TRUE;
}
return $is_available;
}, 10, 3);

Resources