Custom checkout field enable or disable payment methods in Woocommerce 3 - php

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();
}
});

Related

Show additional information depending on shipping selected

I would like to show additional information/order notes when a specific shipping method was selected.
I have multiple shipping options and when selecting a specific one I need the user to provide a different address in the note, please see the images below:
These are the available shipping options:
I want to show this (and it has to be a required field)
I have seen this answer where a checkbox is used to show/hide the notes of an order on the checkout page:
By doing the following:
add_filter( 'woocommerce_checkout_fields', 'custom_checkout_order_notes' );
function custom_checkout_order_notes( $fields ) {
$fields['order']['order_comments']['class'][] = 'off';
return $fields;
}
add_action( 'woocommerce_before_order_notes', 'checkout_checkbox_show_hide_order_notes' );
function checkout_checkbox_show_hide_order_notes( $fields ) {
$target_id = 'order_comments';
?>
<style> p#<?php echo $target_id; ?>_field.off { display:none;}</style>
<script type="text/javascript">
jQuery(function($){
var a = 'input#checkbox_trigger', b = '#<?php echo $target_id; ?>_field';
$(b).hide('fast');
$(a).change(function(){
if( $(b).hasClass('off') ) {
$(b).removeClass('off');
}
if ( $(this).prop('checked') ) {
$(b).show('fast');
} else {
$(b).hide('fast', function(){
$(b+' input').val('');
});
}
});
});
</script>
<?php
woocommerce_form_field( 'checkbox_trigger', array(
'type' => 'checkbox',
'label' => __('Add a note to your order?', 'woocommerce'),
'class' => array('form-row-wide'),
'clear' => true,
), false );
}
But this is not what I want as described above.
Any help would greatly be appreciated.
I figured it out. I have added comments to help future readers.
add_action( 'woocommerce_billing_fields','woocommerce_check_if_shipping_changed' );
function woocommerce_check_if_shipping_changed() {
global $woocommerce;
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return;
// Get the selected shipping method
$chosen_methods = WC()->session->get( 'chosen_shipping_methods' );
$chosen_shipping = $chosen_methods[0];
// Check if it is one of the two I want to show "Aditional Information" for (using their ID's)
// I used developer tools to get their ID's
if ($chosen_shipping == 'wbs:6:5977f58e_postnet_to_postnet' || $chosen_shipping == 'wbs:6:014e3dff_pudo_locker') {
if ($chosen_shipping == 'wbs:6:014e3dff_pudo_locker'){
// Change additional notes label to : Pudo Locker Address:
add_filter('woocommerce_checkout_fields', 'make_order_label_pudo', 9999, 1);
}
if ($chosen_shipping == 'wbs:6:5977f58e_postnet_to_postnet'){
// Change additional notes label to : PostNet Address:
add_filter('woocommerce_checkout_fields', 'make_order_label_postnet', 9999, 1);
}
// Show order notes
add_filter( 'woocommerce_enable_order_notes_field', '__return_true', 9999 );
// Make order notes required
add_filter('woocommerce_checkout_fields', 'make_order_notes_required_field', 9999, 1);
}else{
// Hide order notes
add_filter( 'woocommerce_enable_order_notes_field', '__return_false', 9999 );
// Make order notes not a requirement
add_filter('woocommerce_checkout_fields', 'make_order_notes_not_required_field', 9999, 1);
}
}
function make_order_label_pudo( $fields ) {
$fields['order']['order_comments']['label'] = 'Pudo Locker Address:';
return $fields;
}
function make_order_label_postnet( $fields ) {
$fields['order']['order_comments']['label'] = 'PostNet Address:';
return $fields;
}
function make_order_notes_required_field( $fields ) {
$fields['order']['order_comments']['required'] = true;
return $fields;
}
function make_order_notes_not_required_field( $fields ) {
$fields['order']['order_comments']['required'] = false;
return $fields;
}
// The page needs to be refreshed of the changes to apply
add_action( 'wp_footer', 'checkout_shipping_refresh' );
function checkout_shipping_refresh() {
if ( is_checkout() && ! is_wc_endpoint_url() ) :
?><script type="text/javascript">
jQuery( function($){
let isRefreshPage = false;
$('form.checkout').on('change','input[name^="shipping_method"]',function() {
const val = $( this ).val();
isRefreshPage = true;
});
$('body').on('updated_checkout', function(){
if (isRefreshPage) {
location.reload();
}
});
});
</script>
<?php
endif;
}

Disable specific payment method when WooCommerce billing company is set

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.

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);
}

Apply percentage discount on Woocommerce cart items for new customers

We are using Klarna Checkout(3rd party plugin) to handle payments for our WooCommerce platform.
When the product is added to cart, Klarna Checkout Form appears with the details needed like email and contact number.
When a user enters their email, I determine if it's a new email to give 50% discount:
our-custom.js
var j = jQuery.noConflict();
// check every second if email is filled
var check_is_email_done = setInterval(function() {
var is_email_done = j('.klarna-widget-form-user .email').text();
if(is_email_done.length > 0) {
console.log('email is filled: ' + is_email_done);
var notFound = j('.fortnox-users td').filter(function(){
return j(this).text() == is_email_done;
}).get();
var token = notFound.length;
if(token > 0) {
console.log('Old customer..');
} else {
console.log('New customer..');
// call new_customer_discount() method in functions.php
j.ajax({
type: 'GET',
url: ajaxurl,
cache: false,
data: { action: 'newcustomerdiscount'},
success: function(data) {
console.log('newcustomerdiscount' + data);
},
error: function(xhr,status,error) {
console.log('newcustomerdiscount error:'+error);
}
});
}
clearInterval(check_is_email_done);
}
},1000);
functions.php
function new_customer_discount() {
//echo "new_customer_discount123";
$my_total = wc_format_decimal(WC()->cart->total, 2);
echo 'Total: '.$my_total;
do_action('woocommerce_calculate_totals', function($cart) {
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return;
print_r($cart);
$computed_price = 0;
// Loop Through cart items
foreach ( $cart->get_cart() as $cart_item ) {
// Get the product id (or the variation id)
$product_id = $cart_item['data']->get_id();
// GET THE NEW PRICE (code to be replace by yours)
if($computed_price > 0)
$prod_price = $computed_price * .50; // 50% discount
// Updated cart item price
$cart_item['data']->set_price( $prod_price );
}
});
}
The flow of my code above is when I determine if a customer is new, I call the new_customer_discount() method in functions.php then execute do_action with callback
Do you know how can I execute hook above in functions.php properly? Any help is greatly appreciated. Thanks
As I can't test your jQuery code, Let say that jQuery Ajax request works. Now to change cart items prices you need to use woocommerce_before_calculate_totals instead and in your php Ajax you will use WC_Session…
On your jQuery code, you might need to add on the success part the following line:
j('body').trigger('update_checkout'); // Refresh checkout
So your PHP code will be:
add_action('wp_ajax_nopriv_newcustomerdiscount', 'ajax_customer_discount');
add_action('wp_ajax_newcustomerdiscount', 'ajax_customer_discount');
function ajax_customer_discount() {
WC()->session->set('new_customer', true);
}
add_action('woocommerce_before_calculate_totals', 'set_new_customer_discount', 100, 1 );
function set_new_customer_discount( $cart ) {
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return;
if ( did_action( 'woocommerce_before_calculate_totals' ) >= 2 )
return;
// If it's not a new customer we exit
if( ! WC()->session->get('new_customer') )
return; // Exit
// Loop Through cart items
foreach ( $cart->get_cart() as $cart_item ) {
// 50% items discount
$cart_item['data']->set_price( $cart_item['data']->get_price() / 2 );
}
}
Code goes in function.php file of your active child theme (or active theme). Tested and works when WC()->session->get('new_customer') is true…

Categories