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:

Webseiten für Kultur und Wirtschaft | 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)

Schreibe einen Kommentar

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