You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

WooCommerce结账页Ajax添加多项费用 第二项触发400错误如何解决

问题根因

勾选高级礼盒选项时Ajax请求返回400的核心原因是第二个请求对应的WordPress Ajax action未注册回调:

  • 前端JS中给礼盒复选框绑定的请求,传入的action参数值为enable_fee_2
  • 但代码末尾仅为第一个保险费的enable_fee action注册了登录、未登录用户两类Ajax回调钩子,完全没有为enable_fee_2绑定处理函数,WordPress在admin-ajax.php中找不到匹配的回调时会直接返回400错误。
    除此之外现有代码还存在几个易触发异常的隐患:
  • 保险费计算函数as_calculate_insurance_fee()中部分逻辑分支未给$insurance_fee变量赋值,触发对应条件时会抛出PHP未定义变量警告
  • 礼盒费的显示名称存在拼写错误:Siganture 正确拼写为Signature
  • 两个复选框各自触发独立Ajax请求,存在不必要的性能开销,可合并逻辑简化代码
修复步骤
  • 为enable_fee_2 action补全登录、未登录用户的Ajax回调钩子,直接复用已有的会话存储逻辑即可,无需新增处理函数
  • 在保险费计算函数开头初始化$insurance_fee默认值为0,避免未定义变量问题
  • 修正费用名称的拼写错误
  • 替换原生die()为WordPress原生wp_die(),符合平台编码规范
修正后可直接使用的完整代码
// Calculate insurance fee
function as_calculate_insurance_fee() {
  // 初始化默认值,避免未定义变量警告
  $insurance_fee = 0;
  $shipping_country = WC()->customer->get_shipping_country();
  $cart_subtotal = WC()->cart->subtotal;
  $cart_subtotal_rounded = ceil($cart_subtotal / 100) * 100;

  if($shipping_country == 'AU') {
    if($cart_subtotal <= 5000) $insurance_fee = $cart_subtotal_rounded/100 + 1;

  } else {
    $chosen_methods = WC()->session->get( 'chosen_shipping_methods' );
    $chosen_shipping = $chosen_methods[0];

    if ($chosen_shipping == 'free_shipping:12' || $chosen_shipping == 'starshipit_4') {
      if($cart_subtotal <= 5000) $insurance_fee = $cart_subtotal_rounded/100 * 3;

    } else if($chosen_shipping == 'starshipit_5') {
      $insurance_fee = ($cart_subtotal_rounded - 1000)/100 * 3 + 25;
    }
  }

  return $insurance_fee;
}
 
// Add a Shipping Insurance checkbox field
function add_custom_checkout_checkbox() {
  $insurance_fee = as_calculate_insurance_fee();
  $checked = WC()->session->get('enable_fee') ? true : false;

  woocommerce_form_field( 'insurance_fee', array(
      'type'  => 'checkbox',
      'label' => __('<span class="woocommerce-Price-amount amount"><bdi><span class="woocommerce-Price-currencySymbol">'.get_woocommerce_currency().' </span>'.$insurance_fee.'</bdi></span>'),
      'class' => array( 'form-row-wide' ),
  ), $checked );
}
add_action( 'as_review_order_after_shipping', 'add_custom_checkout_checkbox', 20 );
 
// Add Signature Gift Box checkbox field
function add_custom_checkout_checkbox_2() {
  $checked = WC()->session->get('enable_fee_2') ? true : false;

  woocommerce_form_field( 'premium_giftbox_fee', array(
      'type'  => 'checkbox',
      'label' => __('<span class="woocommerce-Price-amount amount"><bdi><span class="woocommerce-Price-currencySymbol">'.get_woocommerce_currency().' </span>9</bdi></span>'),
      'class' => array( 'form-row-wide' ),
  ), $checked );
}
add_action( 'as_review_order_before_shipping', 'add_custom_checkout_checkbox_2', 20 );

// Add custom fees
function custom_fee( $cart ) {
  // Only on checkout
  if ( ( is_admin() && ! defined( 'DOING_AJAX' ) ) || ! is_checkout() )
    return;

  $insurance_fee = as_calculate_insurance_fee();

  if( WC()->session->get('enable_fee') )
    $cart->add_fee( __( 'Insurance fee', 'woocommerce'), $insurance_fee );

  if( WC()->session->get('enable_fee_2') )
    $cart->add_fee( __( 'Signature Gift Box fee', 'woocommerce'), 9 ); // 修正拼写错误
}
add_action( 'woocommerce_cart_calculate_fees', 'custom_fee', 20, 1 );

// Remove "(optional)" label on checkbox field
function remove_order_comments_optional_fields_label( $field, $key, $args, $value ) {
  if( ( 'insurance_fee' === $key || 'premium_giftbox_fee' === $key ) && is_checkout() ) {
    $optional = '&nbsp;<span class="optional">(' . esc_html__( 'optional', 'woocommerce' ) . ')</span>';
    $field = str_replace( $optional, '', $field );
  }
  return $field;
}
add_filter( 'woocommerce_form_field' , 'remove_order_comments_optional_fields_label', 10, 4 );

// jQuery - Ajax script
function checkout_fees_script() {
  // Only on Checkout
  if( is_checkout() && ! is_wc_endpoint_url() ) :

  if( WC()->session->__isset('enable_fee') )
      WC()->session->__unset('enable_fee');

  if( WC()->session->__isset('enable_fee_2') )
      WC()->session->__unset('enable_fee_2');
  ?>
  <script type="text/javascript">
  jQuery( function($){
    if (typeof wc_checkout_params === 'undefined') 
      return false;

    // 统一监听两个复选框变化,减少重复请求
    $('form.checkout').on('change', 'input[name=insurance_fee], input[name=premium_giftbox_fee]', function(e){
      const feeChecked = $('input[name=insurance_fee]').prop('checked') ? '1' : '';
      const fee2Checked = $('input[name=premium_giftbox_fee]').prop('checked') ? '1' : '';

      $.ajax({
        type: 'POST',
        url: wc_checkout_params.ajax_url,
        data: {
          'action': 'enable_fee',
          'enable_fee': feeChecked,
          'enable_fee_2': fee2Checked,
        },
        success: function () {
          $('body').trigger('update_checkout');
        },
      });
    });
  });
  </script>
  <?php
  endif;
}
add_action( 'wp_footer', 'checkout_fees_script' );

// Get Ajax request and saving to WC session
function get_enable_fee() {
  if ( isset($_POST['enable_fee']) ) {
    WC()->session->set('enable_fee', (bool)$_POST['enable_fee'] );
  }

  if ( isset($_POST['enable_fee_2']) ) {
    WC()->session->set('enable_fee_2', (bool)$_POST['enable_fee_2'] );
  }

  wp_die();
}

add_action( 'wp_ajax_enable_fee', 'get_enable_fee' );
add_action( 'wp_ajax_nopriv_enable_fee', 'get_enable_fee' );
// 补全第二个action的钩子,解决400问题
add_action( 'wp_ajax_enable_fee_2', 'get_enable_fee' );
add_action( 'wp_ajax_nopriv_enable_fee_2', 'get_enable_fee' );

内容的提问来源于stack exchange,提问作者Isabel AG

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 06:03:25