从 WooCommerce 中的自动补货中排除一个特定的支付网关

Exclude one specific payment gateway from auto-restock in WooCommerce

我的付款方式之一是 ipay88,它只会在付款清算后减少库存。

客户付款期间,订单在"pending payment"以下,库存没有减少。但是,当客户没有及时付款时,订单将自动标记为"cancelled"。

由于我集成了自动补货插件,"pending payment"到"cancelled"会增加库存。

我想问一下如何防止 ipay88 的特定付款假期的补货。

if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly

if ( ! class_exists( 'WC_Auto_Stock_Restore' ) ) {

class WC_Auto_Stock_Restore {

    public function __construct() {
    add_action( 'woocommerce_order_status_processing_to_cancelled', array( $this, 'restore_order_stock' ), 10, 1 );
        add_action( 'woocommerce_order_status_on-hold_to_cancelled', array( $this, 'restore_order_stock' ), 10, 1 );
        add_action( 'woocommerce_order_status_pending_to_cancelled', array( $this, 'restore_order_stock' ), 10, 1 );
        add_action( 'woocommerce_order_status_completed_to_cancelled', array( $this, 'restore_order_stock' ), 10, 1 );
        add_action( 'woocommerce_order_status_processing_to_refunded', array( $this, 'restore_order_stock' ), 10, 1 );
        add_action( 'woocommerce_order_status_completed_to_refunded', array( $this, 'restore_order_stock' ), 10, 1 );
        add_action( 'woocommerce_order_status_on-hold_to_refunded', array( $this, 'restore_order_stock' ), 10, 1 );
        add_action( 'woocommerce_order_status_cancelled_to_completed', array( $this, 'remove_order_stock' ), 10, 1 );
        add_action( 'woocommerce_order_status_cancelled_to_processing', array( $this, 'remove_order_stock' ), 10, 1 );
        add_action( 'woocommerce_order_status_cancelled_to_on-hold', array( $this, 'remove_order_stock' ), 10, 1 );
        add_action( 'woocommerce_order_status_cancelled_to_pending', array( $this, 'remove_order_stock' ), 10, 1 );
        //add_action( 'woocommerce_order_status_changed', array( $this, 'adjust_order_stock' ), 10, 3 );
    } // End __construct()

    //public function adjust_order_stock( $order_id, $old_status, $new_status ) {
        //$valid_new_statuses = array( 'complete' );
        //if ( $old_status == cancelled AND $new_status )
    //}

    public function remove_order_stock( $order_id ) {
        $order = new WC_Order( $order_id );

        if ( ! get_option('woocommerce_manage_stock') == 'yes' && ! sizeof( $order->get_items() ) > 0 ) {
            return;
        }

        foreach ( $order->get_items() as $item ) {

            if ( $item['product_id'] > 0 ) {
                $_product = $order->get_product_from_item( $item );

                if ( $_product && $_product->exists() && $_product->managing_stock() ) {
                    $old_stock = $_product->stock;

                    $qty = apply_filters( 'woocommerce_order_item_quantity', $item['qty'], $this, $item );

                    $new_quantity = $_product->reduce_stock( $qty );

                    do_action( 'woocommerce_auto_stock_restored', $_product, $item );

                    $order->add_order_note( sprintf( __( 'Item #%s stock decremented from %s to %s.', 'woocommerce' ), $item['product_id'], $old_stock, $new_quantity) );

                    $order->send_stock_notifications( $_product, $new_quantity, $item['qty'] );
                }
            }
        }
    }

    public function restore_order_stock( $order_id ) {
        $order = new WC_Order( $order_id );

        if ( ! get_option('woocommerce_manage_stock') == 'yes' && ! sizeof( $order->get_items() ) > 0 ) {
            return;
        }

        foreach ( $order->get_items() as $item ) {

            if ( $item['product_id'] > 0 ) {
                $_product = $order->get_product_from_item( $item );

                if ( $_product && $_product->exists() && $_product->managing_stock() ) {
                    $old_stock = $_product->stock;

                    $qty = apply_filters( 'woocommerce_order_item_quantity', $item['qty'], $this, $item );

                    $new_quantity = $_product->increase_stock( $qty );

                    do_action( 'woocommerce_auto_stock_restored', $_product, $item );

                    $order->add_order_note( sprintf( __( 'Item #%s stock incremented from %s to %s.', 'woocommerce' ), $item['product_id'], $old_stock, $new_quantity) );

                    $order->send_stock_notifications( $_product, $new_quantity, $item['qty'] );
                }
            }
        }
    } // End restore_order_stock()
}
$GLOBALS['wc_auto_stock_restore'] = new WC_Auto_Stock_Restore();
}

Updated, tested and fully functional for Woocommerce versions 3+

自 WooCommerce 版本 3 以来,您的代码确实已过时。所以我重新访问了所有代码…

同样,对于每种状态更改使用多个挂钩,您可以用一个唯一的挂钩替换所有挂钩:woocommerce_order_status_changed

最后,有了那个独特的挂钩,您将需要一个独特的功能,可以在订单状态更改时轻松排除您的 'ipay88' 支付网关 ID从 'pending' 到 'cancelled'.

对于生成的订单备注,当订单中有多个商品时,最好得到一个唯一的订单备注...

所以这个插件的完整代码是:

## ---- for WooCommerce versions 3+ - Plugin code version ---- ##

if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly

if ( ! class_exists( 'WC_Auto_Stock_Restore' ) ) {

    class WC_Auto_Stock_Restore {

        public function __construct() {
            add_action( 'woocommerce_order_status_changed', array( $this, 'adjust_order_stock' ), 10, 3 );
        }

        public function adjust_order_stock( $order_id, $old_status, $new_status ) {
            $order = new WC_Order( $order_id );
            $items = $order->get_items();

            if ( ! get_option('woocommerce_manage_stock') == 'yes' && ! count( $items ) > 0 )
                return; // We exit

            // EXCEPTION for 'ipay88' payment method id, when Order status change from 'pending' to 'cancelled'
            if( $order->get_payment_method() == 'ipay88' && $old_status == 'pending' && $new_status == 'cancelled' )
                return; // We exit

            // We don't need from 'pending' to 'refunded' order status
            if( $old_status == 'pending' && $new_status == 'refunded' )
                return; // We exit

            // Group Order statuses in 2 groups (array)
            $statuses_group1 = array( 'processing', 'on-hold', 'pending', 'completed' );
            $statuses_group2 = array( 'cancelled', 'refunded' );

            $change_stock = false;
            $order_note = array();

            ## 1. Restore Order stock (7 order status change types)
            if ( in_array( $old_status, $statuses_group1 ) && in_array( $new_status, $statuses_group2 ) ) {
                $change_stock = true;
                $change_type = 'increase';
                $change_text =  __( 'incremented', 'woocommerce' );
            }
            ## 2. Restore Order stock (4 order status change types)
            elseif ( $old_status == 'cancelled' && in_array( $new_status, $statuses_group1 ) ) {
                $change_stock = true;
                $change_type = 'decrease';
                $change_text =  __( 'decremented', 'woocommerce' );
            }
            ## 3. Other cases
            else return; // We exit

            if( $change_stock ){
                // Iterating through each order 'line_item'
                // Since WC 3, $item is a WC_Order_Item_Product object
                foreach ( $items as $item ) {
                    $product_id = $item->get_product_id(); // The product ID
                    if ( $product_id > 0 ) {
                         // Get tan instance of the WC_Product object
                        $product = $item->get_product();
                        if ( $product && $product->exists() && $product->managing_stock() ) {

                            // Get the product initial stock quantity (before update)
                            $initial_stock = $product->get_stock_quantity();

                            $item_qty = apply_filters( 'woocommerce_order_item_quantity', $item->get_quantity(), $this, $item );

                            // Update the product stock quantity
                            // Replace DEPRECATED methods: increase_stock() & discrease_stock()
                            wc_update_product_stock( $product, $item_qty, $change_type );

                            // Get the product updated stock quantity
                            $updated_stock = ( $change_type == 'increase' ) ? $initial_stock + $item_qty : $initial_stock - $item_qty;

                            do_action( 'woocommerce_auto_stock_restored', $product, $item );

                            // A unique Order note: Store each order note in an array…
                            $order_note[] = sprintf( __( 'Product ID #%s stock %s from %s to %s.', 'woocommerce' ), $product_id, $change_text, $initial_stock, $updated_stock);

                            // DEPRECATED & NO LONGER NEEDED - can be removed
                            //$order->send_stock_notifications( $product, $updated_stock, $item_qty );
                        }
                    }
                }
                // Adding a unique composite order note (for multiple items)
                $order_notes = count($order_note) > 1 ? implode(' | ', $order_note) : $order_note[0];
                $order->add_order_note( $order_notes );
            }
        }
    }
    $GLOBALS['wc_auto_stock_restore'] = new WC_Auto_Stock_Restore();
}

这应该放在插件 php 文件中 see this 与 WooCommerce 插件创建相关).


普通版(主题function.php文件):

## ---- for WooCommerce versions 3+ - Theme code version ---- ##

add_action( 'woocommerce_order_status_changed', 'adjust_order_stock', 10, 3 );
function adjust_order_stock( $order_id, $old_status, $new_status ) {
    $order = new WC_Order( $order_id );
    $items = $order->get_items();

    if ( ! get_option('woocommerce_manage_stock') == 'yes' && ! count( $items ) > 0 )
        return; // We exit

    // EXCEPTION for 'ipay88' payment method id, when Order status change from 'pending' to 'cancelled'
    if( $order->get_payment_method() == 'ipay88' && $old_status == 'pending' && $new_status == 'cancelled' )
        return; // We exit

    // We don't need from 'pending' to 'refunded' order status
    if( $old_status == 'pending' && $new_status == 'refunded' )
        return; // We exit

    // Group Order statuses in 2 groups (array)
    $statuses_group1 = array( 'processing', 'on-hold', 'pending', 'completed' );
    $statuses_group2 = array( 'cancelled', 'refunded' );

    $change_stock = false;
    $order_note = array();

    ## 1. Restore Order stock (7 order status change types)
    if ( in_array( $old_status, $statuses_group1 ) && in_array( $new_status, $statuses_group2 ) ) {
        $change_stock = true;
        $change_type = 'increase';
        $change_text =  __( 'incremented', 'woocommerce' );
    }
    ## 2. Restore Order stock (4 order status change types)
    elseif ( $old_status == 'cancelled' && in_array( $new_status, $statuses_group1 ) ) {
        $change_stock = true;
        $change_type = 'decrease';
        $change_text =  __( 'decremented', 'woocommerce' );
    }
    ## 3. Other cases
    else return; // We exit

    if( $change_stock ){
        // Iterating through each order 'line_item'
        // Since WC 3, $item is a WC_Order_Item_Product object
        foreach ( $items as $item ) {
            $product_id = $item->get_product_id(); // The product ID
            if ( $product_id > 0 ) {
                 // Get tan instance of the WC_Product object
                $product = $item->get_product();
                if ( $product && $product->exists() && $product->managing_stock() ) {

                    // Get the product initial stock quantity (before update)
                    $initial_stock = $product->get_stock_quantity();

                    $item_qty = apply_filters( 'woocommerce_order_item_quantity', $item->get_quantity(), $this, $item );

                    // Update the product stock quantity
                    // Replace DEPRECATED methods: increase_stock() & discrease_stock()
                    wc_update_product_stock( $product, $item_qty, $change_type );

                    // Get the product updated stock quantity
                    $updated_stock = ( $change_type == 'increase' ) ? $initial_stock + $item_qty : $initial_stock - $item_qty;

                    do_action( 'woocommerce_auto_stock_restored', $product, $item );

                    // A unique Order note: Store each order note in an array…
                    $order_note[] = sprintf( __( 'Product ID #%s stock %s from %s to %s.', 'woocommerce' ), $product_id, $change_text, $initial_stock, $updated_stock);

                    // DEPRECATED & NO LONGER NEEDED - can be removed
                    //$order->send_stock_notifications( $product, $updated_stock, $item_qty );
                }
            }
        }
        // Adding a unique composite order note (for multiple items)
        $order_notes = count($order_note) > 1 ? implode(' | ', $order_note) : $order_note[0];
        $order->add_order_note( $order_notes );
    }
}

此代码进入您的活动子主题(或主题)的 function.php 文件。

所有代码都经过测试,仅适用于 WooCommerce 版本 3+


Woocommerce 订单相关: