Woocommerce Mini Cart: Gutschein via AJAX hinzufügen

In einem Shop-Projekt haben wir aus UX-Design-Gründen die beiden Seiten Warenkorb und Kasse auf einer zusammengefasst, so dass der Zahlungsprozess möglichst kurz gehalten werden kann. Auf der neuen Check-Out-Page kommt als Warenkorb die Woocommerce Mini-Cart zum Einsatz, da diese sowieso schon eingebaut war. Da diese Mini-Cart ihren Inhalt per AJAX empfängt, haben wir nun auch die Gutschein-Funktionalität per AJAX der Mini-Cart hinzugefügt.

1. Gutschein einlösen auf der Checkout-Seite

Zuerst fügen wir das Gutscheinformular an die gewünschte Stelle in der Checkout-Seite. Anstatt die Formularfelder für den Gutscheincode auf der Checkout-Seite direkt anzuzeigen, soll nur ein Hinweis mit Link erscheinen. Dafür kann die jQuery UI Dialog-Bibliothek von WordPress verwendet werden.

function ud_show_coupon_js() {

    wc_enqueue_js('$("a.showcoupon").parent().hide();');

    wc_enqueue_js('dialog = $("form.checkout_coupon").dialog({
        autoOpen: false,
        width: 381,
        minHeight: 0,
        modal: false,
        appendTo: "#coupon-anchor",
        position: { my: "left", at: "left", of: "#coupon-anchor"},
            draggable: false,
            resizable: false,
            dialogClass: "coupon-special",
            buttons: {}
    });');

    wc_enqueue_js('$("#show-coupon-form").click( function() {
        if (dialog.dialog("isOpen")) {
            $(".checkout_coupon").hide();
            dialog.dialog( "close" );
        } else {
            $(".checkout_coupon").show();
            dialog.dialog( "open" );
        } // endif
        return false;
    });');

    // apply coupon code via AJAX
    wc_enqueue_js('$(".woocommerce-form-coupon .button").on("click", function() {
        if( $( ".woocommerce-form-coupon #coupon_code").val() ) {
            var coupon = $( ".woocommerce-form-coupon #coupon_code").val();
            data = {
                action: "apply_coupon_code",
                coupon_code: coupon,
                security: "' . wp_create_nonce("ajax_nonce") . '",
                do_what: "apply"
            };
            $.ajax({
                type: "POST",
                url: wc_add_to_cart_params.ajax_url,
                dataType: "html",
                data: data,
                success: function (response) {
                    $(".cart_list.product_list_widget").html(response);
                },
                error: function (errorThrown) {
                    $(".cart_list.product_list_widget").html(errorThrown);
                }
            });
        } // endif
    });');

    // remove coupon code via AJAX
    wc_enqueue_js('$( ".woocommerce-checkout" ).on( "click", ".remove-coupon", function(event) {
        event.preventDefault();
        var coupon = $(this).attr("data-coupon");
        data = {
            action: "apply_coupon_code",
            coupon_code: coupon,
            security: "' . wp_create_nonce("ajax_nonce") . '",
            do_what: "remove"
        };
        $.ajax({
            type: "POST",
            url: wc_add_to_cart_params.ajax_url,
            dataType: "html",
            data: data,
            success: function (response) {
                $(".cart_list.product_list_widget").html(response);
            },
            error: function (errorThrown) {
                $(".cart_list.product_list_widget").html(errorThrown);
            }
        });
    });');

}
add_action('woocommerce_before_checkout_form', 'ud_show_coupon_js');

Falls die UI-Dialog-Bibliothek fehlen sollte, dann kann diese über die functions.php eingebunden werden:

function ud_scripts() {
    wp_enqueue_script('jquery-ui-dialog');
}
add_action('wp_enqueue_scripts', 'ud_scripts');

Ausführlich ist das Hinzufügen des Gutscheinformulars im Artikel «How To Move WooCommerce Coupon Field in Checkout Page» von Owais Alam beschrieben.

Der Hinweis mit Gutscheincode-Link fügen wird per Hook woocommerce_checkout_after_customer_details ein. Soll der Link an einer anderen Stelle erscheinen, dann ist einfach ein anderer Hook oder Filter zu verwenden:

function ud_show_coupon() {
    global $woocommerce;

    if ($woocommerce->cart->needs_payment()) {
        echo '<div class="gutschein">Sie haben einen Gutschein? <a href="#" id="show-coupon-form">Gutscheincode eingeben</a>.</div><div id="coupon-anchor"></div>';
    }
}
add_action('woocommerce_checkout_after_customer_details', 'ud_show_coupon');

Das Eingabefeld für den Gutscheincode wird dabei erst nach angeklicktem Link «Gutscheincode eingeben» angezeigt:

Webshop | Webdesign | Schwyz | Zug | Luzern | Altdorf | ulrich.digital

2. Gutschein via AJAX hinzufügen

Das war der Teil um die Eingabe des Gutscheincodes auf der Checkout-Seite per UI Dialog zu implementieren. Im nächsten Schritt soll der Gutscheincode angewandt, sowie das Total erneut berechnet werden, ohne dass die ganze Checkout-Seite geladen werden muss. Dazu holen wir per jQuery den Gutscheincode vom Eingabefeld und übergeben diesen via AJAX an WordPress. War der Aufruf erfolgreich, wird die Mini-Cart mit eingelöstem Gutschein zurückgegeben:

$(".woocommerce-form-coupon .button").on("click", function() {
    if( $( ".woocommerce-form-coupon #coupon_code").val() ) {
        var coupon = $( ".woocommerce-form-coupon #coupon_code").val();
        data = {
            action: "apply_coupon_code",
            coupon_code: coupon,
            security: "<?php wp_create_nonce('ajax_nonce'); ?>",
            do_what: "apply"
        };
        $.ajax({
            type: "POST",
            url: wc_add_to_cart_params.ajax_url,
            dataType: "html",
            data: data,
            success: function (response) {
                $(".cart_list.product_list_widget").html(response);
            },
            error: function (errorThrown) {
                $(".cart_list.product_list_widget").html(errorThrown);
            }
        });
    } // endif
});

2.1 Gutschein via AJAX entfernen

Der Gutschein soll per AJAX wieder entfernt werden können. Dafür hängen wir dem «Gutschein entfernen»-Link mit der Klasse .remove-coupon per Event-Handler eine AJAX-Funktion an:

$( ".woocommerce-checkout" ).on( "click", ".remove-coupon", function(event) {
    event.preventDefault();
    var coupon = $(this).attr("data-coupon");
    data = {
        action: "apply_coupon_code",
        coupon_code: coupon,
        security: "<?php wp_create_nonce('ajax_nonce'); ?>",
        do_what: "remove"
    };
    $.ajax({
        type: "POST",
        url: wc_add_to_cart_params.ajax_url,
        dataType: "html",
        data: data,
        success: function (response) {
            $(".cart_list.product_list_widget").html(response);
        },
        error: function (errorThrown) {
            $(".cart_list.product_list_widget").html(errorThrown);
        }
    });
});

Auf Seite WordPress wird der Gutscheincode mit WC()->cart->apply_coupon($coupon_code); hinzugefügt und mit WC()->cart->remove_coupon($coupon_code); entfernt. Dafür ist die Abfrage des Werts von do_what verantwortlich. Das Total soll neu gerechnet und die Mini-Cart mit woocommerce_mini_cart(); ausgegeben werden. Dafür sind die Hooks wp_ajax_apply_coupon_code und wp_ajax_nopriv_apply_coupon_code zuständig:

function ud_apply_coupon_code() {
    if ( ! wp_verify_nonce($_POST['security'], 'ajax_nonce') ) {
        wp_die();
    } // endif
    $do_what =  $_POST['do_what'];
    $coupon_code = isset( $_POST['coupon_code'] ) ? $_POST['coupon_code'] : '';
    if ( $do_what == 'apply' ) {
        WC()->cart->apply_coupon( $coupon_code );
    } elseif ( $do_what == 'remove' ) {
        WC()->cart->remove_coupon( $coupon_code );
    } // endif
    WC()->cart->calculate_totals();
    woocommerce_mini_cart();
    wp_die();
}
add_action( 'wp_ajax_apply_coupon_code', 'ud_apply_coupon_code' );
add_action( 'wp_ajax_nopriv_apply_coupon_code', 'ud_apply_coupon_code' );

Als nächstes muss noch das Template mini-cart.php entsprechend angepasst werden. Um die Änderungen beim nächsten WooCommerce Update nicht zu verlieren, ist vor der Anpassung die Template-Datei erst in das entsprechende Verzeichnis /themes/child-theme/woocommerce/cart/ zu kopieren.

Beim gemachten Beispiel soll der «remove Coupon»-Link am gleichen Ort wie bei den Produkten erscheinen:

Webauftritt für Kultur und Wirtschaft | Webdesign | Schwyz | Zug | Luzern | Altdorf | ulrich.digital

Dem Mini-Cart Template fügen wir deshalb ein weiteres Listenelement mit Ausgabe der einzulösenden Gutscheine hinzu. Für den AJAX-Request ist die Klasse «remove-coupon» und das Attribut «data-coupon» des Links ausschlaggebend:

<li class="mini_cart total"><span>Total</span><span><?php echo $subtotal; ?></span></li>
    <?php
    // START Gutscheine ausgeben
    foreach ( WC()->cart->get_coupons() as $code => $coupon ) : ?>
        <li class="checkout coupon">
            <span><a href="<?php echo esc_url( wc_get_checkout_url() ); ?>?remove_coupon=<?php echo esc_attr( sanitize_title( $code ) ); ?>" data-coupon="<?php echo esc_attr( sanitize_title( $code ) ); ?>" class="remove-coupon"><i class="far fa-plus-circle"></i></a>Gutschein: <?php echo esc_attr( sanitize_title( $code ) ); ?></span>
            <span><?php wc_cart_totals_coupon_html( $coupon ); ?></span>
        </li>
        <?php
    endforeach; 
    // END Gutscheine ausgeben ?>
<li class="checkout total"><span>Total</span><span>CHF <?php echo $betrag; ?></span></li>
<li class="checkout taxes"><span> </span><span><?php echo $mwst_eintrag; ?></span></li>

Da wir den Entfernen-Link an einer anderen Position ausgeben, entfernen wir die Default-Ausgabe des Links per Filter woocommerce_cart_totals_coupon_html:

function ud_filter_woocommerce_cart_totals_coupon_html( $coupon_html, $coupon, $discount_amount_html ) {
    // entferne den remove-Link, da dieser im Template mini-cart.php hinzugefügt
    $coupon_html = $discount_amount_html;
    return $coupon_html;
}
add_filter( 'woocommerce_cart_totals_coupon_html', 'ud_filter_woocommerce_cart_totals_coupon_html', 10, 3 );

1 Star2 Stars3 Stars4 Stars5 Stars (1)

Wir brauchen dein Feedback, um uns zu verbessern. Ob du uns jetzt für geniale Webgurus hältst oder für das Gegenteil, lass es uns wissen!

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert