Show hide payment gateways based on checkout fields in Woocommerce [closed] - php

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 4 years ago.
Improve this question
In Woocommerce checkout page, I am trying to hide some payment gateways, keeping only "Cash on delivery" payment method (COD) when "Ship to a different address?" is checked.
I have tried Conditionally hiding et showing payment gateways with some changes, but I didn't worked. I have tried also different answer codes without succes.
How to keep only COD payment when "Ship to a different address?" is checked?
Any help is appreciated.

The following code will hide all payment gateways except "Cash on delivery" (COD) when "Ship to a different address?" is checked (and the shipping checkout fields are shown):
// The jQuery Ajax request
add_action( 'wp_footer', 'checkout_billing_area_script' );
function checkout_billing_area_script() {
// Only checkout page
if( is_checkout() && ! is_wc_endpoint_url() ):
// Remove "ship_different" custom WC session on load
if( WC()->session->get('ship_different') ){
WC()->session->__unset('ship_different');
}
// jQuery Ajax code below
?>
<script type="text/javascript">
jQuery( function($){
if (typeof wc_checkout_params === 'undefined')
return false;
var a = '#ship-to-different-address-checkbox', b = '';
// Ajax function
function triggerSTDA( value ){
$.ajax({
type: 'POST',
url: wc_checkout_params.ajax_url,
data: {
'action': 'ship_different_address',
'ship_different': value,
},
success: function (result) {
$('body').trigger('update_checkout');
console.log(result); // For testing (to be removed)
}
});
}
$(a).on( 'change', function(){
b = $(this).prop('checked') === true ? 'yes' : 'no';
triggerSTDA( b );
});
});
</script>
<?php
endif;
}
// The Wordpress Ajax PHP receiver
add_action( 'wp_ajax_ship_different_address', 'get_ajax_ship_different_address' );
add_action( 'wp_ajax_nopriv_ship_different_address', 'get_ajax_ship_different_address' );
function get_ajax_ship_different_address() {
if ( isset($_POST['ship_different']) ){
WC()->session->set('ship_different', esc_attr($_POST['ship_different']));
echo $_POST['ship_different'];
}
die();
}
// Show/hide payment gateways
add_filter( 'woocommerce_available_payment_gateways', 'conditionally_hide_payment_gateways', 100, 1 );
function conditionally_hide_payment_gateways( $available_gateways ) {
if( WC()->session->get('ship_different') == 'yes' ) {
foreach( $available_gateways as $gateways_id => $gateways ){
if( $gateways_id !== 'cod' ) {
unset($available_gateways[$gateways_id]);
}
}
}
return $available_gateways;
}
Code goes in function.php file of your active child theme (or active theme). Tested and work.

Related

WooCommerce Checkout: make fields (not) required depending on payment option

The requirement:
Depending on the chosen payment option, certain checkout fields should not be required.
My scenario:
It clients select "local pickup" they get the option to select PayPal, credit card etc. and "pay at pickup".
If they pay at pickup, we don't need they payment address. The invoice will be handled at pickup and the checkout is actually a reservation.
I have found a solution myself and share this question as a reference.
Find the solution in an answer.
This is my solution:
add_action( 'woocommerce_checkout_process', 'gw_deactivate_some_fields_on_condition');
function gw_deactivate_some_fields_on_condition() {
add_filter( 'woocommerce_checkout_fields' , 'gw_some_billing_fields_not_required_for_cash_on_delivery_payment_method' );
}
function gw_some_billing_fields_not_required_for_cash_on_delivery_payment_method( $fields ) {
$chosen_payment_method = WC()->session->get('chosen_payment_method');
if ( 0 === strpos( $chosen_payment_method, 'cash_on_delivery' ) ) {
$fields['billing']['billing_address_1']['required'] = false;
$fields['billing']['billing_address_2']['required'] = false;
$fields['billing']['billing_city']['required'] = false;
$fields['billing']['billing_postcode']['required'] = false;
$fields['billing']['billing_country']['required'] = false;
$fields['billing']['billing_state']['required'] = false;
}
return $fields;
}
add_action( 'woocommerce_after_checkout_form', 'gw_disable_payment_fields_if_local_payment' );
function gw_disable_payment_fields_if_local_payment( $available_gateways ) {
?>
<script type="text/javascript">
jQuery( document ).ready(function() {
show_hide_payment_options();
});
jQuery('form.checkout').on('change','input[name^="payment_method"]',function() {
show_hide_payment_options();
});
jQuery('form.checkout').on('change','input[name^="shipping_method"]',function() {
show_hide_payment_options();
});
function show_hide_payment_options() {
var val = jQuery('input[name^="payment_method"]:checked').val(); // If it changed, then it must be the radio options so check the one that's selected
var fields_selector = '#billing_country_field, #billing_address_1_field, #billing_address_2_field, #billing_city_field, #billing_postcode_field';
if (val.match("^cash_on_delivery")) {
jQuery( fields_selector ).fadeOut();
} else {
jQuery( fields_selector ).fadeIn();
}
}
</script>
<?php
}
For handling the shipping fields see this post:
https://www.businessbloomer.com/woocommerce-hide-shipping-local-pickup-selected/
This was also a strong inspiration for my code.

Show or hide html element on chosen shipping method change in Woocommerce

I'm trying to show/hide some elements from my checkout page, based on the chosen shipping method. The page elements I'm trying to show/hide come from another plugin, so I tried to change the display properties for them. I've looked to many thread like:
Show or hide checkout fields based on shipping method in Woocommerce 3
But it's for checkout fields, and I'm not sure how to do it for page elements.
Then based on this answer thread Here's my code so far:
add_action( 'wp_footer', 'conditionally_hidding_order_delivery_date' );
function conditionally_hidding_order_delivery_date(){
// Only on checkout page
if( ! is_checkout() ) return;
// HERE your shipping methods rate ID "Home delivery"
$home_delivery = 'distance_rate_shipping';
?>
<script>
jQuery(function($){
// Choosen shipping method selectors slug
var shipMethod = 'input[name^="shipping_method"]',
shipMethodChecked = shipMethod+':checked';
// Function that shows or hide imput select fields
function showHide( actionToDo='show', selector='' ){
if( actionToDo == 'show' )
$(selector).show( 200, function(){
$(this).addClass("validate-required");
});
else
$(selector).hide( 200, function(){
$(this).removeClass("validate-required");
});
$(selector).removeClass("woocommerce-validated");
$(selector).removeClass("woocommerce-invalid woocommerce-invalid-required-field");
}
// Initialising: Hide if choosen shipping method is "Home delivery"
if( $(shipMethodChecked).val() != '<?php echo $home_delivery; ?>' ) {
showHide('hide','#e_deliverydate_field' );
showHide('hide','#time_slot_field' );
}
// Live event (When shipping method is changed)
$( 'form.checkout' ).on( 'change', shipMethod, function() {
if( $(shipMethodChecked).val() == '<?php echo $home_delivery; ?>' ) {
showHide('show','#e_deliverydate_field' );
showHide('show','#time_slot_field' );
}
else {
showHide('hide','#e_deliverydate_field' );
showHide('hide','#time_slot_field' );
}
});
});
</script>
<?php
}
But it's not working completely (the initializing function is not working.)
Any help is very much appreciated.
Additional edit:
<p class="form-row form-row-wide validate-required" id="e_deliverydate_field" data-priority="" style="display: block;"><label for="e_deliverydate" class="">Date<abbr class="required" title="required">*</abbr></label><span class="woocommerce-input-wrapper"><input class="input-text hasDatepicker" name="e_deliverydate" id="e_deliverydate" placeholder="Choose a Date" value="" style="cursor:text !important;" type="text"></span></p>
My objective is to change the display properties for p element from block to none, and vice versa.
The needed code is something much more simple, than the one used in my other answers, but you need to be sure that the targeted chosen shipping method is 'distance_rate_shipping' as I can't test it.
For initialization problem, see the solution exposed at the end of my answer.
The simplified needed code:
// Embedded jQuery script
add_action( 'wp_footer', 'checkout_delivery_date_script' );
function checkout_delivery_date_script() {
// Only checkout page
if( ! ( is_checkout() && ! is_wc_endpoint_url() ) ) return;
?>
<script type="text/javascript">
jQuery( function($){
var a = 'input[name^="shipping_method"]', b = a+':checked',
c = 'distance_rate_shipping',
d = '#e_deliverydate_field,#time_slot_field';
// Utility function that show or hide the delivery date
function showHideDeliveryDate(){
if( $(b).val() == c )
$(d).show();
else
$(d).hide('fast');
console.log('Chosen shipping method: '+$(b).val()); // <== Just for testing (to be removed)
}
// 1. On start
showHideDeliveryDate();
// 2. On live event "change" of chosen shipping method
$('form.checkout').on('change', a, function(){
showHideDeliveryDate();
});
});
</script>
<?php
}
Code goes in function.php file of your active child theme (or theme). It should work.
The initialization problem:
It's certainly because the plugin you are using that generates the delivery date output is delayed after initialization
The solution can be to add some delay on initialization execution.
So should try to replace this:
// 1. On start
showHideDeliveryDate();
By the following in my code (adjusting the execution delay to something higher or lower than 500):
// 1. On start
setTimeout(function(){
showHideDeliveryDate();
}, 500);

Additional paypal fee on Woocommerce checkout page

In Woocommerce, we are trying to add an additional cost to the order when is purchased via Paypal payment gateway.
We did it changing the price that is sent to Paypal this way:
add_filter('woocommerce_paypal_args', 'addition_pay');
function addition_pay($paypal_args){
$new_value=$paypal_args['amount_1']+10;
$paypal_args['amount_1']=$new_value;
return $paypal_args;
}
It works, but the problem is after the payment process, this additional cost is not reflected in Orders and email notifications.
Is this can be solved in some way? Any help is appreciated.
You should better add a fee based on payment gateway (here Paypal for you), like in the following:
// Add a fee of 10.00 when Paypal is chosen
add_action( 'woocommerce_cart_calculate_fees', 'custom_paypal_additional_fee', 20, 1 );
function custom_paypal_additional_fee( $cart ) {
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return;
if( WC()->session->get( 'chosen_payment_method' ) == 'paypal' )
$cart->add_fee( __( 'Paypal fee', 'woocommerce' ), 10.00 );
}
// Add the information on checkout paypal text gateways section
add_filter('woocommerce_gateway_icon', 'custom_paypal_gateway_text', 20, 2 );
function custom_paypal_gateway_text( $html, $gateway_id ) {
if( $gateway_id == 'paypal' )
$html .= ' <small class="paypal-fee">(+ '.wc_price(10.00).')</small>';
return $html;
}
// Enable ajax update checkout event when choosing a gateway to refresh the fee
add_action('wp_footer', 'payment_gateways_update_checkout_event' );
function payment_gateways_update_checkout_event() {
?>
<script type="text/javascript">
(function($){
$('form.checkout').on( 'change', 'input[name^="payment_method"]', function() {
var t = { updateTimer: !1, dirtyInput: !1,
reset_update_checkout_timer: function() {
clearTimeout(t.updateTimer)
}, trigger_update_checkout: function() {
t.reset_update_checkout_timer(), t.dirtyInput = !1,
$(document.body).trigger("update_checkout")
}
};
$(document.body).trigger('update_checkout')
});
})(jQuery);
</script>
<?php
}
Code goes in function.php file of your active child theme (or active theme). Tested and work.

Conditionally hide a Checkout field in WooCommerce based on chosen shipping

in WooCommerce, I am trying to hide the company name field whenever "delivery to home" is selected. I've tried a bunch of different things.
This is my most recent attempt:
add_filter('woocommerce_checkout_fields', 'xa_remove_billing_checkout_fields');
function xa_remove_billing_checkout_fields($fields) {
$shipping_method ='pakkelabels_shipping_gls1'; // Set the desired shipping method to hide the checkout field(s).
global $woocommerce;
$chosen_methods = WC()->session->get( 'chosen_shipping_methods' );
$chosen_shipping = $chosen_methods[0];
if ($chosen_shipping == $shipping_method) {
unset($fields['billing']['billing_company']); // Add/change filed name to be hide
}
return $fields;
}
But all it does is move the Shipping company from the first field to the last.
How can I conditionally hide a specific checkout field based on chosen shipping method?
As it's a live event, you need to use javascript/jQuery to make it work. The Billing company has to be not required like in default WooCommerce checkout page.
The following code will hide the "Billing company" field, when "Home delivery" shipping is chosen:
// Conditional Show hide checkout fields based on chosen shipping methods
add_action( 'wp_footer', 'conditionally_hidding_billing_company' );
function conditionally_hidding_billing_company(){
// Only on checkout page
if( ! ( is_checkout() && ! is_wc_endpoint_url() ) ) return;
// HERE your shipping methods rate ID "Home delivery"
$home_delivery = 'pakkelabels_shipping_gls1';
?>
<script>
jQuery(function($){
// Choosen shipping method selectors slug
var shipMethod = 'input[name^="shipping_method"]',
shipMethodChecked = shipMethod+':checked';
// Function that shows or hide imput select fields
function showHide( actionToDo='show', selector='' ){
if( actionToDo == 'show' )
$(selector).show( 200, function(){
$(this).addClass("validate-required");
});
else
$(selector).hide( 200, function(){
$(this).removeClass("validate-required");
});
$(selector).removeClass("woocommerce-validated");
$(selector).removeClass("woocommerce-invalid woocommerce-invalid-required-field");
}
// Initialising: Hide if choosen shipping method is "Home delivery"
if( $(shipMethodChecked).val() == '<?php echo $home_delivery; ?>' )
showHide('hide','#billing_company_field' );
// Live event (When shipping method is changed)
$( 'form.checkout' ).on( 'change', shipMethod, function() {
if( $(shipMethodChecked).val() == '<?php echo $home_delivery; ?>' )
showHide('hide','#billing_company_field');
else
showHide('show','#billing_company_field');
});
});
</script>
<?php
}
Code goes in function.php file of your active child theme (or theme) or also in any plugin file.
Tested and works.

Woocommerce Conditional Options from Payment Method Selection

I am wondering if someone can help me with the following code. I am trying to set some conditional html dependent on which payment method the user selects on checkout. On the payment method page I am using the following function to update the payment method information:
function cart_update_script() {
if (is_checkout()) :
?>
<script>
jQuery( function( $ ) {
// woocommerce_params is required to continue, ensure the object exists
if ( typeof woocommerce_params === 'undefined' ) {
return false;
}
$checkout_form = $( 'form.checkout' );
$checkout_form.on( 'change', 'input[name="payment_method"]', function() {
$checkout_form.trigger( 'update' );
});
});
</script>
<?php
endif;
}
add_action( 'wp_footer', 'cart_update_script', 999 );
On the final checkout page I am then getting that selected payment method with this bit of code:
<?php $chosen_gateway = WC()->session->chosen_payment_method; ?>
Then I am using conditional statements like the following:
<?php if ( $chosen_gateway == 'stripe' ) { ?>
//do this
<?php } ?>
My problem is that I am not getting dynamic information when the user changes payment method. Sometimes the code works but sometimes it still thinks a different payment method was selected. Any help would be great!

Categories