如何让WooCommerce订单状态保持为On-Hold,避免自动转为Completed?
解决WooCommerce订单保持“On hold”状态不自动变为“Completed”的方法
原代码失效原因
- 钩子时机不对:
woocommerce_payment_complete仅在支付完成时触发,无法覆盖订单标记发货等其他导致状态变为Completed的场景。 - 逻辑冗余:循环订单商品没有意义,需求是控制整个订单的状态,而非单个商品。
- 未阻止状态变更:代码只是重复设置on-hold状态,没有拦截后续触发状态变更的动作。
有效解决方案
方案一:拦截从On hold到Completed的状态转换
通过woocommerce_order_status_transition钩子,直接阻止订单从on-hold状态切换为completed状态:
add_action('woocommerce_order_status_transition', 'prevent_on_hold_to_completed', 10, 3); function prevent_on_hold_to_completed($order, $old_status, $new_status) { // 当订单试图从on-hold变为completed时,强制恢复为on-hold if ($old_status === 'on-hold' && $new_status === 'completed') { $order->set_status('on-hold'); $order->save(); } }
方案二:严格阻止所有设置Completed状态的操作
如果需要更全面的控制,使用woocommerce_before_order_status_change钩子,在状态变更前直接拦截:
add_action('woocommerce_before_order_status_change', 'prevent_completed_status_for_on_hold', 10, 4); function prevent_completed_status_for_on_hold($order_id, $new_status, $old_status, $order) { // 若当前订单是on-hold状态,禁止切换为completed if ($old_status === 'on-hold' && $new_status === 'completed') { $order->set_status('on-hold'); // 可选:添加调试日志,方便排查问题 error_log("订单 {$order_id} 状态变更被拦截:禁止从 {$old_status} 切换为 {$new_status}"); } }
方案三:标记发货时保持On hold状态
如果需要在标记订单发货时仍维持on-hold状态,添加以下代码:
// 移除on-hold订单的“完成订单”操作按钮 add_filter('woocommerce_order_actions', 'remove_complete_action_for_on_hold', 10, 2); function remove_complete_action_for_on_hold($actions, $order) { if ($order->has_status('on-hold')) { unset($actions['complete']); } return $actions; } // 标记发货时保持on-hold状态 add_action('woocommerce_mark_order_shipped', 'keep_on_hold_when_shipped', 10, 1); function keep_on_hold_when_shipped($order_id) { $order = wc_get_order($order_id); if ($order && $order->has_status('on-hold')) { // 保持on-hold状态,同时添加发货备注 $order->update_status('on-hold', '已寄送换货商品,等待原商品退回'); // 可自行添加追踪号等发货信息 $tracking_number = ''; // 替换为实际追踪号 $carrier = ''; // 替换为实际承运商 $order->add_order_note("已发货:追踪号 {$tracking_number},承运商 {$carrier}"); } }
使用说明
- 将上述代码添加到当前WordPress主题的
functions.php文件中,或使用自定义代码插件(如Code Snippets)管理代码,避免主题更新导致代码丢失。 - 测试时创建测试订单,模拟支付、发货等操作,确认状态是否保持为on-hold。
内容的提问来源于stack exchange,提问作者Rosalito Udtohan
相关产品推荐
相关产品推荐

