I use wordpress, woocommerce, and Paypal for a website.
I want to hide/disable the Paypal option from users from within a certain country. Due to Paypal doesn't do business there. http://recordit.co/oNF3aHp1D4
What code can achieve this without interfere with other users from using Paypal to checkout in other countries?
Found the answer to my question. Add this to your function.php
// Hide Paypal from _____ Country
function YOURTHEME_payment_gateway_disable_country( $available_gateways ) {
global $woocommerce;
if ( isset( $available_gateways['paypal'] ) && $woocommerce->customer->get_country() == 'YOUR COUNTRY CODE' ) {
unset( $available_gateways['paypal'] );
}
return $available_gateways;
}
add_filter( 'woocommerce_available_payment_gateways', 'YOURTHEME_payment_gateway_disable_country' );
Related
With WooCommerce I am using WooCommerce Subscriptions plugin. I have mainly Variable Subscription products and some few simple Subscription products.
I am using woocommerce_dropdown_variation_attribute_options_args filter hook, to update dropdown attribute values on my Variable Subscription products.
For Simple Subscriptions products I would like to add some conditions to allow or deny access to the product page.
So my question is: Which hook could I use to check if a product is a simple subscription, to allow or deny access to the product?
Any help/suggestion will be highly appreciated.
You can check product type on the WC_Product object for simple subscription like:
if( $product->get_type() === 'subscription' ) {
// Do something
}
or
if( $product->is_type('subscription') ) {
// Do something
}
And here below is an example usage that will avoid access to simple subscription product pages, redirecting customer to main shop page and displaying an error notice:
add_action('template_redirect', 'conditional_single_product_page_access');
function conditional_single_product_page_access(){
// Targeting single product pages
if ( is_product() ) {
$product = wc_get_product( get_the_ID() ); // Get the WC_Product Object
// Targeting simple subscription products
if( $product->get_type() === 'subscription' ) {
wc_add_notice( __("You are not allowed to access this product"), 'error' ); // Notice
wp_safe_redirect( get_permalink( wc_get_page_id( 'shop' ) ) ); // Redirection
exit();
}
}
}
Code goes in functions.php file of the active child theme (or active theme). Tested and works.
Notes:
To target variable subscription product type use the slug variable-subscription.
To target a variation subscription, the product type slug is: subscription_variation.
You can use is_subscription() of WC_Subscriptions_Product. You need to pass $product object in is_subscription() function as parameter. Check the below code.
if( WC_Subscriptions_Product::is_subscription( $product ) ) {
// product is subscription.
} else {
// product is not subscription.
}
Update
Use woocommerce_product_is_visible filter hook for remove the product from product catalog. check below code.
add_filter( 'woocommerce_product_is_visible', 'hide_product_if_is_subscription', 20, 2 );
function hide_product_if_is_subscription( $is_visible, $product_id ){
if( WC_Subscriptions_Product::is_subscription( $product_id ) ) {
$is_visible = false;
}
return $is_visible;
}
I would like to add a custom note automatically per order, based on if certain payment options are selected at checkout.
This would be a new line below the customers order notes.
Add the follows code snippet in your active theme's functions.php to achieve the above -
function modify_woocommerce_checkout_posted_data_comments( $posted_data ){
// Add extra custom notes for COD payment
if( isset( $posted_data['order_comments'] ) && isset( $posted_data['payment_method'] ) && $posted_data['payment_method'] == 'cod' ) {
$extra_note = __('Your custom notes goes here for COD payments.', 'textdomain' );
$posted_data['order_comments'] = nl2br( $posted_data['order_comments'] . "\n". $extra_note );
}
return $posted_data;
}
add_filter( 'woocommerce_checkout_posted_data', 'modify_woocommerce_checkout_posted_data_comments', 99 );
Here I added extra notes based on Cash on Delivery payment method. Change this as per your requirements.
In my Woocommerce shop I set up the geolocation system, when geolocation identifies any country other than IT I would like to disable payment methods
If it is IT (geop-ip), show payment methods
If all other country (geo-ip), disable all payment methods.
Woocommerce has already a geolocation Ip feature through WC_Geolocation class, so you don't need any additional plugin.
Here is the way to disable payment gateways for all countries except "IT" (Italy) country code, based on costumer geolocated IP country:
// Disabling payment gateways except for the defined country codes based on user IP geolocation country
add_filter( 'woocommerce_available_payment_gateways', 'geo_country_based_available_payment_gateways', 90, 1 );
function geo_country_based_available_payment_gateways( $available_gateways ) {
// Not in backend (admin)
if( is_admin() )
return $available_gateways;
// ==> HERE define your country codes
$allowed_country_codes = array('IT');
// Get an instance of the WC_Geolocation object class
$geolocation_instance = new WC_Geolocation();
// Get user IP
$user_ip_address = $geolocation_instance->get_ip_address();
// Get geolocated user IP country code.
$user_geolocation = $geolocation_instance->geolocate_ip( $user_ip_address );
// Disable payment gateways for all countries except the allowed defined coutries
if ( ! in_array( $user_geolocation['country'], $allowed_country_codes ) )
$available_gateways = array();
return $available_gateways;
}
Code goes in functions.php file of your active child theme (or active theme). Tested and works.
Related:
Disable WooCommerce payment gateway for guests and specific user roles
Enabling Payment method based on the customers location
Hide specific payment method based on total weight in Woocommerce
Hide payment method based on product type in WooCommerce
Here is a variation from #LoicTheAztec answer that disable just a specific payment method instead of all:
add_filter( 'woocommerce_available_payment_gateways', 'geo_country_based_available_payment_gateways', 90, 1 );
function geo_country_based_available_payment_gateways( $available_gateways ) {
// Not in backend (admin)
if( is_admin() )
return $available_gateways;
// ==> HERE define your country codes
$allowed_country_codes = array('DE','AT');
// Get an instance of the WC_Geolocation object class
$geolocation_instance = new WC_Geolocation();
// Get user IP
$user_ip_address = $geolocation_instance->get_ip_address();
// Get geolocated user IP country code.
$user_geolocation = $geolocation_instance->geolocate_ip( $user_ip_address );
// Disable payment gateways for all countries except the allowed defined coutries
if ( ! in_array( $user_geolocation['country'], $allowed_country_codes ) ) {
unset( $available_gateways['stripe_sofort'] );
}
return $available_gateways;
}
I know Istack, as well as maxmind etc ..
I thought something simpler like this function, which is based on the blling_country and not on the geo-ip country:
function payment_gateway_disable_country( $available_gateways ) {
global $woocommerce;
if ( is_admin() ) return;
if ( isset( $available_gateways['authorize'] ) && $woocommerce->customer->get_billing_country() <> 'US' ) {
unset( $available_gateways['authorize'] );
} else if ( isset( $available_gateways['paypal'] ) && $woocommerce->customer->get_billing_country() == 'US' ) {
unset( $available_gateways['paypal'] );
}
return $available_gateways;
}
add_filter( 'woocommerce_available_payment_gateways', 'payment_gateway_disable_country' );
In order to find out the user's country you can use a tool like FreeGeoIp, now renamed to Ipstack. You provide the service an IP address and it will tell you the country address the user is likely in (among other information).
There are two options
1. Using their hosted API (free for 10,000 requests and paid for more than that)
2. Downloading a release from the GitHub link and hosting it yourself
When you need to know the user's country you can send a HTTP request with the user's IP address to the API and then use that information to enable or disable the payment method.
In Woocommerce, I would like to hide "paypal" gateway on the "checkout" page before the order is created for the first time and just show "cash on delivery" gateway (labeled as Reserve).
On the other hand, on checkout/order-pay page when the order status is "pending", hide the 'Reserve' gateway and show "paypal". (this happens when we change the status of the order to "pending" manually and send the invoice to the customer with a payment link).
I thought it should be done by checking order status and using the woocommerce_available_payment_gateways filter hook. But I have problems with getting current order status.
Also I'm not sure what's the status of a newly created order which the user is on the checkout page and still the order is not shown in the admin backend.
This is my incomplete code:
function myFunction( $available_gateways ) {
// How to check if the order's status is not pending payment?
// How to pass the id of the current order to wc_get_order()?
$order = wc_get_order($order_id);
if ( isset($available_gateways['cod']) && /* pending order status?? */ ) {
// hide "cod" gateway
} else {
// hide "paypal" gateway
}
return $available_gateways;
}
add_filter( 'woocommerce_available_payment_gateways', 'myFunction' );
I also tried WC()->query_vars['order'] instead of wc_get_order(); to get the current order and check its status but it didn't work too.
I saw woocommerce_order_items_table action hook but couldn't get the order either.
How could I retrieve the Id and the status of the order on the checkout/order-pay page?
Update 2021
If I have correctly understood, You want to set/unset your available payment gateways, depending on the live generated order which status has to pending to have the "paypal" gateway. Ian all other cases the available gateway is only "reserve" (renamed "cod" payment gateway).
This code retrieve the live order ID using the get_query_var(), this way:
add_filter( 'woocommerce_available_payment_gateways', 'custom_available_payment_gateways' );
function custom_available_payment_gateways( $available_gateways ) {
// Not in backend (admin)
if( is_admin() )
return $available_gateways;
if ( is_wc_endpoint_url( 'order-pay' ) ) {
$order = wc_get_order( absint( get_query_var('order-pay') ) );
if ( is_a( $order, 'WC_Order' ) && $order->has_status('pending') ) {
unset( $available_gateways['cod'] );
} else {
unset( $available_gateways['paypal'] );
}
} else {
unset( $gateways['paypal'] );
}
return $available_gateways;
}
Code goes in functions.php file of your active child theme (or theme) or also in any plugin file.
The code is tested and works.
I don't know if it's possible, but, we would need to add some different payment methods for Barcelona.
So, our idea is that if the customer lives in Barcelona area (Catalunya), he will see a credit card payment method and a bank transfer account different than the rest of Spain.
Is that possible with WooCommerce?
Thanks.
If you want to enable this kind of feature in WooCommerce, Customers need to be registered and logged on first, as it's the only way to get they town location before checkout process.
Also you will have to change some settings in WooCommerce allowing only registerers users to checkout.
Then you will have to add some mandatory fields in the registration process as the town, zip code and country.
Once that done, it's going to be easy to enable / disable payment gateways based on this registered customer fields.
1) For customizing the registration fields:
How to add custom fields in user registration on the “My Account” page
2) For payment gateways/methods based on this Customer information, You can use a custom hooked function in woocommerce_available_payment_gateways filter hook:
add_filter( 'woocommerce_available_payment_gateways', 'custom_payment_gateways_process' );
function custom_payment_gateways_process( $available_gateways ) {
// Not in backend (admin)
if( is_admin() )
return $available_gateways;
if ( is_admin() || !is_user_logged_in() )
return $available_gateways;
$current_user_id = get_current_user_id();
$user_meta = get_user_meta( $current_user_id );
// User City, Postcode, State and Country code
$user_city = $user_meta['billing_city'];
$user_postcode = $user_meta['shipping_postcode'];
$user_State = $user_meta['shipping_state'];
$user_country = $user_meta['shipping_country'];
// Disable Cash on delivery ('cod') method example for customer out of spain:
if ( isset( $available_gateways['cod'] ) && $user_country != 'ES' ) {
unset( $available_gateways['cod'] );
}
// You can set many conditions based on the user data
return $available_gateways;
}
This code is just an example, and you will have to set inside the right conditions for the targeted payment methods/gateways…
Code goes in functions.php file of your active child theme (or theme) or also in any plugin file.