I have made hidden the other payment methods if selected COD method (which is flat_rate:5 in my case). I. am using Show hide payment methods based on selected shipping method in Woocommerce answer where I have made some minor edits.
The code works exactly as it should be however, I can't edit menus in "Appearance -> Menus" screen. It seems no problem in front-end.
function payment_gateways_based_on_chosen_shipping_method( $gateways ) {
// Get chosen shipping methods
$chosen_shipping_methods = (array) WC()->session->get( 'chosen_shipping_methods' );
if ( in_array( 'flat_rate:5', $chosen_shipping_methods ) )
{
unset( $gateways['bacs'] );
unset( $gateways['iyzico'] );
}
return $gateways;
}
add_filter( 'woocommerce_available_payment_gateways', 'payment_gateways_based_on_chosen_shipping_method' );
I am totally confused where is the bug and why it only appears on "Appearence -> Menus" page.
Also this guy from WordPress support forum had encounter similar issue with different code but in same filter (woocommerce_available_payment_gateways).
Thank you.
That's because WC()->session is null on backoffice. So you can't call method "get".
You need to check if you are in admin area before execute your code:
function payment_gateways_based_on_chosen_shipping_method( $gateways ) {
if(is_admin()){
return $gateways;
}
// Get chosen shipping methods
$chosen_shipping_methods = (array) WC()->session->get( 'chosen_shipping_methods' );
if ( in_array( 'flat_rate:5', $chosen_shipping_methods ) ){
unset( $gateways['bacs'] );
unset( $gateways['iyzico'] );
}
return $gateways;
}
add_filter( 'woocommerce_available_payment_gateways', 'payment_gateways_based_on_chosen_shipping_method' );
Related
I am trying to remove the proceed to checkout button and restrict access to the checkout page until a customer fills out the 'Calculate shipping' option on the basket page.
I created a local shipping method that's restricted to multiple post/zipcodes. I then went and added this to my functions.php file.
function disable_checkout_button_no_shipping() {
$package_counts = array();
// get shipping packages and their rate counts
$packages = WC()->shipping->get_packages();
foreach( $packages as $key => $pkg )
$package_counts[ $key ] = count( $pkg[ 'rates' ] );
// remove button if any packages are missing shipping options
if( in_array( 0, $package_counts ) )
remove_action( 'woocommerce_proceed_to_checkout', 'woocommerce_button_proceed_to_checkout', 20 );
}
add_action( 'woocommerce_proceed_to_checkout', 'disable_checkout_button_no_shipping', 1 );
However when I test the site in different browsers and in incognito modes the 'Proceed to checkout' button is there.
If I click on the 'Calculate shipping' link and not fill out the form but update it the button disappears. I basically want the button to appear when a customer fills out the 'Calculate shipping' form on the cart page (and have one of the postcodes in my shipping method) before being able to proceed to the checkout page.
You should better try with the "Chosen shipping method" from WooCommerce session like:
function disable_checkout_button_no_shipping() {
$chosen_shipping_methods = WC()->session->get( 'chosen_shipping_methods' );
// remove button if there is no chosen shipping method
if( empty( $chosen_shipping_methods ) ) {
remove_action( 'woocommerce_proceed_to_checkout', 'woocommerce_button_proceed_to_checkout', 20 );
}
}
add_action( 'woocommerce_proceed_to_checkout', 'disable_checkout_button_no_shipping', 1 );
Or in a different way using woocommerce_check_cart_items action hook:
add_action( 'woocommerce_check_cart_items', 'required_chosen_shipping_methods' );
function required_chosen_shipping_methods() {
$chosen_shipping_methods = WC()->session->get( 'chosen_shipping_methods' );
if( is_array( $chosen_shipping_methods ) && count( $chosen_shipping_methods ) > 0 ) {
// Display an error message
wc_add_notice( __("A shipping method is required in order to proceed to checkout."), 'error' );
}
}
It should better work.
On Woocommerce, I have enabled 2 shipping methods: Free shipping or Flat rate. I have enabled 2 payment methods: Bank transfer (bacs) and PayPal (paypal).
What I want to achieve:
If a customer selects PayPal as payment type he should be forced to select "Flat rate" as shipping method. "Free shipping" should be either hidden or greyed out or something like that.
If bank transfer is chosen then both shipping methods should be available.
Any help is appreciated.
If anyone is interested, I found a solution:
function alter_payment_gateways( $list ){
// Retrieve chosen shipping options from all possible packages
$chosen_rates = ( isset( WC()->session ) ) ? WC()->session->get( 'chosen_shipping_methods' ) : array();
if( in_array( 'free_shipping:1', $chosen_rates ) ) {
$array_diff = array('WC_Gateway_Paypal');
$list = array_diff( $list, $array_diff );
}
return $list;
}
add_action('woocommerce_payment_gateways', 'alter_payment_gateways');
This code will deactivate PayPal if a customer selects free shipping.
Update 2: The following code will disable "free_shipping" shipping method (method ID) when "paypal" is the chosen payment method:
add_filter( 'woocommerce_package_rates', 'shipping_methods_based_on_chosen_payment', 100, 2 );
function shipping_methods_based_on_chosen_payment( $rates, $package ) {
// Checking if "paypal" is the chosen payment method
if ( WC()->session->get( 'chosen_payment_method' ) === 'paypal' ) {
// Loop through shipping methods rates
foreach( $rates as $rate_key => $rate ){
if ( 'free_shipping' === $rate->method_id ) {
unset($rates[$rate_key]); // Remove 'Free shipping'shipping method
}
}
}
return $rates;
}
// Enabling, disabling and refreshing session shipping methods data
add_action( 'woocommerce_checkout_update_order_review', 'refresh_shipping_methods', 10, 1 );
function refresh_shipping_methods( $post_data ){
$bool = true;
if ( WC()->session->get('chosen_payment_method' ) ) $bool = false;
// Mandatory to make it work with shipping methods
foreach ( WC()->cart->get_shipping_packages() as $package_key => $package ){
WC()->session->set( 'shipping_for_package_' . $package_key, $bool );
}
WC()->cart->calculate_shipping();
}
// Jquery script for checkout page
add_action('wp_footer', 'refresh_checkout_on_payment_method_change' );
function refresh_checkout_on_payment_method_change() {
// Only checkout page
if( is_checkout() && ! is_wc_endpoint_url() ):
?>
<script type="text/javascript">
jQuery(function($){
// On shipping method change
$('form.checkout').on( 'change', 'input[name^="payment_method"]', function(){
$('body').trigger('update_checkout'); // Trigger Ajax checkout refresh
});
})
</script>
<?php
endif;
}
Code goes in function.php file of your active child theme (or active theme). Tested and works.
To get the related shipping methods rate IDs, something like flat_rate:12, inspect with your browser code inspector each related radio button attribute name like:
Note: Since WooCommerce new versions changes, sorry, the code doesn't work anymore.
I am developing a site with the following plugins:
WooCommerce
WooCommerce Subscriptions
Pakkelabels.dk for WooCommerce
"Pakkelabels.dk" is a packaging label plugin for carriers in Denmark. This plugin is using the standard WooCommerce filters and hooks to add additional shipping methods.
I am using a mixed checkout. The cart totals currently looks like this:
This is what I wan't to do
For recurring orders I wan't to limit the shipping methods to just "DAO Pakkeshop" and "Local pick up" (sorry for the Danish language in the image).
I have added this to functions.php, which unsets the shipping methods I don't wan't to have, when a specific product ID (the subscription product) is in the cart:
add_filter( 'woocommerce_package_rates', 'hide_shipping_methods_woo_sg', 10, 2 );
function hide_shipping_methods_woo_sg( $rates, $package ) {
$product_id = get_field('product_auto_cart', 'option');
if($product_id){
$product_cart_id = WC()->cart->generate_cart_id( $product_id );
$in_cart = WC()->cart->find_product_in_cart( $product_cart_id );
if($in_cart) {
unset( $rates['pakkelabels_shipping_dao_direct'] );
unset( $rates['pakkelabels_shipping_gls_private'] );
unset( $rates['pakkelabels_shipping_gls_business'] );
unset( $rates['pakkelabels_shipping_gls'] );
unset( $rates['pakkelabels_shipping_pdk'] );
unset( $rates['pakkelabels_shipping_postnord_private'] );
unset( $rates['pakkelabels_shipping_postnord_business'] );
// unset( $rates['local_pickup:19'] );
}
return $rates;
}
}
My problem is, that this removes the shipping methods for both the order and recurring order, as you can see on the image.
I need some sort of conditional, so that I can target only the recurring order shipping methods and unset those.
How can I achieve this?
Okay - that was a simple fix. WC()->cart->recurring_carts was the conditional I needed. My code now looks like this:
add_filter( 'woocommerce_package_rates', 'hide_shipping_methods_woo_sg', 10, 2 );
function hide_shipping_methods_woo_sg( $rates, $package ) {
$product_id = get_field('product_auto_cart', 'option');
if($product_id){
$product_cart_id = WC()->cart->generate_cart_id( $product_id );
$in_cart = WC()->cart->find_product_in_cart( $product_cart_id );
if($in_cart && WC()->cart->recurring_carts) {
unset( $rates['pakkelabels_shipping_dao_direct'] );
unset( $rates['pakkelabels_shipping_gls_private'] );
unset( $rates['pakkelabels_shipping_gls_business'] );
unset( $rates['pakkelabels_shipping_gls'] );
unset( $rates['pakkelabels_shipping_pdk'] );
unset( $rates['pakkelabels_shipping_postnord_private'] );
unset( $rates['pakkelabels_shipping_postnord_business'] );
// unset( $rates['local_pickup:19'] );
}
return $rates;
}
}
The above shipping methods are now removed for recurring carts.
My cart totals now looks like this:
How to disable BACS payment method for local delivery shipping method?
I have included the code below to my functions.php file, but it doesn't work.
Maybe someone could help me with this.
function my_custom_available_payment_gateways( $gateways ) {
$chosen_shipping_rates = WC()->session->get( 'chosen_shipping_methods' );
// When 'local delivery' has been chosen as shipping rate
if ( in_array( 'local_delivery', $chosen_shipping_rates ) ) :
// Remove bank transfer payment gateway
unset( $gateways['bacs'] );
endif;
return $gateways;
}
add_filter( 'woocommerce_available_payment_gateways', 'my_custom_available_payment_gateways' );
You are not far. To make your code working you need to manipulate the data in the array of chosen shipping methods to get only the slugs in a foreach loop.
Here is the code:
add_filter( 'woocommerce_available_payment_gateways', 'unset_bacs_for_local_delivery' );
function unset_bacs_for_local_delivery( $gateways ) {
// Not in backend (admin)
if( is_admin() )
return $gateways;
// Initialising variables
$chosen_shipping_method_ids = array();
$chosen_shipping_methods = (array) WC()->session->get( 'chosen_shipping_methods' );
// Iterating and manipulating the "chosen shipping methods" to get the SLUG
foreach( $chosen_hipping_methods as $shipping_method_rate_id ) :
$shipping_method_array = explode(':', $shipping_method_rate_id);
$chosen_shipping_method_ids[] = $shipping_method_array[0];
endforeach;
//When 'local delivery' has been chosen as shipping method
if ( in_array( 'local_delivery', $chosen_shipping_method_ids ) ) :
// Remove bank transfer payment gateway
unset( $gateways['bacs'] );
endif;
return $gateways;
}
This code is tested and is fully functional.
Code goes in functions.php file of your active child theme (or theme). Or also in any plugin php files.
I am trying to hide some payment options in Woocommerce in case of specific delivery option. I tried to put this to my functions.php but It´s not working and I don´t know why.
Can you help me please?
function payment_gateway_disable_country( $available_gateways, $available_methods )
{
global $woocommerce;
if ( isset( $available_methods['local_delivery'] ) ){
unset( $available_gateways['paypal'] );
}
return $available_gateways;
}
add_filter( 'woocommerce_available_payment_gateways', 'payment_gateway_disable_country' );
My research:
link 1
link 2
link 3
link 4
The available delivery methods do not get passed as a parameter in the filter woocommerce_available_payment_gateways - you need to load them in and check them.
The code below should remove the paypal payment option one if the user selects local delivery. If your checkout page is the AJAX based one then as the user changes the delivery method, the available payment options should also change.
function payment_gateway_disable_country($available_gateways) {
global $woocommerce;
$packages = $woocommerce->shipping->get_packages();
foreach ( $packages as $i => $package ) {
$chosen_method = isset( $woocommerce->session->chosen_shipping_methods[ $i ] ) ?
$woocommerce->session->chosen_shipping_methods[ $i ] : '';
if ('local_delivery' == $chosen_method) {
unset($available_gateways['paypal']);
break;
}
}
return $available_gateways;
}
add_filter(
'woocommerce_available_payment_gateways',
'payment_gateway_disable_country'
);
Let me know if you have any issues with the code; I did not have a chance to test it with woocommerce.
$available_methods will not be accessible inside your function. So first define it globally & access as global variable inside function, somewhat like this:
global $available_methods;
$available_methods = array( 'local_delivery' => 'yes' );
function payment_gateway_disable_country( $available_gateways )
{
global $woocommerce, $available_methods;
if ( isset( $available_methods['local_delivery'] ) ){
unset( $available_gateways['paypal'] );
}
return $available_gateways;
}
add_filter( 'woocommerce_available_payment_gateways', 'payment_gateway_disable_country' );