我一直在使用自定义 WooCommerce 插件,该插件通过在结帐过程中单击按钮来设置固定的运费。虽然它通常总是按预期工作,但在每 20 个订单中大约有 2 个订单下单后,发货行本身在订单详细信息表、确认电子邮件或 WooCommerce 订单页面中不可见。
这是我正在使用的代码,希望有人可以帮助确定问题。
<?php
/**
* Plugin Name: Custom Shipping Value
* Description: Customizations for WooCommerce.
* Version: 1.0
* Author: udd_ish
**/
defined( 'ABSPATH' ) or exit;
add_action('wp_enqueue_scripts', 'enqueue_custom_scripts');
function enqueue_custom_scripts() {
// Enqueue the custom JS file
wp_enqueue_script('jquery');
wp_enqueue_script('distancecal-scripts', plugin_dir_url(__FILE__) . 'js/distancecal-scripts.js', array('jquery'), '1.0', true);
wp_localize_script('distancecal-scripts', 'ajax_object', array('ajaxurl' => admin_url('admin-ajax.php')));
}
function modify_shipping_cost($shipping_cost) {
if ( isset($shipping_cost) ){
WC()->session->set('shipping_cost', $shipping_cost);
error_log("Shipping cost set to $shipping_cost in session");
}
return $shipping_cost;
}
add_filter( 'woocommerce_form_field_button', 'create_button_form_field_type', 10, 4 );
function create_button_form_field_type( $field, $key, $args, $value ){
return sprintf('<p class="form-row %s" id="%s_field" data-priority="%s">
<button type="%s" id="%s" class="%s">%s</button>
</p>',
implode(' ', $args['class']), esc_attr($key), $args['priority'] ? $args['priority'] : '',
$args['type'], esc_attr($key), $args['input-class'], $args['label'] );
}
add_action('woocommerce_checkout_fields', 'insert_custom_button_in_billing_form');
function insert_custom_button_in_billing_form( $fields ) {
$fields['billing']['custom-button'] = array(
'type' => 'button',
'label' => __('Calculate Delivery Fee'),
'class' => array('form-row-wide'),
'input-class' => 'button alt',
'priority' => 61, // <== Field location (after Street address fields)
);
return $fields;
}
add_filter( 'woocommerce_cart_shipping_method_full_label', 'display_only_shipping_method_price', 10, 2 );
function display_only_shipping_method_price( $label, $method ) {
// HERE define your targeted rate id
$targeted_rate_id = 'flat_rate:4';
if ( $method->id === $targeted_rate_id && 0 < $method->cost ) {
$label = str_replace( $method->label . ': ', '', $label);
}
return $label;
}
add_filter( 'woocommerce_package_rates', 'shipping_package_rates_filter_callback', 100, 2 );
function shipping_package_rates_filter_callback( $rates, $package ) {
// HERE define your targeted rate id
$targeted_rate_id = 'flat_rate:4';
if ( ! array_key_exists($targeted_rate_id, $rates) )
return $rates;
$new_cost = WC()->session->get('shipping_cost'); // Get new cost from WC sessions
if ( ! empty($new_cost) ) {
// Set shipping label empty
$rates[$targeted_rate_id]->label = '';
$rate = $rates[$targeted_rate_id];
$cost = $rate->cost; // Set the initial cost in a variable for taxes calculations
$rates[$targeted_rate_id]->cost = $new_cost; // Set the new cost
$has_taxes = false; // Initializing
$taxes = array(); // Initializing
foreach ($rate->taxes as $key => $tax_cost){
if( $tax_cost > 0 ) {
$tax_rate = $tax_cost / $cost; // Get the tax rate conversion
$taxes[$key] = $new_cost * $tax_rate; // Set the new tax cost in taxes costs array
$has_taxes = true; // There are taxes (set it to true)
}
}
if( $has_taxes ) {
$rates[$targeted_rate_id]->taxes = $taxes; // Set taxes costs array
}
} else {
unset($rates[$targeted_rate_id]);
}
return $rates;
}
// PHP WP AJAX handler
add_action('wp_ajax_shipping_cost_update', 'shipping_cost_update_callback');
add_action('wp_ajax_nopriv_shipping_cost_update', 'shipping_cost_update_callback');
function shipping_cost_update_callback() {
$price = 100;
modify_shipping_cost($price);
wp_die(); // Make sure to exit after handling the AJAX request
}
// Refresh shipping methods
add_action('woocommerce_checkout_update_order_review', 'checkout_update_refresh_shipping_methods' );
function checkout_update_refresh_shipping_methods() {
if ( WC()->session->__isset('shipping_cost') ) {
$packages = WC()->cart->get_shipping_packages();
foreach ($packages as $package_key => $package ) {
WC()->session->set( 'shipping_for_package_' . $package_key, false ); // Or true
}
}
}
// Remove the WC session variable once the order is created
add_action('woocommerce_checkout_order_created', 'remove_wc_session_shipping_cost_variable', 10, 1);
function remove_wc_session_shipping_cost_variable( ) {
if ( WC()->session->__isset('shipping_cost') ) {
WC()->session->__unset('shipping_cost');
}
}
// (optional) Remove the WC Session variable on other pages than checkout
add_action('template_redirect', 'wc_session_shipping_cost_variable_only_on_checkout', 10, 1);
function wc_session_shipping_cost_variable_only_on_checkout() {
if ( ! ( is_checkout() && ! is_wc_endpoint_url() ) ) {
remove_wc_session_shipping_cost_variable();
}
}
这是JS代码
jQuery( function($) {
// Add your custom JavaScript here
$(document.body).on('click', '#custom-button', function() {
$('#custom-button').text('Calculating Delivery Fee').prop('disabled', true);
$.ajax({
type: 'POST',
url: ajax_object.ajaxurl,
data: {
action: 'shipping_cost_update'
},
success: function(response) {
console.log(response);
$('#custom-button').text('Calculate Delivery Fee').prop('disabled', false);
$(document.body).trigger('update_checkout', { update_shipping_method: true });
},
error: function(error) {
// Handle AJAX error if needed
console.error('AJAX error:', error);
$('#custom-button').text('Calculate Delivery Fee').prop('disabled', false);
alert('Error calculating delivery fee. Please try again.');
}
});
}
});
});
我找到了一个可能有用的选项,但是,可能还有更好的选择。
// Hook to modify taxes based on products and user roles
add_action('woocommerce_cart_calculate_fees', 'add_custom_tax_to_selected_products', 20, 1);
function add_custom_tax_to_selected_products($cart) {
// Check if it is admin or AJAX request, and avoid executing the code in that case
if (is_admin() && !defined('DOING_AJAX')) {
return;
}
// Check if the user has the 'usuario_diferente' role
if (!current_user_can('usuario_diferente')) {
return;
}
// IDs of products that should receive the 8% tax
$product_ids_with_tax = array(966, 301, 328, 326, 327, 355, 625); // Sustituir con los IDs reales de los productos
// Variable to store the total additional tax
$tax_amount = 0;
// Iterate over the products in the cart
foreach ($cart->get_cart() as $cart_item_key => $cart_item) {
$product_id = $cart_item['product_id'];
// Check if the product is on the list of products with additional tax
if (in_array($product_id, $product_ids_with_tax)) {
// Calculate 8% of the subtotal of this product
$item_total = $cart_item['line_total']; // Total price of the product in the cart without taxes
$tax_amount += ($item_total * 0.08); // Add 8% of the total price of that product
}
}
// Si hay un monto de impuesto a agregar, o no hay otros impuestos presentes
if ($tax_amount > 0) {
// Get current taxes
$taxes = WC()->cart->get_cart_contents_taxes();
// If taxes already exist, add the additional tax
if (!empty($taxes)) {
foreach ($taxes as $key => $value) {
$taxes[$key] += $tax_amount;
break; // We only modified the first tax found
}
} else {
// If there is no tax, we add the tax as the first one
$cart->add_fee(__('Impuesto', 'woocommerce'), $tax_amount, true); // Lo marcamos como impuesto
}
// Set modified taxes if there were already taxes
if (!empty($taxes)) {
WC()->cart->set_cart_contents_taxes($taxes);
}
}
}