Disable specific payment method when WooCommerce billing company is set - php

I am trying to disable the paypal payment gateway when the company name is added on a new order but for some reason my code isn't working. Can somebody help me out?
// Disable gateway if company name is filled in
function payment_gateway_disable_paypal( $available_gateways ) {
global $woocommerce;
if ( isset( $available_gateways['paypal'] ) && $woocommerce->customer->get_billing_company() == "" ) {
unset( $available_gateways['paypal'] );
}
return $available_gateways;
}
add_filter( 'woocommerce_available_payment_gateways', 'payment_gateway_disable_paypal' );

Use the following to disable specific payment method when specific checkout field is filled by user on checkout page:
// Jquery script that send the Ajax request
add_action( 'woocommerce_after_checkout_form', 'custom_checkout_js_script' );
function custom_checkout_js_script() {
$field_key = 'billing_company'; // Here set the targeted field
WC()->session->__unset('field_'.$field_key);
?>
<script type="text/javascript">
jQuery(function($){
if (typeof wc_checkout_params === 'undefined')
return false;
var field = '[name="<?php echo $field_key; ?>"]';
$( 'form.checkout' ).on('input change', field, function() {
$.ajax({
type: 'POST',
url: wc_checkout_params.ajax_url,
data: {
'action': 'targeted_checkout_field_change',
'field_key': '<?php echo $field_key; ?>',
'field_value': $(this).val(),
},
success: function (result) {
$(document.body).trigger('update_checkout');
console.log(result); // For testing only
},
});
});
});
</script>
<?php
}
// The Wordpress Ajax PHP receiver
add_action( 'wp_ajax_targeted_checkout_field_change', 'get_ajax_targeted_checkout_field_change' );
add_action( 'wp_ajax_nopriv_targeted_checkout_field_change', 'get_ajax_targeted_checkout_field_change' );
function get_ajax_targeted_checkout_field_change() {
// Checking that the posted email is valid
if ( isset($_POST['field_key']) && isset($_POST['field_value']) ) {
// Set the value in a custom Woocommerce session
WC()->session->set('field_'. esc_attr($_POST['field_key']), esc_attr($_POST['field_value']) );
// Return the session value to jQuery
echo json_encode(WC()->session->get('field_'. esc_attr($_POST['field_key']))); // For testing only
}
wp_die(); // always use die at the end
}
// Disable specific payment method if specif checkout field is set
add_filter( 'woocommerce_available_payment_gateways', 'payment_gateway_disable_paypal' );
function payment_gateway_disable_paypal( $available_gateways ) {
if( is_admin() )
return $available_gateways;
$payment_id = 'paypal'; // Here define the payment Id to disable
$field_key = 'billing_company'; // Here set the targeted field
$field_value = WC()->session->get('field_'.$field_key);
if ( isset($available_gateways[$payment_id]) && ! empty($field_value) ) {
unset( $available_gateways[$payment_id] );
}
return $available_gateways;
}
Code goes in functions.php file of the active child theme (or active theme). Tested and works.

Related

Ajax Add to cart for simple and variable products on WooCommerce single products

The code below is working for add to cart with WooCommerce for simple products, but not for variable products. Can someone help me out? Because this code works with the latest WC, please do not remove this question because there are lots of codes for this online that do not work at all.
The error I am getting that is says in a notice that I should choose a product option, even when I chose one.
JS:
jQuery(function($) {
$('form.cart').on('submit', function(e) {
e.preventDefault();
var form = $(this);
form.block({ message: null, overlayCSS: { background: '#fff', opacity: 0.6 } });
var formData = new FormData(form.context);
formData.append('add-to-cart', form.find('[name=add-to-cart]').val() );
var $thisbutton = form.find('.single_add_to_cart_button'); //
// Ajax action
$.ajax({
url: wc_add_to_cart_params.wc_ajax_url.toString().replace( '%%endpoint%%', 'ace_add_to_cart' ),
data: formData,
type: 'POST',
processData: false,
contentType: false,
beforeSend: function (response) {
$thisbutton.removeClass('added').addClass('loading');
},
complete: function( response ) {
response = response.responseJSON;
if ( ! response ) {
return;
}
if ( response.error && response.product_url ) {
window.location = response.product_url;
return;
}
// Redirect to cart option
if ( wc_add_to_cart_params.cart_redirect_after_add === 'yes' ) {
window.location = wc_add_to_cart_params.cart_url;
return;
}
// Trigger event so themes can refresh other areas.
$( document.body ).trigger( 'added_to_cart', [ response.fragments, response.cart_hash, $thisbutton ] );
// Remove existing notices
$( '.woocommerce-error, .woocommerce-message, .woocommerce-info' ).remove();
// Add new notices
form.closest('.product').before(response.fragments.notices_html)
form.unblock();
}
});
});
});
PHP:
/* WOOCOMMERCE AJAX ADD TO CART
--------------------------------------------------- */
function ace_ajax_add_to_cart_handler() {
WC_Form_Handler::add_to_cart_action();
WC_AJAX::get_refreshed_fragments();
}
/* Add fragments for notices. */
function ace_ajax_add_to_cart_add_fragments( $fragments ) {
$all_notices = WC()->session->get( 'wc_notices', array() );
$notice_types = apply_filters( 'woocommerce_notice_types', array( 'error', 'success', 'notice' ) );
ob_start();
foreach ( $notice_types as $notice_type ) {
if ( wc_notice_count( $notice_type ) > 0 ) {
wc_get_template( "notices/{$notice_type}.php", array(
'messages' => array_filter( $all_notices[ $notice_type ] ),
'notices' => array_filter( $all_notices[ $notice_type ] ),
) );
}
}
$fragments['notices_html'] = ob_get_clean();
wc_clear_notices();
return $fragments;
}
add_action( 'wc_ajax_ace_add_to_cart', 'ace_ajax_add_to_cart_handler' );
add_action( 'wc_ajax_nopriv_ace_add_to_cart', 'ace_ajax_add_to_cart_handler' );
remove_action( 'wp_loaded', array( 'WC_Form_Handler', 'add_to_cart_action' ), 20 ); // Remove WC Core add to cart handler to prevent double-add
add_filter( 'woocommerce_add_to_cart_fragments', 'ace_ajax_add_to_cart_add_fragments' );
To enable Ajax add to cart for simple and variable products on Single product pages you need something different, building a custom Ajax add to cart function that handles also custom product fields and cart item data manipulation (what WooCommerce default Ajax add to cart doesn't allow).
Try the following fully tested on WooCommerce version 4.9.0:
add_action( 'wp_footer', 'single_product_ajax_add_to_cart_js_script' );
function single_product_ajax_add_to_cart_js_script() {
?>
<script>
(function($) {
$('form.cart').on('submit', function(e) {
e.preventDefault();
var form = $(this),
mainId = form.find('.single_add_to_cart_button').val(),
fData = form.serializeArray();
form.block({ message: null, overlayCSS: { background: '#fff', opacity: 0.6 } });
if ( mainId === '' ) {
mainId = form.find('input[name="product_id"]').val();
}
if ( typeof wc_add_to_cart_params === 'undefined' )
return false;
$.ajax({
type: 'POST',
url: wc_add_to_cart_params.wc_ajax_url.toString().replace( '%%endpoint%%', 'custom_add_to_cart' ),
data : {
'product_id': mainId,
'form_data' : fData
},
success: function (response) {
$(document.body).trigger("wc_fragment_refresh");
$('.woocommerce-error,.woocommerce-message').remove();
$('input[name="quantity"]').val(1);
$('.content-area').before(response);
form.unblock();
// console.log(response);
},
error: function (error) {
form.unblock();
// console.log(error);
}
});
});
})(jQuery);
</script>
<?php
}
add_action( 'wc_ajax_custom_add_to_cart', 'custom_add_to_cart_handler' );
add_action( 'wc_ajax_nopriv_custom_add_to_cart', 'custom_add_to_cart_handler' );
function custom_add_to_cart_handler() {
if( isset($_POST['product_id']) && isset($_POST['form_data']) ) {
$product_id = $_POST['product_id'];
$variation = $cart_item_data = $custom_data = array(); // Initializing
$variation_id = 0; // Initializing
foreach( $_POST['form_data'] as $values ) {
if ( strpos( $values['name'], 'attributes_' ) !== false ) {
$variation[$values['name']] = $values['value'];
} elseif ( $values['name'] === 'quantity' ) {
$quantity = $values['value'];
} elseif ( $values['name'] === 'variation_id' ) {
$variation_id = $values['value'];
} elseif ( $values['name'] !== 'add_to_cart' ) {
$custom_data[$values['name']] = esc_attr($values['value']);
}
}
$product = wc_get_product( $variation_id ? $variation_id : $product_id );
// Allow product custom fields to be added as custom cart item data from $custom_data additional array variable
$cart_item_data = (array) apply_filters( 'woocommerce_add_cart_item_data', $cart_item_data, $product_id, $variation_id, $quantity, $custom_data );
// Add to cart
$cart_item_key = WC()->cart->add_to_cart( $product_id, $quantity, $variation_id, $variation, $cart_item_data );
if ( $cart_item_key ) {
// Add to cart successful notice
wc_add_notice( sprintf(
'%s %d × "%s" %s' ,
wc_get_cart_url(),
__("View cart", "woocommerce"),
$quantity,
$product->get_name(),
__("has been added to your cart", "woocommerce")
) );
}
wc_print_notices(); // Return printed notices to jQuery response.
wp_die();
}
}
Code goes in functions.php file of the active child theme (or active theme). Tested and works.
All notices are enable and displayed on the fly:
Handling product custom fields and cart item data manipulation:
This custom Ajax add to cart code handle product custom fields, allowing to add them as custom cart item data.
For that we use woocommerce_add_cart_item_data WooCommerce dedicated hook enabled in our custom Ajax add to cart code, allowing to add product custom fields as custom cart item data or manipulate cart data on the fly.
If we add a product custom input text field with this code:
add_action( 'woocommerce_before_add_to_cart_button', 'product_additional_custom_fields' );
function product_additional_custom_fields() {
echo '<table class="variations" cellspacing="0" width="100px">
<tbody><tr>
<td class="label" style="width:100px"><label for="engraving">' . __("Engraving text") . '</label></td>
<td class="value">
<input type="text" name="engraving" id="engraving" value="" />
</td>
</tr></tbody>
</table>
</br>';
}
Then if you want to pass the field value as custom cart item data, you will use
add_filter( 'woocommerce_add_cart_item_data', 'add_cart_item_custom_data', 10, 5 );
function add_cart_item_custom_data( $cart_item_data, $product_id, $variation_id = 0, $quantity, $custom_data = array() ) {
if ( isset($custom_data['engraving']) && ! empty($custom_data['engraving']) ) {
$cart_item_data['engraving'] = sanitize_text_field($custom_data['engraving']);
}
return $cart_item_data;
}
And you can check with the following, that will display in cart and checkout that custom cart item data:
add_filter( 'woocommerce_get_item_data', 'display_on_cart_and_checkout', 10, 2 );
function display_on_cart_and_checkout( $cart_data, $cart_item ) {
if ( isset($cart_item['engraving']) ) {
$cart_data[] = array(
"name" => __("Engraving text", "woocommerce"),
"value" => $cart_item['engraving']
);
}
return $cart_data;
}
Code goes in functions.php file of the active child theme (or active theme). Tested and works.
Notes:
This code works on the fly as it is, but it's recommended to enqueue the jQuery code as an external file.
On some themes you should replace: $('.content-area').before(response); with $('.products').before(response);
to display the notices correctly…
Thanks for the helpful snippet, but the above code was not working for guest uses, but only for logins. The wc_fragment_refresh does not trigger when you log out And use it as a guest user.
$(document.body).trigger("wc_fragment_refresh");
Regards

How to add multiple products via checkbox at WooCommerce checkout (ajax)

So I have a script that I use to add a specific product to the cart when a checkbox is checked at checkout. AJAX is used to add and remove said product.
My question is, how can I cleanly and correctly manipulate this code to allow for an additional product to be added with a second checkbox. As in, say in the future I wanted the ability to add 1 or 2 extra "add-ons" how can I do this without duplicating code?
That is my current problem. I'm fairly decent at times, but often I find myself duplicating code knowing it has to be unnecessary. Any help appreciated (if you could explain a little bit it would be super appreciated. If not I can learn by examining the changes.)
// Display a custom checkout field
add_action( 'woocommerce_checkout_order_review', 'add_a_product1' , 10 );
function add_a_product1() {
$value = WC()->session->get('add_a_product');
woocommerce_form_field( 'cb_add_product', array(
'type' => 'checkbox',
'label' => ' ' . __('Add <span style="color:#ef4a23;">PRODUCT 1</span> for just <span style="color:#ef4a23;">$12.99?</span>'),
'class' => array('form-row-wide'),
), $value == 'yes' ? true : false );
}
// The jQuery Ajax request
add_action( 'wp_footer', 'checkout_custom_jquery_script' );
function checkout_custom_jquery_script() {
// Only checkout page
if( is_checkout() && ! is_wc_endpoint_url() ):
// Remove "ship_different" custom WC session on load
if( WC()->session->get('add_a_product') ){
WC()->session->__unset('add_a_product');
}
if( WC()->session->get('product_added_key') ){
WC()->session->__unset('product_added_key');
}
// jQuery Ajax code
?>
<script type="text/javascript">
jQuery( function($){
if (typeof wc_checkout_params === 'undefined')
return false;
$('form.checkout').on( 'change', '#cb_add_product', function(){
var value = $(this).prop('checked') === true ? 'yes' : 'no';
$.ajax({
type: 'POST',
url: wc_checkout_params.ajax_url,
data: {
'action': 'add_a_product',
'add_a_product': value,
},
success: function (result) {
$('body').trigger('update_checkout');
console.log(result);
}
});
});
});
</script>
<?php
endif;
}
// The Wordpress Ajax PHP receiver
add_action( 'wp_ajax_add_a_product', 'checkout_ajax_add_a_product' );
add_action( 'wp_ajax_nopriv_add_a_product', 'checkout_ajax_add_a_product' );
function checkout_ajax_add_a_product() {
if ( isset($_POST['add_a_product']) ){
WC()->session->set('add_a_product', esc_attr($_POST['add_a_product']));
echo $_POST['add_a_product'];
}
die();
}
// Add remove product
add_action( 'woocommerce_before_calculate_totals', 'adding_removing_specific_product' );
function adding_removing_specific_product( $cart ) {
if (is_admin() && !defined('DOING_AJAX'))
return;
if ( did_action( 'woocommerce_before_calculate_totals' ) >= 2 )
return;
// HERE the specific Product ID
$product_id = 2759;
if( WC()->session->get('add_a_product') == 'yes' && ! WC()->session->get('product_added_key') )
{
$cart_item_key = $cart->add_to_cart( $product_id );
WC()->session->set('product_added_key', $cart_item_key);
}
elseif( WC()->session->get('add_a_product') == 'no' && WC()->session->get('product_added_key') )
{
$cart_item_key = WC()->session->get('product_added_key');
$cart->remove_cart_item( $cart_item_key );
WC()->session->__unset('product_added_key');
}
}

WooCommerce extra fee on shipping cost if checkbox ship to other address is enabled

Is there an option that, say if a customer wants to ship to another address other than his billing address, can there be an extra fee based on that checkbox? I want that if a customer unchecks that checkbox, a extra fee of € 12.50 is added on the shipping cost. If anyone knows, please let me know :)
The checkbox is the default woocommerce checkbox btw.
I already fixed it by adding below code to the functions.php within your own theme:
add_filter( 'woocommerce_form_field' , 'remove_order_comments_optional_fields_label', 10, 4 );
function remove_order_comments_optional_fields_label( $field, $key, $args, $value ) {
// Only on checkout page for Order notes field
if( 'ship_to_different_address' === $key && is_checkout() ) {
$optional = ' <span class="optional">(' . esc_html__( 'optional', 'woocommerce' ) . ')</span>';
$field = str_replace( $optional, '', $field );
}
return $field;
}
// Ajax / jQuery script
add_action( 'wp_footer', 'ship_to_different_address_script' );
function ship_to_different_address_script() {
// On checkoutpage
if( ( is_checkout() && ! is_wc_endpoint_url() ) ) :
?>
<script type="text/javascript">
jQuery( function($){
if (typeof woocommerce_params === 'undefined')
return false;
console.log('defined');
$('input[name=ship_to_different_address]').click( function(){
var fee = $(this).prop('checked') === true ? '1' : '';
$.ajax({
type: 'POST',
url: woocommerce_params.ajax_url,
data: {
'action': 'ship_to_different_address',
'ship_to_different_address': fee,
},
success: function (result) {
$('body').trigger('update_checkout');
console.log(result);
},
});
});
});
</script>
<?php
endif;
}
// Get the ajax request and set value to WC session
add_action( 'wp_ajax_ship_to_different_address', 'get_ajax_ship_to_different_address' );
add_action( 'wp_ajax_nopriv_ship_to_different_address', 'get_ajax_ship_to_different_address' );
function get_ajax_ship_to_different_address() {
if ( isset($_POST['ship_to_different_address']) ) {
WC()->session->set('ship_to_different_address', ($_POST['ship_to_different_address'] ? '1' : '0') );
echo WC()->session->get('ship_to_different_address');
}
die();
}
// Add / Remove a custom fee
add_action( 'woocommerce_cart_calculate_fees', 'add_remove_ship_to_different_address', 10, 1 );
function add_remove_ship_to_different_address( $cart )
{
// Only on checkout
if ((is_admin() && !defined('DOING_AJAX')) || is_cart())
return;
$fee_amount = 12.50;
if (WC()->session->get('ship_to_different_address'))
$cart->add_fee(__('Shipping fee', 'woocommerce'), $fee_amount);
}

Custom checkout field enable or disable payment methods in Woocommerce 3

So i'm working on http://www.lichtunie.nl
We have a functioning checkout page with the needed fields.
The problem is this:
In the Netherlands (where we're based) We have something called KvK, if you start a company you need to register it there and you get a KvK number.
We can check those numbers through a website to see if they're legit and how their payment history is.
Now we have the option of "paying with cheque" Which let's you order and pay within a 30 day time period after receiving the invoice.
What we want now is that when someone doesn't fill in their KvK number field on checkout they can't use this method of payment.
As soon as they've filled in the "KvK number" field they should be able to though.
I've been looking for a while and just can't figure out how to do this. Anyone got any tips?
Thanks in advance,
Lex
The following code will keep only "cheque" payment method if the billing KVK number checkout field is filled or exist:
add_filter( 'woocommerce_available_payment_gateways', 'kvk_field_cheque_payment_method', 20, 1);
function kvk_field_cheque_payment_method( $gateways ){
foreach( $gateways as $gateway_id => $gateway ) {
// Not in backend (admin)
if( is_admin() )
return $gateways;
if( WC()->session->get( 'is_kvk_nummer' ) && $gateway_id != 'cheque' ){
unset( $gateways[$gateway_id] );
}
}
return $gateways;
}
// The Wordpress Ajax PHP receiver
add_action( 'wp_ajax_kvk_nummer', 'get_ajax_kvk_nummer' );
add_action( 'wp_ajax_nopriv_kvk_nummer', 'get_ajax_kvk_nummer' );
function get_ajax_kvk_nummer() {
if ( $_POST['bkvkn'] == '1' ){
WC()->session->set('is_kvk_nummer', '1');
} else {
WC()->session->set('is_kvk_nummer', '0');
}
die();
}
// The jQuery Ajax request
add_action( 'wp_footer', 'checkout_kvk_fields_script' );
function checkout_kvk_fields_script() {
// Only checkout page
if( is_checkout() && ! is_wc_endpoint_url() ):
// Remove "is_kvk_nummer" custom WC session on load
if( WC()->session->get('is_kvk_nummer') ){
WC()->session->__unset('is_kvk_nummer');
}
?>
<script type="text/javascript">
jQuery( function($){
var a = 'input#billing_kvk_nummer';
// Ajax function
function checkKvkNummer( value ){
$.ajax({
type: 'POST',
url: wc_checkout_params.ajax_url,
data: {
'action': 'kvk_nummer',
'bkvkn': value != '' ? 1 : 0,
},
success: function (result) {
$('body').trigger('update_checkout');
}
});
}
// On start
checkKvkNummer($(a).val());
// On change event
$(a).change( function () {
checkKvkNummer($(this).val());
});
});
</script>
<?php
endif;
};
Code goes in functions.php file of your active child theme (or active theme). Tested and works.
Addition
Also to hide "cheque" payment method if billing KVK number checkout field is not filled, replace the first function with this one:
add_filter( 'woocommerce_available_payment_gateways', 'kvk_field_cheque_payment_method', 20, 1);
function kvk_field_cheque_payment_method( $gateways ){
// Not in backend (admin)
if( is_admin() )
return $gateways;
foreach( $gateways as $gateway_id => $gateway ) {
if( $gateway_id != 'cheque' && WC()->session->get( 'is_kvk_nummer' ) ){
unset( $gateways[$gateway_id] );
} elseif( $gateway_id == 'cheque' && ! WC()->session->get( 'is_kvk_nummer' ) ){
unset( $gateways[$gateway_id] );
}
}
return $gateways;
}
It should work (untested).
Try this code your active theme custom js file
$( "#KvK_number" ).change(function() { //Here assign the KvK number ID
if (this.val() == "") {
$('#paying_with_cheque').hide(); /// Here give the Check payment div id
}
else
{
$('#paying_with_cheque').show();
}
});

Remove shipping cost if custom checkbox is checked in WooCommerce Checkout

I am trying to set the price of shipping rates to $0.00 if a checkbox in the checkout fields is checked.
Current Attempt:
function no_shipping_for_own_ups($rates,$package) {
foreach ($rates as $rate) {
//Set the price
$rate->cost = 0;
}
return $rates;
}
function woo_add_cart_ups_y_n_fee( $cart ){
if ( ! $_POST || ( is_admin() && ! is_ajax() ) ) {
return;
}
if ( isset( $_POST['post_data'] ) ) {
parse_str( $_POST['post_data'], $post_data );
} else {
$post_data = $_POST;
}
if (isset($post_data['billing_ups_yn'])) {
add_filter( 'woocommerce_package_rates','no_shipping_for_own_ups', 99, 2 );
}
}
add_action( 'woocommerce_cart_calculate_fees', 'woo_add_cart_ups_y_n_fee', 43, 1 );
As $post_data['billing_ups_yn'] being the checkbox that I set to update the checkout when triggered.
Simply if the checkbox is checked, then apply the filter to set shipping rates to 0.
This, however, isn't working.
To alter shipping methods cost via Ajax on a custom javascript event in checkout page is quiet more complicated than conditionally altering fees or anything else as you will see below.
To store the Ajax data I use WC_Sessions and to alter Shipping methods costs will only work if you manipulate the shipping sessions data
The full working code:
// Add a Custom checkbox field for shipping options (just for testing)
add_action( 'woocommerce_after_checkout_billing_form', 'custom_billing_checkbox_for_testing', 10, 1 );
function custom_billing_checkbox_for_testing( $checkout ) {
$field_id = 'billing_ups_yn';
// Get the checked state if exist
$billing_ups = WC()->session->get('billing_ups' );
if(empty($billing_ups))
$billing_ups = $checkout->get_value( $field_id );
// Add the custom checkout field (checkbox)
woocommerce_form_field( $field_id, array(
'type' => 'checkbox',
'class' => array( 'form-row-wide' ),
'label' => __('Billing UPS'),
), $billing_ups );
}
// function that gets the Ajax data
add_action( 'wp_ajax_woo_get_ajax_data', 'woo_get_ajax_data' );
add_action( 'wp_ajax_nopriv_woo_get_ajax_data', 'woo_get_ajax_data' );
function woo_get_ajax_data() {
if ( $_POST['billing_ups'] == '1' ){
WC()->session->set('billing_ups', '1' );
} else {
WC()->session->set('billing_ups', '0' );
}
echo json_encode( WC()->session->get('billing_ups' ) );
die(); // Alway at the end (to avoid server error 500)
}
// Conditionally changing the shipping methods costs
add_filter( 'woocommerce_package_rates','conditional_custom_shipping_cost', 90, 2 );
function conditional_custom_shipping_cost( $rates, $package ) {
if ( WC()->session->get('billing_ups' ) == '1' ){
foreach ( $rates as $rate_key => $rate_values ) {
// Not for "Free Shipping method" (all others only)
if ( 'free_shipping' !== $rate_values->method_id ) {
// Set the rate cost
$rates[$rate_key]->cost = 0;
// Set taxes rate cost (if enabled)
$taxes = array();
foreach ($rates[$rate_key]->taxes as $key => $tax)
if( $rates[$rate_key]->taxes[$key] > 0 ) // set the new tax cost
$taxes[$key] = 0;
$rates[$rate_key]->taxes = $taxes;
}
}
}
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('billing_ups' ) == '1' ) $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();
}
// The Jquery script
add_action( 'wp_footer', 'custom_checkout_script' );
function custom_checkout_script() {
?>
<script type="text/javascript">
jQuery( function($){
// update cart on delivery location checkbox option
$('#billing_ups_yn_field input').change( function () {
var checked = 0;
if ( $('#billing_ups_yn').is(':checked') )
checked = 1;
$.ajax({
type: 'POST',
url: wc_checkout_params.ajax_url,
data: {
'action': 'woo_get_ajax_data',
'billing_ups': checked,
},
success: function (result) {
$('body').trigger('update_checkout');
console.log('response: '+result); // just for testing
},
error: function(error){
console.log(error); // just for testing
}
});
});
});
</script>
<?php
}
Code goes in function.php file of your active child theme (or active theme).
Tested and works.
Update related to your comment:
If you wish to have always the checkbox unchecked by default at load you will replace the first function by this one:
// Add a Custom checkbox field for shipping options (just for testing)
add_action( 'woocommerce_after_checkout_billing_form', 'custom_billing_checkbox_for_testing', 10, 1 );
function custom_billing_checkbox_for_testing( $checkout ) {
$field_id = 'billing_ups_yn';
// Add the custom checkout field (checkbox)
woocommerce_form_field( $field_id, array(
'type' => 'checkbox',
'class' => array( 'form-row-wide' ),
'label' => __('Billing UPS'),
), '' );
}
I have similar project about 3 years ago and has radio button and date picker that will both modify and update the shipping details/amount when changed, the radio button will modify Shipping surcharge and the date picker will have -10 discount price when Saturday and Friday is selected from the calendar.
working example here
I assume you had knowledge with PHP and AJax and can modify this, you only need to modify few things like the session value and calculation as well as those jquery selector and form fields selector
function to handle ajax request, the purpose is to only assign $_SESSION value
add_action('wp_ajax_woo_modify_charges', 'etq_calculate', 10);
add_action('wp_ajax_nopriv_woo_modify_charges', 'etq_calculate', 10);
function etq_calculate() {
global $woocommerce;
$charge = isset($_POST['billing_area']) ? $_POST['billing_area'] : 'no';
$deldate = isset($_POST['jck_delivery_date']) ? $_POST['jck_delivery_date'] : '06/08/2015';
$delday = strtotime(str_replace('/', '-', $deldate));
$day = date('l', $delday);
if ( $day === 'Saturday' || $day === 'Friday') $val = -10;
else $val = 0;
if ( $charge === 'no' ) $surchage = 0;
else $surchage = 10;
if( !isset($_SESSION) ) session_start();
$_SESSION['val'] = $val;
$_SESSION['surcharge'] = $surchage;
}
Next function is to hook the modification on woocommerce_cart_calculate_fees from the value of $_SESSION.. this is where the price update happens
add_action('woocommerce_cart_calculate_fees', 'woo_change_cart_fee');
function woo_change_cart_fee() {
if(!isset($_SESSION)) session_start();
$surcharge = isset($_SESSION['surcharge']) ? $_SESSION['surcharge'] : 0;
$discount = isset($_SESSION['val']) ? $_SESSION['val'] : 0;
if ( $surcharge !== '0' ) WC()->cart->add_fee('Shipping Surchage', $surcharge, false, '');
if ( $discount !== '0' ) WC()->cart->add_fee('Delivery Discount', $discount, false, '');
}
then for jquery script that handles ajax
(function($){
'use strict';
$(document).ready( function() {
var $date_field = $('#jck_delivery_date');
// update cart on delivery date changes
$('#jck_delivery_date').bind('change', function () {
if ($('#billing_area_yes').is(':checked')) {
var surcharge = $('#billing_area_yes').val();
$('#billing_area_yes').prop('checked', true);
} else {
var surcharge = 'no';
}
var deldate = $('#jck_delivery_date').val();
var data = {
action: 'woo_modify_charges',
jck_delivery_date: deldate,
billing_area: surcharge
};
$.ajax({
type: 'POST',
url: wc_checkout_params.ajax_url,
data: data,
success: function (code) {
console.log(code);
//jQuery('.woocommerce-error, .woocommerce-message').remove();
if (code === '0') {
//$form.before(code);
$('body').trigger('update_checkout');
}
},
dataType: 'html'
});
return false;
});
// update cart on delivery location checkbox option
$('#billing_area_field input').change( function () {
if ($('#billing_area_yes').is(':checked')) {
var surcharge = $('#billing_area_yes').val();
} else {
var surcharge = 'no';
}
var deldate = $('#jck_delivery_date').val();
console.log( surcharge );
var data = {
action: 'woo_modify_charges',
billing_area: surcharge,
jck_delivery_date: deldate,
};
$.ajax({
type: 'POST',
url: wc_checkout_params.ajax_url,
data: data,
success: function (code) {
console.log(code);
//jQuery('.woocommerce-error, .woocommerce-message').remove();
if (code === '0') {
//$form.before(code);
$('body').trigger('update_checkout');
}
},
dataType: 'html'
});
return false;
});
});
})(jQuery);

Categories