WooCommerce AJAX cross domain add to cart

Posted: asked May 18 at 20:06 - Source : stackoverflow

I'm having trouble adding to cart from a different domain.
I have enabled CORS header, and ajax is working properly, but subsequent ajax queries for the cart state result in empty response.
I guess it has to be something related to cookies/session bu not sure what (haven't peeked much into WC internals and my head is spinning this last few days I do, so I would appreciate expert advice)

This is what I have in PHP:

add_action( 'wp_ajax_a3_add_to_cart', 'a3_add_to_cart' );
add_action( 'wp_ajax_nopriv_a3_add_to_cart', 'a3_add_to_cart' );

function a3_add_to_cart(){
    header('Content-Type: application/json');

    $product_id = $_REQUEST['product_id'];
    $variation_id = $_REQUEST['variation_id'];
    $quantity = $_REQUEST['quantity'];
    $variation = $_REQUEST['variation'];    

    try{
        WC()->cart->add_to_cart($product_id, $quantity, $variation_id, $variation);
        do_action( 'woocommerce_set_cart_cookies', TRUE );
        do_action( 'woocommerce_ajax_added_to_cart', $product_id );
        $context = a3_get_cart_data();
        exit(json_encode(array('status' => 'ok', 'message'=> 'Added product to cart', 'data' => $context )));
    }    
    catch(Exception $exc){
        exit(json_encode(array('status' => 'error', 'message'=> $exc->message)));
    }
}

add_action( 'wp_ajax_a3_get_cart', 'a3_get_cart' );
add_action( 'wp_ajax_nopriv_a3_get_cart', 'a3_get_cart' );

function a3_get_cart(){    
    header('Content-Type: application/json');

    $context = a3_get_cart_data();

    exit(json_encode($context));
}

function a3_get_cart_data(){
    $cart_items = [];

    WC()->cart->calculate_totals();

    foreach ( WC()->cart->get_cart() as $cart_item_key => $cart_item ) {
        $item = [];

        $_product   = apply_filters( 'woocommerce_cart_item_product', $cart_item['data'], $cart_item, $cart_item_key );
        $product_id = apply_filters( 'woocommerce_cart_item_product_id', $cart_item['product_id'], $cart_item, $cart_item_key );

        //var_dump($cart_item['data']);

        if ( $_product && $_product->exists() && $cart_item['quantity'] > 0 && apply_filters( 'woocommerce_cart_item_visible', true, $cart_item, $cart_item_key ) ) {
            $item['product_permalink'] = apply_filters( 'woocommerce_cart_item_permalink', $_product->is_visible() ? $_product->get_permalink( $cart_item ) : '', $cart_item, $cart_item_key );
            $item['product_classes'] = "woocommerce-cart-form__cart-item " . esc_attr( apply_filters( 'woocommerce_cart_item_class', 'cart_item', $cart_item, $cart_item_key ) );
            $item['product_remove_link'] = apply_filters( 'woocommerce_cart_item_remove_link', sprintf(
                            '<a href="%s" class="remove" aria-label="%s" data-product_id="%s" data-product_sku="%s">&times;</a>',
                            esc_url( WC()->cart->get_remove_url( $cart_item_key ) ),
                            __( 'Remove this item', 'woocommerce' ),
                            esc_attr( $product_id ),
                            esc_attr( $_product->get_sku() )
                        ), $cart_item_key );
            $item['product_image'] = new TimberImage($_product->get_image_id());
            $item['product_name'] = apply_filters( 'woocommerce_cart_item_name', $_product->get_name(), $cart_item, $cart_item_key ) . '&nbsp;';
            $item['product_sku'] = $_product->get_sku();
            $item['product_stock'] = $_product->get_stock_quantity() > 0 ? 'In stock' : 'Out of stock';
            $item['item_data'] =  WC()->cart->get_item_data( $cart_item );
            $item['back_order_notification'] = "";
            // Backorder notification
            if ( $_product->backorders_require_notification() && $_product->is_on_backorder( $cart_item['quantity'] ) ) {
                $item['back_order_notification'] = '<p class="backorder_notification">' . esc_html__( 'Available on backorder', 'woocommerce' ) . '</p>';
            }

            //var_dump(WC()->cart->get_item_data( $cart_item ));
            //exit();

            $item['product_price'] = apply_filters( 'woocommerce_cart_item_price', WC()->cart->get_product_price( $_product ), $cart_item, $cart_item_key );

            if ( $_product->is_sold_individually() ) {
                $item['product_quantity'] = sprintf( '1 <input type="hidden" name="cart[%s][qty]" value="1" />', $cart_item_key );
            } else {
                $item['product_quantity'] = woocommerce_quantity_input( array(
                    'input_name'  => "cart[{$cart_item_key}][qty]",
                    'input_value' => $cart_item['quantity'],
                    'max_value'   => $_product->backorders_allowed() ? '' : $_product->get_stock_quantity(),
                    'min_value'   => '0',
                ), $_product, false );
            }

            $item['product_quantity'] = apply_filters( 'woocommerce_cart_item_quantity', $item['product_quantity'], $cart_item_key, $cart_item );

            $item['subtotal'] = apply_filters( 'woocommerce_cart_item_subtotal', WC()->cart->get_product_subtotal( $_product, $cart_item['quantity'] ), $cart_item, $cart_item_key );

            $cart_items[] = $item;      
        }
    }

    $context['cart_items'] = $cart_items;

    return $context;
}


And in JS:

$( document ).on( 'click', '.btn-cart', function() { 

var site = bio_js.siteSettings;

var prod_id = $('[name="product_id"]').val();//store product id in post id variable
var variation_id = $('[name="variation_id"]').val();//store product id in post id variable
var qty = $('#qty1').val();//store quantity in qty variable
var data = {
    action : 'a3_add_to_cart', 
    product_id : prod_id,
    variation_id : variation_id,
    quantity : qty,                    
};
var variation = {};

$('[data-attribute_name]').each(function(){
    variation['attribute_' + $(this).data('attribute_name')] = $(this).val();
});

data.variation = variation;

$.ajax({
    url : site.ajax_url, 
    type : 'post', 
    data : data ,
    success : function(resp){                                
        console.log(resp);

        $.post('/cart', {cart:resp.data}, function(resp){
            console.log(resp);
            $.get(site.ajax_url, {action:'a3_get_cart'}, function(resp1){
            console.log(resp1);
            });
        });
    }

});

return false;
});