如何防止WooCommerce商品库存降至-1及以下?
解决WooCommerce加密货币支付导致的库存负数问题
针对加密货币支付延迟引发的库存超卖问题,可通过调整库存处理逻辑、自定义订单状态和设置超时机制来解决,以下是具体方案:
1. 调整加密货币订单的库存扣减时机
默认WooCommerce会在订单创建时扣减库存,待处理订单超时后恢复,这是问题根源。我们可以改为仅在订单完成时扣减库存,取消时恢复库存,彻底避免待处理阶段的库存波动:
// 加密货币订单完成时扣减库存 add_action('woocommerce_order_status_completed', 'crypto_order_complete_deduct_stock', 10, 1); function crypto_order_complete_deduct_stock($order_id) { $order = wc_get_order($order_id); // 替换为你的加密货币支付网关slug(如coinbasecommerce) if ($order->get_payment_method() === 'your_crypto_gateway_slug') { foreach ($order->get_items() as $item) { $product = $item->get_product(); $qty = $item->get_quantity(); wc_update_product_stock($product, -$qty, 'edit'); } } } // 加密货币订单取消时恢复库存 add_action('woocommerce_order_status_cancelled', 'crypto_order_cancelled_restore_stock', 10, 1); function crypto_order_cancelled_restore_stock($order_id) { $order = wc_get_order($order_id); if ($order->get_payment_method() === 'your_crypto_gateway_slug') { foreach ($order->get_items() as $item) { $product = $item->get_product(); $qty = $item->get_quantity(); wc_update_product_stock($product, $qty, 'edit'); } } } // 禁用加密货币订单创建时的自动库存扣减 add_filter('woocommerce_can_reduce_order_stock', 'disable_crypto_order_stock_reduction', 10, 2); function disable_crypto_order_stock_reduction($reduce, $order) { if ($order->get_payment_method() === 'your_crypto_gateway_slug') { return false; } return $reduce; }
2. 创建专属的加密货币待确认订单状态
为加密货币订单单独设置一个状态,避免和普通待处理订单混淆,同时确保该状态下库存始终锁定:
// 注册「加密货币待确认」订单状态 add_action('init', 'register_crypto_pending_status'); function register_crypto_pending_status() { register_post_status('wc-crypto-pending', array( 'label' => '加密货币待确认', 'public' => true, 'exclude_from_search' => false, 'show_in_admin_all_list' => true, 'show_in_admin_status_list' => true, 'label_count' => _n_noop('加密货币待确认 (%s)', '加密货币待确认 (%s)') )); } // 将自定义状态添加到订单状态下拉菜单 add_filter('wc_order_statuses', 'add_crypto_pending_to_order_statuses'); function add_crypto_pending_to_order_statuses($order_statuses) { $new_order_statuses = array(); foreach ($order_statuses as $key => $status) { $new_order_statuses[$key] = $status; if ('wc-pending' === $key) { $new_order_statuses['wc-crypto-pending'] = '加密货币待确认'; } } return $new_order_statuses; } // 修改加密货币网关的默认订单状态为自定义状态 add_filter('woocommerce_payment_gateway_settings', 'set_crypto_gateway_default_status'); function set_crypto_gateway_default_status($settings) { foreach ($settings as &$setting) { // 替换为你的加密货币网关订单状态设置ID if (isset($setting['id']) && $setting['id'] === 'your_crypto_gateway_slug_order_status') { $setting['default'] = 'crypto-pending'; } } return $settings; } // 确保自定义状态下库存不被自动恢复 add_filter('woocommerce_restore_stock_after_order_cancellation', 'keep_stock_locked_for_crypto_pending', 10, 2); function keep_stock_locked_for_crypto_pending($restore, $order) { if ($order->get_status() === 'crypto-pending') { return false; } return $restore; }
3. 设置库存锁定超时机制
为加密货币订单设置合理的锁定时长(比如24小时,根据区块链确认速度调整),超时未确认则自动取消订单并恢复库存,避免库存被永久锁定:
// 初始化定时任务,每小时检查超时订单 add_action('wp', 'setup_crypto_order_timeout_cron'); function setup_crypto_order_timeout_cron() { if (!wp_next_scheduled('crypto_order_timeout_check')) { wp_schedule_event(time(), 'hourly', 'crypto_order_timeout_check'); } } // 执行超时订单检查与处理 add_action('crypto_order_timeout_check', 'check_crypto_order_timeouts'); function check_crypto_order_timeouts() { // 查询超过24小时未确认的加密货币订单 $args = array( 'status' => 'crypto-pending', 'date_created' => '<' . (time() - 24 * 60 * 60), 'limit' => -1 ); $orders = wc_get_orders($args); foreach ($orders as $order) { $order->update_status('cancelled', '加密货币支付超时未确认,自动取消'); crypto_order_cancelled_restore_stock($order->get_id()); } }
4. 前端库存显示优化
在商品页面显示实际可购买库存(总库存 - 加密货币待确认订单占用的库存),避免用户看到错误库存下单:
// 修改商品显示的库存数量 add_filter('woocommerce_get_availability_text', 'adjust_crypto_product_stock_display', 10, 2); function adjust_crypto_product_stock_display($text, $product) { if (!$product->is_in_stock()) return $text; $total_stock = $product->get_stock_quantity(); // 查询所有加密货币待确认订单中该商品的总占用量 $args = array( 'status' => 'crypto-pending', 'limit' => -1, 'meta_query' => array( array( 'key' => '_product_id', 'value' => $product->get_id(), 'compare' => '=' ) ) ); $pending_orders = wc_get_orders($args); $locked_qty = 0; foreach ($pending_orders as $order) { foreach ($order->get_items() as $item) { if ($item->get_product_id() === $product->get_id()) { $locked_qty += $item->get_quantity(); } } } $available_qty = $total_stock - $locked_qty; return $available_qty > 0 ? sprintf('库存:%d', $available_qty) : '暂时无货'; }
注意事项
- 所有代码需添加到主题的
functions.php文件或自定义插件中,修改前请备份文件。 - 替换代码中
your_crypto_gateway_slug为实际使用的加密货币支付网关的slug(可在WooCommerce支付设置中查看)。 - 可根据业务需求调整超时时间、库存锁定逻辑等参数。
内容的提问来源于stack exchange,提问作者William
相关产品推荐
相关产品推荐

