WooCommerce: Disable multiple Payment methods based on country - php

What I am trying to do here is hide payments methods, based on the customer country.
Hide bacs and cheque, when the country is different than US.
When the country is US, hide cod payment method (this is working)
I been trying to do this, but it didn't work
Here is the code:
add_filter( 'woocommerce_available_payment_gateways', 'custom_payment_gateway_disable_country' );
function custom_payment_gateway_disable_country( $available_gateways ) {
if ( is_admin() ) return $available_gateways;
if ( isset( $available_gateways['bacs' && 'cheque'] ) && WC()->customer->get_billing_country() <> 'US' ) {
unset( $available_gateways['bacs' && 'cheque'] );
} else {
if ( isset( $available_gateways['cod'] ) && WC()->customer->get_billing_country() == 'US' ) {
unset( $available_gateways['cod'] );
}
}
return $available_gateways;
}
Can someone push me in the right direction? Any help will be appreciated!

Your if/else statements are wrong. As isset( $available_gateways['bacs' && 'cheque'] will never work.
See: PHP If Statement with Multiple Conditions
So you get:
function filter_woocommerce_available_payment_gateways( $payment_gateways ) {
// Not on admin
if ( is_admin() ) return $payment_gateways;
// Get country
$customer_country = WC()->customer->get_shipping_country() ? WC()->customer->get_shipping_country() : WC()->customer->get_billing_country();
// Country = US
if ( in_array( $customer_country, array( 'US' ) ) ) {
// Cod
if ( isset( $payment_gateways['cod'] ) ) {
unset( $payment_gateways['cod'] );
}
} else {
// Bacs & Cheque
if ( isset( $payment_gateways['bacs'] ) && isset( $payment_gateways['cheque'] ) ) {
unset( $payment_gateways['bacs'] );
unset( $payment_gateways['cheque'] );
}
}
return $payment_gateways;
}
add_filter( 'woocommerce_available_payment_gateways', 'filter_woocommerce_available_payment_gateways', 10, 1 );

Related

WooCommerce Subscriptions - Changing the wording/removing subscription terms (eg /month)

I found this older post: How to change the "/ month" on a woocommerce subscription product page
'''
add_filter('woocommerce_subscriptions_product_price_string_inclusions',
'remove_subscription_inclusions', 10, 2);
function remove_subscription_inclusions( $include, $product ) {
$include['subscription_length'] = '';
return $include;
}
'''
That code works great for the product pages, but it doesn't remove the "/month" ('term' I guess would be the correct term) in the cart/checkout pages.
Does anyone have any idea how to apply the same thing as in the other post the cart/checkout pages as well?
// Line items pricing
add_filter( 'woocommerce_subscriptions_product_price_string', 'wc_subscriptions_product_price_string', 10, 3 );
function wc_subscriptions_product_price_string( $price_string, $product, $args ) {
if ( is_cart() || ( is_checkout() && ! is_wc_endpoint_url() ) ) {
return $args['price'];
}
return $price_string;
}
// Total line items
add_filter( 'woocommerce_subscription_price_string', 'wc_subscription_recurring_price_string', 10, 2 );
function wc_subscription_recurring_price_string( $subscription_string, $subscription_details ) {
if ( is_cart() || ( is_checkout() && ! is_wc_endpoint_url() ) ) {
$recurring_amount = $subscription_details['recurring_amount'];
if( is_numeric( $recurring_amount ) ) {
return strip_tags( wc_price($recurring_amount) );
}
else {
return $recurring_amount;
}
}
return $subscription_string;
}

Show cash on delivery (COD) based on applied coupons in WooCommerce

I am trying to have cash on delivery (COD) enabled only for customers that use certain type off coupons.
I have an existing code that, when coupons of a certain type are entered, converts the product sales price to the regular product price.
Now I would like to add that cash on delivery (COD) only is available for valid coupons within the same function.
The part that I have tried to add is this:
if ($coupons = WC()->cart->get_applied_coupons() == False )
unset( $available_gateways['cod'] );
Resulting in:
add_action( 'woocommerce_before_calculate_totals', 'add_custom_price', 10, 1);
function add_custom_price( $cart_object) {
global $woocommerce;
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return;
$coupon = False;
if ($coupons = WC()->cart->get_applied_coupons() == False )
unset( $available_gateways['cod'] );
if ($coupons = WC()->cart->get_applied_coupons() == False )
$coupon = False;
else {
foreach ( WC()->cart->get_applied_coupons() as $code ) {
$coupons1 = new WC_Coupon( $code );
if ($coupons1->type == 'percent_product' || $coupons1->type == 'percent')
$coupon = True;
}
}
if ($coupon == True)
foreach ( $cart_object->get_cart() as $cart_item )
{
$price = $cart_item['data']->regular_price;
$cart_item['data']->set_price( $price );
}
}
This does not give real error messages, but certainly not the desired result either. Any advice?
First of all I have rewritten your existing code, the part that converts sale prices to regular prices when a certain type of coupon is applied. This because your current code contains outdated methods:
function action_woocommerce_before_calculate_totals( $cart ) {
if ( is_admin() && ! defined( 'DOING_AJAX' ) ) return;
if ( did_action( 'woocommerce_before_calculate_totals' ) >= 2 ) return;
// Initialize
$flag = false;
// Applied coupons only
if ( sizeof( $cart->get_applied_coupons() ) >= 1 ) {
// Loop trough
foreach ( $cart->get_applied_coupons() as $coupon_code ) {
// Get an instance of the WC_Coupon Object
$coupon = new WC_Coupon( $coupon_code );
// Only for certain types, several can be added, separated by a comma
if ( in_array( $coupon->get_discount_type(), array( 'percent', 'fixed_product', 'percent_product' ) ) ) {
$flag = true;
break;
}
}
}
// True
if ( $flag ) {
// Loop through cart items
foreach ( $cart->get_cart() as $cart_item ) {
// Get regular price
$regular_price = $cart_item['data']->get_regular_price();
// Set new price
$cart_item['data']->set_price( $regular_price );
}
}
}
add_action( 'woocommerce_before_calculate_totals', 'action_woocommerce_before_calculate_totals', 10, 1 );
Then to only make COD active, if coupons of a certain type are applied you can use the woocommerce_available_payment_gateways hook
By default COD will not be available:
// Payment gateways
function filter_woocommerce_available_payment_gateways( $payment_gateways ) {
// Not on admin
if ( is_admin() ) return $payment_gateways;
// Initialize
$flag = false;
// WC Cart
if ( WC()->cart ) {
// Get cart
$cart = WC()->cart;
// Applied coupons only
if ( sizeof( $cart->get_applied_coupons() ) >= 1 ) {
// Loop trough
foreach ( $cart->get_applied_coupons() as $coupon_code ) {
// Get an instance of the WC_Coupon Object
$coupon = new WC_Coupon( $coupon_code );
// Only for certain types, several can be added, separated by a comma
if ( in_array( $coupon->get_discount_type(), array( 'percent', 'fixed_product', 'percent_product' ) ) ) {
$flag = true;
break;
}
}
}
}
// NOT true, so false
if ( ! $flag ) {
// Cod
if ( isset( $payment_gateways['cod'] ) ) {
unset( $payment_gateways['cod'] );
}
}
return $payment_gateways;
}
add_filter( 'woocommerce_available_payment_gateways', 'filter_woocommerce_available_payment_gateways', 10, 1 );
Both codes go goes in functions.php file of the active child theme (or active theme).
Tested in WordPress 5.8.1 and WooCommerce 5.8.0

Auto apply coupon based on custom user_meta in Woocommerce

First post here so be gentle. I have done my usual searching and testing but I am stumped.
Anyways here is my code that I am trying to use. I need to apply a coupon code that takes 2% off all orders if the user belongs to a certain buying group which is in their profile.
The coupon also does an exclude on one category at the moment so I don't know exactly how that factors in when automatically applying a code.
Does it just follow the restrictions for the coupon?
add_action( 'woocommerce_before_cart', 'anla_apply_buying_group_discount_coupon' );
function anla_apply_buying_group_discount_coupon() {
global $woocommerce;
global $current_user;
$user_id = get_current_user_id();
$maybe_has_buying_group_discount = get_user_meta( $user_id, 'has_buying_group_discount', true );
if ( '1' === $maybe_has_buying_group_discount ) {
return true;
}
elseif ( '0' === $maybe_has_buying_group_discount ) {
return false;
}
if ($maybe_has_buying_group_discount == true ) {
$woocommerce->cart->add_discount( 'buying group discount (2%)' );
}
elseif ($maybe_has_buying_group_discount == false ) {
$woocommerce->cart->remove_discount( 'buying group discount (2%)' );
$woocommerce->cart->calculate_totals();
}
}
Any help is appreciated.
There are some errors and deprecated methods in your code. The hook that you are using is not the right one. Instead try the following with additional notice messages:
add_action( 'woocommerce_before_calculate_totals', 'apply_group_discount_coupon', 20, 1 );
function apply_group_discount_coupon( $cart ) {
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return;
if ( did_action( 'woocommerce_before_calculate_totals' ) >= 2 )
return;
// HERE set your coupon code
$coupon_name = "buying group discount (2%)";
$user_id = get_current_user_id();
$discount_enabled = get_user_meta( $user_id, 'has_buying_group_discount', true );
$coupon_code = sanitize_title( $coupon_name );
if ( $discount_enabled && ! $cart->has_discount( $coupon_code ) ){
$cart->apply_coupon( $coupon_code );
$message = __("You have 2% of discount as Premium user group", 'woocommerce');
} elseif ( ! $discount_enabled && $cart->has_discount( $coupon_code ) ) {
$cart->remove_coupon( $coupon_code );
$message = __("You can't get a discount as Premium user group", 'woocommerce');
} else
return;
// Display a custom notice
if( isset($message) ){
wc_clear_notices();
wc_add_notice( $message, 'notice');
}
}
Code goes in function.php file of your active child theme (or active theme). Tested and works.
The version without message:
add_action( 'woocommerce_before_calculate_totals', 'apply_group_discount_coupon', 20, 1 );
function apply_group_discount_coupon( $cart ) {
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return;
// HERE set your coupon code
$coupon_name = "buying group discount (2%)";
$user_id = get_current_user_id();
$discount_enabled = get_user_meta( $user_id, 'has_buying_group_discount', true );
$coupon_code = sanitize_title( $coupon_name );
if ( $discount_enabled && ! $cart->has_discount( $coupon_code ) )
$cart->apply_coupon( $coupon_code );
elseif ( ! $discount_enabled && $cart->has_discount( $coupon_code ) ) {
$cart->remove_coupon( $coupon_code );
else
return;
}

Woocommerce payment options only for certain countries

I am trying to enable and disable certain payment functions for certain countries in Woocommerce. I had placed the following code in my functions:
function payment_gateway_disable_by_country( $available_gateways ) {
// Abort if in admin area
if ( is_admin() ) {
return $available_gateways;
}
$billing_country = WC()->customer->get_country();
$shipping_country = ! empty( WC()->customer->get_shipping_country() ) ? WC()->customer->get_shipping_country() : $billing_country;
if ( isset( $available_gateways['invoice'] ) && $billing_country != 'DE' ) {
unset( $available_gateways['invoice'] );
}
if ( isset( $available_gateways['cod'] ) && $shipping_country != 'DE' ) {
unset( $available_gateways['cod'] );
}
return $available_gateways;
}
add_filter( 'woocommerce_available_payment_gateways','payment_gateway_disable_by_country');
but then I am getting a white screen with the following error message:
Fatal error: Can't use method return value in write context in /home/www/mysite/html/wordpress/wp-content/themes/mytheme/functions.php on line 10.
Is there anything wrong with my code?

Disabling Amazon Payments Advanced method from WooCommerce checkout page

I'm trying to disable a couple of payment gateways based on a user's role. The function & hook I found works on the Paypal method but not Amazon Payments Advanced. Here's my code:
function wk_disable_gateways( $available_gateways ) {
global $woocommerce;
$wholesale_cust = check_user_role( array( 'wholesale', 'orig-wholesale' ) );
if ( isset( $available_gateways['paypal'] ) && $wholesale_cust ) {
unset( $available_gateways['paypal'] );
}
if ( isset( $available_gateways['amazon_payments_advanced'] ) && $wholesale_cust ) {
unset( $available_gateways['amazon_payments_advanced'] );
}
return $available_gateways;
}
add_filter( 'woocommerce_available_payment_gateways', 'wk_disable_gateways' );
The "Pay with Amazon" code is still running on the checkout page. Any ideas?
This is not the best solution, but I have not been able to find a more viable answer.
First off I did what you did and disabled all gateways expect the one I wanted the user to use. In my case I only want someone to check out with the nmigateway.
This goes inside of your theme functions.php
add_filter( 'woocommerce_available_payment_gateways', 'filter_gateways', 1);
function filter_gateways( $gateways ){
global $woocommerce;
// what products you wish to exculde
$nonPPproducts = array(1457, 1447, 479); // LIST YOUR PRODUCT IDS HERE
foreach ($woocommerce->cart->cart_contents as $key => $values ) {
if ( in_array( $values['product_id'], $nonPPproducts ) ) {
foreach ( $gateways as $gateway_key => $gateway ) {
if ( $gateway_key !== 'nmipay' ) {
unset( $gateways[ $gateway_key ] );
}
}
}
}
return $gateways;
}
Next here is the part that makes this not the best solution editing the plugins source code.
Change the following two functions inside of the plugins/woocommerce-gateway-amazon-payments-advanced/amazon-payments-advanced.php
/**
* Checkout Button
*
* Triggered from the 'woocommerce_proceed_to_checkout' action.
*/
function checkout_button() {
global $woocommerce;
// what products you wish to exculde
$nonPPproducts = array(1457, 1447, 479); // LIST YOUR PRODUCT IDS HERE
foreach ($woocommerce->cart->cart_contents as $key => $values ) {
if ( in_array( $values['product_id'], $nonPPproducts ) ) {
$disable_button = true;
}
}
if(!isset($disable_button) && $disable_button !== true ){
?><div id="pay_with_amazon"></div><?php
}
}
/**
* Checkout Message
*/
function checkout_message() {
global $woocommerce;
// what products you wish to exculde
$nonPPproducts = array(1457, 1447, 479); // LIST YOUR PRODUCT IDS HERE
foreach ($woocommerce->cart->cart_contents as $key => $values ) {
if ( in_array( $values['product_id'], $nonPPproducts ) ) {
$disable_button = true;
}
}
if(!isset($disable_button) && $disable_button !== true ){
if ( empty( $this->reference_id ) ) {
echo '<div class="woocommerce-info info"><div id="pay_with_amazon"></div> ' . apply_filters( 'woocommerce_amazon_pa_checkout_message', __( 'Have an Amazon account?', 'woocommerce-gateway-amazon-payments-advanced' ) ) . '</div>';
}
}
}
Keep in mind that when the plugin is updated all of your changes will be lost.

Categories