添加/移除优惠券后自动刷新WooCommerce结账地址字段
WooCommerce结账地址字段随订单总额自动显隐的解决方案
需求与现有问题
- 需求:当使用100%折扣码导致订单总额为0时,隐藏并设为非必填所有结账地址字段;当订单总额大于0时,恢复地址字段为必填并显示。
- 现有代码问题:仅在结账页首次加载时生效,用户在结账页添加/移除优惠券后,订单金额自动更新,但地址字段不会同步切换状态,需手动刷新页面才能恢复。
现有代码
add_filter( 'woocommerce_default_address_fields', 'customising_checkout_fields', 10000, 1 ); function customising_checkout_fields( $address_fields ) { $total = WC()->cart->cart_contents_total; if ( $total == 0 ) { $address_fields['address_1']['required'] = false; $address_fields['address_2']['required'] = false; $address_fields['company']['required'] = false; $address_fields['country']['required'] = false; $address_fields['city']['required'] = false; $address_fields['state']['required'] = false; $address_fields['postcode']['required'] = false; $address_fields['address_1']['hidden'] = true; $address_fields['address_2']['hidden'] = true; $address_fields['company']['hidden'] = true; $address_fields['country']['hidden'] = true; $address_fields['city']['hidden'] = true; $address_fields['state']['hidden'] = true; $address_fields['postcode']['hidden'] = true; } return $address_fields; }
完整解决方案
要实现地址字段随订单总额自动更新,需要后端PHP确保字段状态在AJAX请求中正确计算,加上前端JS监听结账更新事件同步切换字段状态,两者配合实现和购物车总额一致的自动更新逻辑。
1. 后端PHP调整代码
add_filter( 'woocommerce_default_address_fields', 'customising_checkout_fields', 10000, 1 ); function customising_checkout_fields( $address_fields ) { // 使用cart->total获取折扣后的最终订单总额(包含运费、税费等),判断更准确 $total = WC()->cart->total; $is_free_order = ( $total == 0 ); // 批量设置所有地址字段的必填和隐藏状态 foreach ( $address_fields as $key => $field ) { $address_fields[$key]['required'] = !$is_free_order; $address_fields[$key]['hidden'] = $is_free_order; } return $address_fields; } // 确保AJAX更新结账时,地址字段状态能重新计算 add_action( 'woocommerce_checkout_update_order_review', 'refresh_checkout_address_fields' ); function refresh_checkout_address_fields( $post_data ) { WC()->cart->calculate_totals(); }
2. 前端JS自动同步字段状态
将以下代码添加到主题的functions.php文件,或者自定义JS插件中:
add_action( 'wp_footer', 'checkout_address_auto_update_js' ); function checkout_address_auto_update_js() { // 仅在结账页(非订单完成等端点)加载脚本 if ( is_checkout() && ! is_wc_endpoint_url() ) { ?> <script> jQuery(document).ready(function($) { // 定义切换地址字段状态的函数 function toggleAddressFields() { // 提取订单总额数字(适配不同货币符号) var totalText = $('.order-total .woocommerce-Price-amount').text(); var orderTotal = parseFloat(totalText.replace(/[^0-9.]/g, '')); var billingFields = $('.woocommerce-billing-fields .form-row'); var shippingFields = $('.woocommerce-shipping-fields .form-row'); var allAddressInputs = $('.woocommerce-billing-fields input, .woocommerce-shipping-fields input'); if (orderTotal === 0) { billingFields.hide(); shippingFields.hide(); allAddressInputs.prop('required', false); } else { billingFields.show(); shippingFields.show(); // 恢复核心地址字段的必填属性(可根据需求调整字段ID) $('#billing_address_1, #billing_country, #billing_city, #billing_postcode').prop('required', true); $('#shipping_address_1, #shipping_country, #shipping_city, #shipping_postcode').prop('required', true); } } // 监听WooCommerce原生的结账更新事件(添加/移除优惠券、修改购物车都会触发) $(document.body).on('updated_checkout', toggleAddressFields); // 页面首次加载时执行一次,确保初始状态正确 toggleAddressFields(); }); </script> <?php } }
关键说明
- 后端改用
WC()->cart->total判断订单总额,避免仅计算商品总价导致的判断错误(比如含运费的订单用100%折扣后总额仍为0)。 - 前端监听
updated_checkout事件,这是WooCommerce结账页更新时的原生触发事件,确保和购物车金额更新逻辑完全同步。 - JS中通过正则提取数字适配不同货币格式,兼容性更强。
内容的提问来源于stack exchange,提问作者a1sin
相关产品推荐
相关产品推荐

