WooCommerce - how can I dynamically load checkout page using ajax?

12,759

Solution 1

On opening the modal window do a Ajax call to get checkout page content;

In back end use do " echo do_shortcode('[woocommerce_checkout]'); " to return checkout page content.

/* PHP Code on functions.php */
add_action( 'wp_ajax_getCheckoutPageContent', 'getCheckoutPageContentCallBack' );
add_action( 'wp_ajax_nopriv_getCheckoutPageContent', 'getCheckoutPageContentCallBack' );

function getCheckoutPageContentCallBack() {
    echo do_shortcode('[woocommerce_checkout]');
    die();
}

/* JS Code to be called on modal open callback*/
var wp_ajax_url="http://yourwebsite/wp-admin/admin-ajax.php";
var data = {
    action: 'getCheckoutPageContent'
};

jQuery.post( wp_ajax_url, data, function(content) {
    // show content on modal
});

Edit:

In my case I am showing checkout modal on addto cart and I have used bootstarp modal.

here is my code.

    /* PHP Code on functions.php */
    add_action( 'wp_ajax_getCheckoutPageContent', 'getCheckoutPageContentCallBack' );
    add_action( 'wp_ajax_nopriv_getCheckoutPageContent', 'getCheckoutPageContentCallBack' );

    function getCheckoutPageContentCallBack() {


        $product_id        = absint( $_POST['product_id'] );
        $quantity          = absint( $_POST['quantity'] );
        $product_status    = get_post_status( $product_id );
        $passed_validation = apply_filters( 'woocommerce_add_to_cart_validation', true, $product_id, $quantity );

        if ( $passed_validation && WC()->cart->add_to_cart( $product_id, $quantity ) && 'publish' === $product_status ) {

            do_action( 'woocommerce_ajax_added_to_cart', $product_id );
            global $woocommerce;
            $items = $woocommerce->cart->get_cart();

            wc_setcookie( 'woocommerce_items_in_cart', count( $items ) );
            wc_setcookie( 'woocommerce_cart_hash', md5( json_encode( $items ) ) );
            do_action( 'woocommerce_set_cart_cookies', true );

            define( 'WOOCOMMERCE_CHECKOUT', true );
            echo do_shortcode('[woocommerce_checkout]');


        } else {

            echo "Something went wrong, please try again later.";
        }

        die();
    }

    /* woocommerce shop page*/

    <?php 
    /*
        Template Name:costom shop
    */

    get_header();
    ?>
    <link rel="stylesheet" type="text/css" href="<?php echo get_template_directory_uri();?>/bootstrap/css/bootstrap.min.css">
    <script type="text/javascript" src="<?php echo get_template_directory_uri();?>/bootstrap/js/bootstrap.min.js"></script>

    <?php  
      $args = array(
            'post_type' => 'product',
            'posts_per_page' => -1,
            'orderby' => 'rand'
        );

        $the_query = new WP_Query( $args );

        if ( $the_query->have_posts() ) : while ( $the_query->have_posts() ) : $the_query->the_post(); ?>

        <div class="row">
            <div class="col-md-12">
                <h2><?php the_title() ?></h2>
                <div>
                    <div class="row">
                        <div class="col-md-6">
                            <?php the_post_thumbnail(); ?>
                        </div>
                        <div class="col-md-6">
                            <a href="#!" data-productid="<?php echo $post->ID; ?>" class="btn btn-primary" onclick="customCheckout(event)">Add to Cart</a>
                        </div>
                    </div>
                    <strong>Description</strong>
                    <div><?php the_excerpt(); ?></div>
                </div>
            </div>
        </div>

        <?php endwhile; else : ?>

        <p>There in no product :( </p>

    <?php endif;
    wp_reset_postdata(); ?>


    <!-- Checkout Modal -->
    <div class="modal fade" id="checkoutModal" tabindex="-1" role="dialog" aria-labelledby="checkoutModalLabel">
      <div class="modal-dialog" role="document">
        <div class="modal-content">
          <div class="modal-header">
            <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
            <h4 class="modal-title" id="checkoutModalLabel">Checkout</h4>
          </div>
          <div class="modal-body">
            <div id="checkOutPageContent">

            </div>
          </div>      
        </div>
      </div>
    </div>

    <script type="text/javascript">

        function customCheckout(event){
            var wp_ajax_url="<?php echo site_url();?>/wp-admin/admin-ajax.php";
            var data = {
                action: 'getCheckoutPageContent',
                product_id: jQuery(event.target).data('productid'),
                quantity: 1
            };

            jQuery.post( wp_ajax_url, data, function(content) {
                jQuery("#checkOutPageContent").html(content);
                jQuery("#checkoutModal").modal('show');

            });
        }

    </script>
    <?php
    get_footer();
    ?>

Solution 2

You would need to include the checkout.min.js javascript to ensure the AJAX callback works on the checkout page. You can manually embed it inside your AJAX loaded checkout page;

<?php echo plugins_url(); ?>/woocommerce/assets/js/frontend/checkout.min.js

Hope that helps

Share:
12,759
user2929594
Author by

user2929594

Updated on June 14, 2022

Comments

  • user2929594
    user2929594 almost 2 years

    I'd like to display checkout in the lightbox/modal window, so it would be quickly accessible from every shop page. Any ideas how to do this? The shop will be integrated witha paypal (maybe express) and Stripe plugin.

  • drake035
    drake035 over 8 years
    Thanks! Your code works however after the Ajax call executed I only get <div class="woocommerce"></div>, nothing else. In this case, do_shortcode('[woocommerce_checkout]') returns nothing but this. Any idea why?
  • James Jones
    James Jones over 8 years
    I find that's a common fallacy. It would cost more in developer time to write the equivalent robust code than to just buy the plugin
  • Swarnendu Paul
    Swarnendu Paul over 8 years
    You must add the product into cart before calling do_shortcode('[woocommerce_checkout]') , please make sure your cart has some product in it
  • drake035
    drake035 over 8 years
    Thanks a lot @Swarnendu. It mostly works except that the payment method section is lacking, would you know why?
  • Swarnendu Paul
    Swarnendu Paul over 8 years
    @drake035 I have updated my code; this should work; I have added define( 'WOOCOMMERCE_CHECKOUT', true ); before do_shortcode('[woocommerce_checkout]'); Please check once.
  • drake035
    drake035 over 8 years
    Thx @Swarnendu, works better but still not 100% :) Payment method is Stripe (via plugin "Stripe for WooCommerce"). Submitting form redirects to Checkout page with "Error: There was a problem connecting to the payment gateway" and checkout form below, submitting again from there works. If I switch to default WP theme and use regular checkout form, it also works directly which makes me think there's still something wrong/missing in this code. Any idea?
  • drake035
    drake035 over 8 years
    Additional clue: on default WP theme clicking "place order" button triggers Ajax functionality (with Ajax loader appearing) before redirecting to Order Received page. But with this custom code, no Ajax functionality seems to occur, the same Checkout page reloads with the error message I mentioned.
  • Swarnendu Paul
    Swarnendu Paul over 8 years
    @drake035 I use paypal and COD for testing, it worked, didn't tried stripe, will try and fix if got any bug.
  • drake035
    drake035 over 8 years
    Just tried with another Stripe plugin ("Striper"), but same result: when clicking "place order" from Ajax-loaded checkout form I get an error message (in this case "Must provide source or customer. Transaction Error: Could not complete your payment"). Then, from the Checkout page, "place order" now works. From what I can see, the normal behaviour with WC is that "place order" triggers some necessary Ajax stuff. But this fails to happen when the checkout form provided by [woocommerce_checkout] shortcode :/
  • Swarnendu Paul
    Swarnendu Paul over 8 years
    @drake035 for stripe use "Stripe for WooCommerce" plugin. It works fine, you must supply api key credentials in admin panel. evernote.com/shard/s479/sh/5d9a6310-e1fb-44e7-8f20-5aedd2552‌​f80/…
  • drake035
    drake035 over 8 years
    Thx Swarnendu, but I think the problem isn't related to the Stripe plugin. Rather there is some native WooCommerce Ajax stuff that is missing in this code. Clicking "place order" should trigger this native Ajax functionality, but it's not triggered here and that's why the payment process fails no matter which gateway plugin is used (I tried 3 separate Stripe plugins)... Somehow they managed to solve this problem in wordimpress.com/plugins/woocommerce-quick-checkout. But I'm not advanced enough to find out how. I guess I'll have to convince the client to buy this plugin. Thanks anyway!
  • Swarnendu Paul
    Swarnendu Paul over 8 years
    @drake035 Thanks for pointing this issue. It looks I need to dig further.
  • drake035
    drake035 over 8 years
  • DarkNeuron
    DarkNeuron over 7 years
    Sorry but linking a plugin is the worst answer one can give.
  • James Jones
    James Jones over 7 years
    @DarkNeuron where's your brilliant answer then?
  • DarkNeuron
    DarkNeuron over 7 years
    I could ask you the same.
  • dafyddPrys
    dafyddPrys about 7 years
    If anyone is still interested, I had to work a little harder to get my wp_verify_nonce function to succeed. In the scope of the above function, I needed to set the customer again to get the generated nonce to be valid. I passed the user ID in with the POST and then set it with wp_set_current_user($data['user_id']). I am using a paypal gateway on my setup.
  • buzibuzi
    buzibuzi almost 3 years
    this code works for me fine when im logged-in. using it as a guest user, i dont get the payment methods displayed. instead getting the error "No available payment methods for your state". any idea why ?