Following Disable Payment Gateway For Specific Shipping Method On Checkout Only answer to my previous question, which:
Disables Payment Gateways ('cardgatecreditcard', 'cardgategiropay', 'cardgateideal', 'cardgatesofortbanking')
When Specific Shipping Methods are Selected ('flat_rate', 'request_shipping_quote')
However, it seems that the last part is causing a conflict with the WooCommerce Home page:
add_filter( 'woocommerce_available_payment_gateways', 'filter_woocommerce_available_payment_gateways', 10, 1 );
function filter_woocommerce_available_payment_gateways( $available_gateways ) {
$gateways_to_disable = array( 'cardgatecreditcard', 'cardgategiropay', 'cardgateideal', 'cardgatesofortbanking' );
$shipping_methods = array( 'flat_rate', 'request_shipping_quote' );
$disable_gateways = false;
// Check if we need to disable gateways
foreach ( $shipping_methods as $shipping_method ) {
if ( strpos( WC()->session->get( 'chosen_shipping_methods' )[0], $shipping_method ) !== false ) $disable_gateways = true;
}
// If so, disable the gateways
if ( $disable_gateways ) {
foreach ( $available_gateways as $id => $gateway ) {
if ( in_array( $id, $gateways_to_disable ) ) {
unset( $available_gateways[$id] );
}
}
}
return $available_gateways;
}
How do I go about troubleshooting this further?
This is the Fatal Error:
Fatal error: Uncaught Error: Call to a member function get() on null in /home/customer/www/multitrance.com/public_html/wp-content/themes/oceanwp-child/functions.php:304
Stack trace:
#0 /home/customer/www/multitrance.com/public_html/wp-includes/class-wp-hook.php(287): filter_woocommerce_available_payment_gateways(Array)
#1 /home/customer/www/multitrance.com/public_html/wp-includes/plugin.php(212): WP_Hook->apply_filters(Array, Array)
#2 /home/customer/www/multitrance.com/public_html/wp-content/plugins/woocommerce/includes/class-wc-payment-gateways.php(160): apply_filters('woocommerce_ava...', Array)
#3 /home/customer/www/multitrance.com/public_html/wp-content/plugins/woocommerce/packages/woocommerce-admin/src/Features/OnboardingTasks.php(92): WC_Payment_Gateways->get_available_payment_gateways()
#4 /home/customer/www/multitrance.com/public_html/wp-content/plugins/woocommerce/packages/woocommerce-admin/src/Features/OnboardingTasks.php(149): Automattic\WooCommerce\Admin\Features\OnboardingTasks::get_settings()
#5 /home/custo in /home/customer/www/multitrance.com/public_html/wp-content/themes/oceanwp-child/functions.php on line 304
Line 304:
if ( strpos( WC()->session->get( 'chosen_shipping_methods' )[0], $shipping_method ) !== false ) $disable_gateways = true;
You need to restrict your code to only checkout page:
add_filter( 'woocommerce_available_payment_gateways', 'filter_woocommerce_available_payment_gateways' );
function filter_woocommerce_available_payment_gateways( $available_gateways ) {
if( is_checkout() && ! is_wc_endpoint_url() ) {
$gateways_to_disable = array( 'cardgatecreditcard', 'cardgategiropay', 'cardgateideal', 'cardgatesofortbanking' );
$shipping_methods = array( 'flat_rate', 'request_shipping_quote' );
$chosen_shipping = WC()->session->get( 'chosen_shipping_methods' )[0];
$disable_gateways = false;
// Check if we need to disable gateways
foreach ( $shipping_methods as $shipping_method ) {
if ( strpos( $chosen_shipping, $shipping_method ) !== false ) {
$disable_gateways = true;
}
}
// If so, disable the gateways
if ( $disable_gateways ) {
foreach ( $available_gateways as $payment_id => $gateway ) {
if ( in_array( $payment_id, $gateways_to_disable ) ) {
unset( $available_gateways[$payment_id] );
}
}
}
}
return $available_gateways;
}
It should work without making trouble in home page
Related
In WooCommerce shop I have 2 delivery method based on Parcel locker. The first is payable in advance, while the second is cash on delivery.
The idea is:
easypack_parcel_machines -> only Pay in advance
easypack_parcel_machines_cod -> only Cash on delivery
My code below. After applying in both cases, I only have Pay in advance. What's wrong?
add_filter( 'woocommerce_available_payment_gateways', 'gateway_disable_shipping_meth' );
function gateway_disable_shipping_meth( $available_gateways ) {
if ( ! is_admin() ) {
$chosen_methods = WC()->session->get( 'chosen_shipping_methods' );
$chosen_shipping = $chosen_methods[0];
if ( isset( $available_gateways['bacs'] ) && 0 === strpos( $chosen_shipping, 'easypack_parcel_machines' ) ) {
unset( $available_gateways['cod'] );
}
elseif ( isset( $available_gateways['cod'] ) && 0 === strpos( $chosen_shipping, 'easypack_parcel_machines_cod' ) ) {
unset( $available_gateways['bacs'] );
}
}
return $available_gateways;
}
As both shipping methods start with the same slug, you should simply need to invert them in your if / elseif statement as follows (also there are some other mistake):
add_filter( 'woocommerce_available_payment_gateways', 'gateway_disable_shipping_meth' );
function gateway_disable_shipping_meth( $available_gateways ) {
if ( ! is_admin() ) {
$chosen_shipping = WC()->session->get( 'chosen_shipping_methods' )[0];
if ( isset( $available_gateways['bacs'] ) && 0 === strpos( $chosen_shipping, 'easypack_parcel_machines_cod' ) ) {
unset( $available_gateways['bacs'] );
}
elseif ( isset( $available_gateways['cod'] ) && 0 === strpos( $chosen_shipping, 'easypack_parcel_machines' ) ) {
unset( $available_gateways['cod'] );
}
}
return $available_gateways;
}
or also this way too:
add_filter( 'woocommerce_available_payment_gateways', 'gateway_disable_shipping_meth' );
function gateway_disable_shipping_meth( $available_gateways ) {
if ( ! is_admin() ) {
$chosen_shipping = WC()->session->get( 'chosen_shipping_methods' )[0];
if ( 0 === strpos( $chosen_shipping, 'easypack_parcel_machines' ) ) {
if ( false !== strpos( $chosen_shipping, 'cod' ) && isset( $available_gateways['bacs'] ) ) {
unset( $available_gateways['bacs'] );
} elseif ( isset( $available_gateways['cod'] ) ) {
unset( $available_gateways['cod'] );
}
}
}
return $available_gateways;
}
It should work.
I ran into an issue in WooCommerce and I'm wondering if anyone else has experienced it too.
I sell certain products that are too fragile to be shipped by UPS/DHL/FedEx. So I have to ship these products via pallet. To solve my problem I created a "request a quote" shipping method that allows my customers to select BACS as the payment method, request a quote as the shipping method and submit their orders. And after I have calculated the shipping costs, I update the order (change the shipping method to N/A) and change the status from "on-hold" to "pending payment" to allow the customer to pay by card if they wish to.
This is where I ran into the issue. I noticed that if I unset several payment gateways and if these certain shipping methods are selected, these payment gateways are not available to the customer in the "order-pay" endpoint (website/my-account/orders/) even if I remove the shipping method from the order.
Is there a way around this?
This is the code I am using to Disable Payment Gateway For Specific Shipping Method.
add_filter( 'woocommerce_available_payment_gateways', 'filter_woocommerce_available_payment_gateways', 10, 1 );
function filter_woocommerce_available_payment_gateways( $available_gateways ) {
$gateways_to_disable = array( 'cardgatecreditcard', 'cardgategiropay', 'cardgateideal', 'cardgatesofortbanking' );
$shipping_methods = array( 'flat_rate', 'request_shipping_quote' );
$disable_gateways = false;
// Check if we need to disable gateways
foreach ( $shipping_methods as $shipping_method ) {
if ( strpos( WC()->session->get( 'chosen_shipping_methods' )[0], $shipping_method ) !== false ) $disable_gateways = true;
}
// If so, disable the gateways
if ( $disable_gateways ) {
foreach ( $available_gateways as $id => $gateway ) {
if ( in_array( $id, $gateways_to_disable ) ) {
unset( $available_gateways[$id] );
}
}
}
return $available_gateways;
}
UPDATE After consulting with a few developers they advised that this code runs every time Payment Gateways are required and suggested that I run this snippet only on the Checkout page.
They suggested adding the following to my code:
if ( is_checkout_pay_page() ) {
// unset Payment Gateways
}
SOLVED Here's my attempt and it works. But not sure if it can we expressed better:
add_filter( 'woocommerce_available_payment_gateways', 'filter_woocommerce_available_payment_gateways', 10, 1 );
function filter_woocommerce_available_payment_gateways( $available_gateways ) {
if ( ! ( is_checkout_pay_page() ) ) {
$gateways_to_disable = array( 'cardgatecreditcard', 'cardgategiropay', 'cardgateideal', 'cardgatesofortbanking' );
$shipping_methods = array( 'flat_rate', 'request_shipping_quote' );
$disable_gateways = false;
// Check if we need to disable gateways
foreach ( $shipping_methods as $shipping_method ) {
if ( strpos( WC()->session->get( 'chosen_shipping_methods' )[0], $shipping_method ) !== false ) $disable_gateways = true;
}
// If so, disable the gateways
if ( $disable_gateways ) {
foreach ( $available_gateways as $id => $gateway ) {
if ( in_array( $id, $gateways_to_disable ) ) {
unset( $available_gateways[$id] );
}
}
}
return $available_gateways;
}
else { return $available_gateways;
}
}
add_filter( 'woocommerce_available_payment_gateways', 'filter_woocommerce_available_payment_gateways', 10, 1 );
function filter_woocommerce_available_payment_gateways( $available_gateways ) {
if ( ! ( is_checkout_pay_page() ) ) {
$gateways_to_disable = array( 'paymentgateway1', 'paymentgateway2', 'paymentgateway3' );
$shipping_methods = array( 'shippingmethod1', 'shippingmethod2', 'shippingmethod3' );
$disable_gateways = false;
// Check if we need to disable gateways
foreach ( $shipping_methods as $shipping_method ) {
if ( strpos( WC()->session->get( 'chosen_shipping_methods' )[0], $shipping_method ) !== false ) $disable_gateways = true;
}
// If so, disable the gateways
if ( $disable_gateways ) {
foreach ( $available_gateways as $id => $gateway ) {
if ( in_array( $id, $gateways_to_disable ) ) {
unset( $available_gateways[$id] );
}
}
}
return $available_gateways;
}
else { return $available_gateways;
}
}
This question already has answers here:
Show hide payment methods based on selected shipping method in Woocommerce
(2 answers)
Hide payment methods based on selected shipping method in WooCommerce [duplicate]
(1 answer)
Closed 2 years ago.
I created this code on WooCommerce to disable multiple payment gateways (cardgatecreditcard, cardgategiropay, cardgateideal and cardgatesofortbanking) for two different shipping methods (request_shipping_quote and flat_rate). But how do I simplify it?
// Disable Payment Gateway For Specific Shipping Method
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['cardgatecreditcard'] ) && 0 === strpos( $chosen_shipping, 'flat_rate' ) ) {
unset( $available_gateways['cardgatecreditcard'] );
}
if ( isset( $available_gateways['cardgategiropay'] ) && 0 === strpos( $chosen_shipping, 'flat_rate' ) ) {
unset( $available_gateways['cardgategiropay'] );
}
if ( isset( $available_gateways['cardgateideal'] ) && 0 === strpos( $chosen_shipping, 'flat_rate' ) ) {
unset( $available_gateways['cardgateideal'] );
}
if ( isset( $available_gateways['cardgatesofortbanking'] ) && 0 === strpos( $chosen_shipping, 'flat_rate' ) ) {
unset( $available_gateways['cardgatesofortbanking'] );
}
if ( isset( $available_gateways['cardgatecreditcard'] ) && 0 === strpos( $chosen_shipping, 'request_shipping_quote' ) ) {
unset( $available_gateways['cardgatecreditcard'] );
}
if ( isset( $available_gateways['cardgategiropay'] ) && 0 === strpos( $chosen_shipping, 'request_shipping_quote' ) ) {
unset( $available_gateways['cardgategiropay'] );
}
if ( isset( $available_gateways['cardgateideal'] ) && 0 === strpos( $chosen_shipping, 'request_shipping_quote' ) ) {
unset( $available_gateways['cardgateideal'] );
}
if ( isset( $available_gateways['cardgatesofortbanking'] ) && 0 === strpos( $chosen_shipping, 'request_shipping_quote' ) ) {
unset( $available_gateways['cardgatesofortbanking'] );
}
}
return $available_gateways;
}
Try the following:
add_filter( 'woocommerce_available_payment_gateways', 'filter_woocommerce_available_payment_gateways', 10, 1 );
function filter_woocommerce_available_payment_gateways( $available_gateways ) {
$gateways_to_disable = array( 'cardgatecreditcard', 'cardgategiropay', 'cardgateideal', 'cardgatesofortbanking' );
$shipping_methods = array( 'flat_rate', 'request_shipping_quote' );
$disable_gateways = false;
// Check if we need to disable gateways
foreach ( $shipping_methods as $shipping_method ) {
if ( strpos( WC()->session->get( 'chosen_shipping_methods' )[0], $shipping_method ) !== false ) $disable_gateways = true;
}
// If so, disable the gateways
if ( $disable_gateways ) {
foreach ( $available_gateways as $id => $gateway ) {
if ( in_array( $id, $gateways_to_disable ) ) {
unset( $available_gateways[$id] );
}
}
}
return $available_gateways;
}
I have successfully added this code to my functions.php, and it works - to great relief.
Here is a URL of it in action: https://www.bagnboxman.co.uk/?add-to-cart=207,7488,39439,939,393,395,396,411,1012,503
I would dearly love to redirect to the cart contents on loading this, so that a customer does not see a green wall of text "you have successfully added xyz to your cart"
Is this possible? How would I do this?
This is the code in question:
// adds support for multi add to cart for 3rd party cart plugin
function woocommerce_maybe_add_multiple_products_to_cart() {
// Make sure WC is installed, and add-to-cart qauery arg exists, and contains at least one comma.
if ( ! class_exists( 'WC_Form_Handler' ) || empty( $_REQUEST['add-to-cart'] ) || false === strpos( $_REQUEST['add-to-cart'], ',' ) ) {
return;
}
// Remove WooCommerce's hook, as it's useless (doesn't handle multiple products).
remove_action( 'wp_loaded', array( 'WC_Form_Handler', 'add_to_cart_action' ), 20 );
$product_ids = explode( ',', $_REQUEST['add-to-cart'] );
$count = count( $product_ids );
$number = 0;
foreach ( $product_ids as $product_id ) {
if ( ++$number === $count ) {
// Ok, final item, let's send it back to woocommerce's add_to_cart_action method for handling.
$_REQUEST['add-to-cart'] = $product_id;
return WC_Form_Handler::add_to_cart_action();
}
$product_id = apply_filters( 'woocommerce_add_to_cart_product_id', absint( $product_id ) );
$was_added_to_cart = false;
$adding_to_cart = wc_get_product( $product_id );
if ( ! $adding_to_cart ) {
continue;
}
// only works for simple atm
if ( $adding_to_cart->is_type( 'simple' ) ) {
// quantity applies to all products atm
$quantity = empty( $_REQUEST['quantity'] ) ? 1 : wc_stock_amount( $_REQUEST['quantity'] );
$passed_validation = apply_filters( 'woocommerce_add_to_cart_validation', true, $product_id, $quantity );
if ( $passed_validation && false !== WC()->cart->add_to_cart( $product_id, $quantity ) ) {
wc_add_to_cart_message( array( $product_id => $quantity ), true );
}
}
}
}
add_action( 'wp_loaded', 'woocommerce_maybe_add_multiple_products_to_cart', 15 );
I use this code snippet to below in order to disable Payment Gateway For Specific Shipping Method.
Snippet found here : https://businessbloomer.com/woocommerce-disable-payment-gateway-for-specific-shipping-method/
function bbloomer_gateway_disable_shipping_30( $available_gateways ) {
global $woocommerce;
$chosen_methods = WC()->session->get( 'chosen_shipping_methods' );
$chosen_shipping = $chosen_methods[0];
if ( isset( $available_gateways['cod'] ) && 0 === strpos( $chosen_shipping, 'local_pickup' ) ) {
unset( $available_gateways['cod'] );
}
if ( isset( $available_gateways['paypal'] ) && 0 === strpos( $chosen_shipping, 'local_pickup' ) ) {
unset( $available_gateways['paypal'] );
}
if ( isset( $available_gateways['stripe'] ) && 0 === strpos( $chosen_shipping, 'local_pickup' ) ) {
unset( $available_gateways['stripe'] );
}
return $available_gateways;
}
add_filter( 'woocommerce_available_payment_gateways', 'bbloomer_gateway_disable_shipping_30' );
This code triggers a 500 error with contact form 7
https://moebella24.ninapresotto.com/wp-json/contact-form-7/v1/contact-forms/57004/feedback 500