Alles was du über den Bestellstatus in WooCommerce wissen musst

In diesem Artikel erklären wir alles Wissenswerte über den Bestellstatus in WooCommerce.

von

Ein Bestandteil von WooCommerce der gerne vernachlässigt wird, ist der Bestellstatus. Dabei basieren viele wichtige (Automatisierungs-) Prozesse auf dem Status einer Bestellung.

Wie funktioniert der Bestellstatus

Gibt dein Kunde eine neue Bestellung auf, erhält die Bestellung einen bestimmten Status. Dieser Bestellstatus hängt im Normalfall von der gewählten Zahlungsmethode ab. Folgende Bestellstatus existieren standardmäßig in WooCommerce:

  • Zahlung ausstehend: pending
  • In Bearbeitung: processing
  • In Wartestellung: on-hold
  • Fertiggestellt: completed
  • Storniert: cancelled
  • Rückerstattet: refunded
  • Fehlgeschlagen: failed

Zahlungsmethoden wie PayPal, die eine automatische Zahlung (z.B. via API) anbieten, vergeben im Normalfall den Status pending. Dieser Status impliziert, dass die Bestellung “bezahlbar” ist. Anders verhält es sich bei einer manuellen Zahlungsmethode wie z.B. Banküberweisung. In diesem Fall wird der Status on-hold vergeben. Dieser Status deutet zwar auch daraufhin, dass noch keine Zahlung erfolgte – trotzdem wird ein anderer Status als bei automatischen Zahlungsmethoden verwendet. Das liegt u.a. daran, dass per Standard Bestellungen des Status pending über den “Bestellung bezahlen” Endpunkt abrufbar sind, d.h. das der Kunde über einen Link die Bestellung bezahlen bzw. die Zahlungsart wechseln kann.

Standardstatus anpassen

Wie bereits erwähnt ist der Standardstatus nach der Bestellaufgabe abhängig von der gewählten Zahlungsmethode. In manchen Fällen ist es jedoch sinnvoll den Standardstatus anzupassen bzw. zu manipulieren. Das ist eine recht einfache Aufgabe die per Snippet in der functions.php erledigt werden kann. Natürlich gibt es dafür vermutlich auch ein Plugin – grundsätzlich empfehle ich aber die WP-Installation so “schlank” wie möglich zu halten und Plugins nur zu installieren, wenn es notwendig ist. Das nachfolgende Beispiel ändert den Standardstatus auf on-hold.

function vd_adjust_default_order_status( $status ) {
     return 'on-hold';
}
add_filter( 'woocommerce_default_order_status', 'vd_adjust_default_order_status', 10, 1 );

Bestellung bezahlen

Schaut man sich die Methode needs_payment in der Klasse WC_Order an, gibt diese Methode die Status pending und failed zurück. Das bedeutet, dass letzten Endes nur diese beiden Status als “bezahlbar” interpretiert werden und auch nur diese Status über den Bestellung bezahlen Endpunkt bezahlt werden können. Insofern du in deinem Setup weitere Status über den Bestellung bezahlen Endpunkt bezahlen lassen möchtest (oder deinem Kunden die Möglichkeit geben willst, für einen anderen Status die Zahlungsmethode nachträglich wechseln zu können), kannst du per Filter in der functions.php weitere Status hinzufügen:

function vd_add_need_payment_statuses( $statuses ) {
     $statuses[] = 'on-hold';
     return $statuses;
}
add_filter( 'woocommerce_valid_order_statuses_for_payment', 'vd_add_need_payment_statuses', 10, 1 );
add_filter( 'woocommerce_order_is_pending_statuses', 'vd_add_need_payment_statuses', 10, 1 );

Bestellung als bezahlt markieren

WooCommerce entscheidet auf Basis des Bestellstatus ob eine Bestellung als bezahlt gilt oder nicht. Standardmäßig sind folgende Status ein Indikator für eine bezahlte Bestellung:

  • In Bearbeitung
  • Fertiggestellt

Erreicht die Bestellung einen dieser Status, gilt sie als bezahlt. Das wird über die Funktion wc_get_is_paid_statuses bestimmt, die wiederum auch per Filter erweitert werden kann um weitere Bestellstatus hinzufügen.

function vd_add_is_paid_status( $statuses ) {
     $statuses[] = 'my-custom-status';
     return $statuses;
}
add_filter( 'woocommerce_order_is_paid_statuses', 'vd_add_is_paid_status', 10, 1 );

Natürlich lässt sich auch via Filter für eine konkrete Bestellung entscheiden, ob sie als bezahlt gelten soll oder nicht.

function vd_add_order_is_paid( $is_paid, $order ) {
     if ( $order->has_status( 'on-hold' ) ) {
         $is_paid = true;
     }
     return $is_paid;
}
add_filter( 'woocommerce_order_is_paid', 'vd_add_order_is_paid', 10, 2 );

Statuswechsel

Ein wichtiger Bestandteil von vielen Plugins, die auf WooCommerce aufbauen sind Hooks, die ausgeführt werden, sobald der Bestellstatus einer Bestellung wechselt. Ein Beispiel sind Bestellbenachrichtigungen: Sobald du in der Bestellverwaltung die Bestellung als fertiggestellt markierst, erhält dein Kunde die “Bestellung fertiggestellt” E-Mail zugestellt.

Besonders lohnenswert ist es sich dafür die Methode status_transition in WC_Order anzusehen. Wenn der Status einer Bestellung wechselt und die Bestellung gespeichert wird, wird diese Methode ausgeführt. Zuerst wird der Hook woocommerce_order_status_{new_status} ausgeführt. Wobei der Platzhalter {new_status} mit dem neuen Status zu ersetzen ist, z.B. completed insofern die Bestellung als fertiggestellt markiert wurde. Anschließend werden weitere Hooks ausgeführt – zum Einen der allg. Hook woocommerce_order_status_changed und zum Anderen der spezifische Hook woocommerce_order_status_{old_status}_{new_status}. Letzterer kann verwendet werden um spezifische Aufgaben zu erledigen, die nur bei einem konkreten Statuswechseln von → zu ausgeführt werden sollen.

Auch Germanized nutzt die Statuswechsel-Hooks zum gewisse Aufgaben zu erledigen. Zum Beispiel nutzen wir die Statuswechsel um unsere Rechnungen automatisiert zu erzeugen. Insofern du also konfiguriert hast, dass die Rechnung zu einem bestimmten Status erzeugt werden soll, gehen wir also folgendermaßen vor:

function vd_generate_invoice( $order_id, $order ) {
    $invoices = wc_gzdp_get_invoices_by_order( $order, 'simple' );
    if ( empty( $invoices ) ) {
        // Create a new invoice
    }
}
add_action( 'woocommerce_order_status_completed', 'vd_generate_invoice', 10, 2 );

Natürlich bieten sich die Hooks auch für viele andere Aufgabenbereiche an: Übertragung an die Warenwirtschaft, an Bewertungsdienstleister z.B. eKomi oder aber an Versanddienstleister wie DHL.

Status nach erfolgreicher Zahlung

Der Status nach Eingang einer Zahlung ist von besonderer Interesse: Auch wir auf vendidero.de passen diesen Status an, um weitere Prozesse auszulösen (z.B. Buchhaltung, Lizenzverwaltung, E-Mails). Interessant ist hierfür die Methode payment_complete ebenfalls in der Klasse WC_Order. Zahlungsmethoden rufen diese Methode auf, sobald die Zahlung erfolgreich verbucht werden konnte (z.B. bei erfolgreicher Zahlung via PayPal). Auch hier werden wieder nützliche Hooks ausgeführt, die es uns erlauben auf den Bestellstatus zuzugreifen und diesen anzupassen.

Per Default wird der Status nach der Bezahlung entweder auf processing oder completed gesetzt. Das hängt davon ab, ob die Bestellung nach Auffassung von WooCommerce noch einer weiteren Bearbeitung bedarf oder nicht. WooCommerce untersucht dafür, ob in der Bestellung nur virtuelle und herunterladbare Produkte enthalten sind. Insofern das nicht der Fall ist, verwendet WooCommerce den Status processing. Auf vendidero.de verwenden wir allerdings eine eigene, ausgeklügeltere Download-Architektur als WooCommerce, d.h. unsere Produkte sind nicht als herunterladbar bzw. virtuell markiert. Deshalb passen wir diesen Status einfach per Filter an:

function vd_adjust_order_paid_status( $status, $order_id, $order ) {
     return 'completed';
}
add_filter( 'woocommerce_payment_complete_order_status', 'vd_adjust_order_paid_status', 10, 3 );

Damit wird jede Bestellung nach erfolgreicher Zahlung automatisch auf completed bzw. fertiggestellt gesetzt. Anschließend greifen natürlich wieder die Hooks zum Statuswechsel, sodass nachfolgende Prozesse greifen können.

Bestellstatus hinzufügen

Aufgrund der guten Struktur in WooCommerce kannst du neue Bestellstatus einfach hinzufügen. Dein neuer Status ist dann einfach in WooCommerce integriert und kann sofort genutzt werden.

function vd_add_order_status( $statuses ) {
    $statuses['wc-my-custom-status'] = __( 'My Custom Status', 'text-domain' );
    return $statuses;
}
add_filter( 'wc_order_statuses', 'vd_add_order_status', 10, 1 );

Zusätzlich müsstet ihr aber den Status auch noch als post_status registrieren, da der Status sonst nicht von WordPress erkannt werden würde – auch hierfür stellt WooCommerce einen Hook zur Verfügung (der allerdings noch vor dem init-Hook ausgeführt werden muss).

function vd_register_order_post_status( $statuses ) {
    $statuses['wc-my-custom-status'] = array(
        'label'                     => _x( 'My Custom Status', 'Order status', 'text-domain' ),
        'public'                    => false,
        'exclude_from_search'       => false,
        'show_in_admin_all_list'    => true,
        'show_in_admin_status_list' => true,
        'label_count'               => _n_noop( 'Custom Desc <span class="count">(%s)</span>', 'Custom Desc <span class="count">(%s)</span>', 'text-domain' ),
   );
}
add_filter( 'woocommerce_register_shop_order_post_statuses', 'vd_register_order_post_status', 10, 1 );

Für diesen Artikel habe ich folgendes Setup verwendet:

  • WordPress 5.2
  • WooCommerce 3.7
  • PHP 7.3