WordPress 6.5+WooCommerce 8.7:需获取$_POST数据的订单保存钩子
解决WooCommerce 8.7获取自定义配送字段并保存的问题
为什么你之前的钩子没用?
woocommerce_thankyou:这是订单完成后跳转的感谢页钩子,此时POST请求已经结束,全局$_POST早就清空了,拿不到数据很正常。woocommerce_store_api_checkout_update_order_meta:如果是块结账(当前WooCommerce默认用这个),结账请求走REST API,数据不在$_POST里,得从请求对象里取。
分两种场景解决
1. 经典结账(老版表单式结账)
直接用woocommerce_checkout_update_order_meta钩子,订单创建时触发,此时$_POST数据完整。
代码示例:
add_action('woocommerce_checkout_update_order_meta', 'save_my_custom_shipping_field', 10, 1); function save_my_custom_shipping_field($order_id) { // 把custom_shipping_field换成你JS添加的字段name属性 if (isset($_POST['custom_shipping_field'])) { // 清洗数据避免安全问题 $field_value = sanitize_text_field($_POST['custom_shipping_field']); // 保存到订单元数据,下划线前缀可隐藏在后台默认元数据列表中 update_post_meta($order_id, '_my_custom_shipping_field', $field_value); } }
2. 块结账(新版区块式结账)
这种情况走REST API,得从请求对象里拿数据,用woocommerce_rest_checkout_process_payment_with_context钩子:
代码示例:
add_action('woocommerce_rest_checkout_process_payment_with_context', 'save_custom_field_via_rest_api', 10, 2); function save_custom_field_via_rest_api($response, $request) { $order_id = $response->data['order_id']; // 若JS把字段加到了shipping对象里,用这个判断 if (isset($request['shipping']['custom_shipping_field'])) { $field_value = sanitize_text_field($request['shipping']['custom_shipping_field']); update_post_meta($order_id, '_my_custom_shipping_field', $field_value); } // 要是字段直接在请求根节点,用下面的判断 // if (isset($request['custom_shipping_field'])) { // $field_value = sanitize_text_field($request['custom_shipping_field']); // update_post_meta($order_id, '_my_custom_shipping_field', $field_value); // } return $response; }
要注意的点
- JS添加字段时,经典结账要确保字段在
<form id="checkout">表单内,否则提交时不会携带数据;块结账要把字段数据附加到结账请求的shipping或对应对象中,不然API拿不到。 - 字段名别和WooCommerce自带字段冲突,建议加自定义前缀,比如
my_shipping_xxx。 - 必须用
sanitize_text_field这类清洗函数处理数据,防止恶意内容注入。
内容的提问来源于stack exchange,提问作者Jakub Mráz
相关产品推荐
相关产品推荐

