Home / eCommerce / Auto Complete Virtual Orders – Not EFT
Duplicate Snippet

Embed Snippet on Your Site

Auto Complete Virtual Orders – Not EFT

Auto complete virtual orders that are virtual but NOT downloadable, excluding EFT orders

Code Preview
php
<?php
/**
 * Auto-complete orders that contain ONLY virtual items,
 * but ONLY after payment is confirmed.
 * EXCLUDES EFT / Direct Bank Transfer (bacs).
 */
add_action( "woocommerce_payment_complete", "vg_autocomplete_virtual_orders_after_payment", 20 );
function vg_autocomplete_virtual_orders_after_payment( $order_id ) {
    if ( ! $order_id ) {
        return;
    }
    $order = wc_get_order( $order_id );
    if ( ! $order ) {
        return;
    }
    // Exclude offline methods (especially EFT/BACS)
    $excluded_methods = array( "bacs", "cod", "cheque" );
    if ( in_array( $order->get_payment_method(), $excluded_methods, true ) ) {
        return;
    }
    // Extra safety: only proceed if WooCommerce considers it paid
    if ( ! $order->is_paid() ) {
        return;
    }
    // Only complete from sensible states
    if ( ! $order->has_status( array( "processing", "on-hold" ) ) ) {
        return;
    }
    // If it's already completed, don't touch it again
    if ( $order->has_status( "completed" ) ) {
        return;
    }
    // If ANY item is not virtual (or product cannot be read), do not autocomplete
    foreach ( $order->get_items() as $item ) {
        $product = $item->get_product();
        if ( ! $product || ! $product->is_virtual() ) {
            return;
        }
    }
    // All virtual + paid -> complete it
    $order->update_status(
        "completed",
        "System: Auto-completed (all items virtual + payment confirmed)."
    );
}
/**
 * Safety net: Force BACS (EFT) orders back to On Hold if anything tries to complete them.
 */
add_action( "woocommerce_thankyou", function( $order_id ) {
    if ( ! $order_id ) return;
    $order = wc_get_order( $order_id );
    if ( ! $order ) return;
    if ( "bacs" === $order->get_payment_method() && $order->has_status( array( "processing", "completed" ) ) ) {
        $order->update_status( "on-hold", "System: Forced On Hold for EFT verification." );
    }
}, 50 );

Comments

Add a Comment