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.
Related
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.
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.
In Woocommerce, I wrote the code for billing_state to use the shipping charge. Now I want to write the value from billing_state to billing_city, when changing billing_state, billing_city also changes
This are my custom states code:
add_filter( 'woocommerce_states', 'vietnam_cities_woocommerce' );
function vietnam_cities_woocommerce( $states ) {
$states['VN'] = array(
'HCM' => __('Hồ Chí Minh', 'woocommerce') ,
'HANOI' => __('Hà Nội', 'woocommerce') ,
'HAIPHONG' => __('Hải Phòng', 'woocommerce') ,
);
return $states;
}
Any help is appreciated.
The following code will fill up the city from the state value when the country is Vietnam (VN) in the checkout page:
// Add checkout custom select fields
add_action( 'wp_footer', 'custom_checkout_city_field', 20, 1 );
function custom_checkout_city_field() {
// Only checkout page
if( is_checkout() && ! is_wc_endpoint_url() ):
$country = 'VN'; // <=== <=== The country code
// $states = WC()->countries->get_shipping_country_states()[$country];
?>
<script type="text/javascript">
jQuery(function($){
var c = '<?php echo $country; ?>', f = 'form.checkout';
// On billing state change
$(f).on('change', '#billing_state', function(){
if($('#billing_country').val() == c ){
$('#billing_city').val($(this).val());
}
});
// On shipping state change
$(f).on('change', '#shipping_state', function(){
if($('#shipping_country').val() == c ){
$('#shipping_city').val($(this).val());
}
});
});
</script>
<?php
endif;
}
Code goes in function.php file of your active child theme (active theme). Tested and works.
In Woocommerce checkout form im trying to hide billing_city and billing_address_1 fields first and after I fill the fields postcode and housenumber the other fields (address_1 and city) has to show.
This is the script, but I does not work well and I dont know what I do wrong:
?>
<script type="text/javascript">
jQuery('input#billing_housenumber').change(function(){
if (this.checked) {
jQuery('#billing_city').fadeIn();
jQuery('#billing_city input').val('');
} else {
jQuery('#billing_city').fadeOut();
}
});
</script>
<?php
Any help is appreciated.
Update 2
There is some errors, mistakes and missing things in your code. Also you should hooked it in a function (or register it as an external file).
I have added at the end a function that add the billing "housenumber" field in checkout (just for testing purpose)…
In the code below I am using some CSS inline styles to hide the billing city and address_1 fields and to show them when they have an additional selector class "on".
Here is a hooked function that will enable this code in checkout only:
add_action( 'wp_footer', 'custom_checkout_script' );
function custom_checkout_script() {
// Only checkout page
if( ! ( is_checkout() && ! is_wc_endpoint_url() ) ) return;
// CSS Styles (Hidding fields)
?>
<style>
#billing_city_field, #billing_address_1_field { display:none !important;}
#billing_city_field.on ,#billing_address_1_field.on { display:block!important;}
</style>
<?php
// Jquery script
?>
<script type="text/javascript">
jQuery( function($){
var a = 'input#billing_housenumber',
b = 'input#billing_postcode',
c = '#billing_city_field,#billing_address_1_field';
// On start
if( $(a).val() != '' && $(b).val() != '' && ! $(c).hasClass('on') ){
$(c).css('display','none !important').addClass('on').show();
console.log('start');
}
// On change: If housenumber and postcode fields are filled, we display other hidden fields
$(a+','+b).on( 'change', function(){
if ( $(a).val() != '' && $(b).val() != '' && ! $(c).hasClass('on') ) {
$(c).css('display','none !important').addClass('on').show( 500 );
console.log('change - in');
} else if( ( $(a).val() == '' || $(b).val() == '' ) && $(c).hasClass('on') ) {
$(c).hide( 200, function(){
$(c).removeClass('on').css('display','block')
});
console.log('change - out');
}
});
});
</script>
<?php
}
Code goes in function.php file of your active child theme (or active theme). Tested and works.
This code has been tested with this temporary additional code, that generates the checkout "housenumber" text field (just for testing purpose):
// Add custom checkout field
add_action( 'woocommerce_billing_fields', 'my_custom_checkout_field' );
function my_custom_checkout_field( $fields ) {
$fields['billing_housenumber'] = array(
'class' => array('form-row-wide'),
'label' => __('Housenumber ?'),
'required' => false,
'clear' => true
);
return $fields;
}
Code goes in function.php file of your active child theme (or active theme).
Related: Show or hide html element on chosen shipping method change in Woocommerce
There is one step left. I don't see the housenumber (after a customer purchase a product). So you don't see the housenumber in the mail or in invoice.
This is in the e-mail but I don't see more detail for address:
/**
* #hooked WC_Emails::customer_details() Shows customer details
* #hooked WC_Emails::email_address() Shows email address
*/
do_action( 'woocommerce_email_customer_details', $order, $sent_to_admin, $plain_text, $email );
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.