AppBridge SDK Bug: Cart object fails to interact with cart in embedded POS application

Solved
Highlighted
New Member
16 0 0

I am developing an embedded Shopify POS application. On server we use nodejs+expres and on client-side we use pure Javascript (not React). Our server side code is pretty much based on the following tutorial and it seems to work well as far authorization and retrieving access token is concerned

 https://help.shopify.com/en/api/tutorials/build-a-shopify-app-with-node-and-express#step-4-start-bui...

 

 

1.  For App Setup, we enable "Shopify POS extension"Screen Shot 2019-09-07 at 8.41.19 AM.pngEnabling "Shopify POS" for the app

 

 

2. Under "Manage embedded app", we have enabled the app

 

Screen Shot 2019-09-07 at 8.40.12 AM.png

3.The embedded app is configured to show up within a Modal on the cart page

Screen Shot 2019-09-07 at 8.49.09 AM.png

 

4. The app then shows up in the POS system. 

 

IMG_4607 2.JPG

 

5. The app authenticates and authorizes successfully using the code below

// https://MyapiURL/authentication
router.get('/', function (req, res) { const shop = req.query.shop; if (shop) { const state = nonce(); const redirectUri = process.env.FORWARDING_ADDRESS + '/shopify/authorization/callback'; const installUrl = 'https://' + shop + '/admin/oauth/authorize?' + 'client_id=' + process.env.SHOPIFY_API_KEY + '&scope=' + "write_products, read_locations, write_orders, write_draft_orders, read_orders" + '&redirect_uri=' + redirectUri; res.redirect(installUrl); } else { return res.status(400).send('Missing shop parameter. Please add ?shop=your-development-shop.myshopify.com to your request'); } })

6. Post authentication we retrieve store information using a access token just for verification purposes

 

IMG_4608.JPG

 

7. Now coming to the Cart page.. our application shows up as "Sample App"

 

IMG_4609.JPG

 

8 . When the user clicks on the "Sample App" .. we render the following html page (this is a jade template which gets transformed into html on server-side before being sent to the browser) 

 

//show_donation_page.pug

doctype html
html(lang="en")
    head
        link(rel='stylesheet', href='/styles/style.css', type='text/css')
        script(src='/scripts/jquery-3-4-1.js', type='text/javascript') 
        script(src='https://unpkg.com/@shopify/app-bridge@1.6.8/umd/index.development.js', type='text/javascript')
        script.
          var apiKey =  '!{apiKey}';
          var shopOrigin = '!{shopOrigin}';
    body
        div(id="container1")
        div(id="container2")
        div(id="container-error")
        script(src='/scripts/process_cart.js', type='text/javascript')
//process_cart.js
const AppBridge = window['app-bridge'];
const actions = window['app-bridge'].actions;
const createApp = AppBridge.createApp;
const Cart = actions.Cart;
const Toast = actions.Toast;

// apiKey and shopOrigin variables are populated on server-side
const app = createApp({
  apiKey: apiKey,
  shopOrigin: shopOrigin
});
var cart;

app.featuresAvailable(actions.Group.Cart).then(function (state) {
  var _ref = state.Cart && state.Cart[Cart.Action.FETCH],
  Dispatch = _ref.Dispatch;

// Let's check value of Dispatch $("#container1").html(JSON.stringify(Dispatch);
// container1 on our page displays "true" if (Dispatch) {
// we enter this code block //--> GOOD NEWS!! WE DO GET TO THIS POINT cart = Cart.create(app);
// I VERIFIED THAT THE 'cart' object gets created by alert(JSON.stringify(cart)) // Attemp 1: Let's try and read the items in the cart cart.subscribe(Cart.Action.FETCH, function (payload) { // THIS CALLBACK NEVER FIRES $("#container2").html(JSON.stringify(payload)); });
cart.dispatch(Cart.Action.FETCH); // Attempt 2: Let's try and add an item var lineItemPayload = { price: '20', quantity: 1, title: 'Bab Low - Blue Jay // White Soles', };
// FAIL: ITEM DOES NOT GET ADDED --> NO ERROR MESSAGE REPORTED cart.dispatch( Cart.addLineItem(lineItemPayload), ); } else { // THE TOAST MESSAGE DOES NOT FIRE SINCE DISPATCH EVALUATES TO TRUE var toastOptions = { message: 'Cart is not available', duration: 5000, isError: true }; var toastError = Toast.create(app, toastOptions); toastError.dispatch(Toast.Action.SHOW); } }); app.error(function (data) { // THIS CALLBACK DOES NOT FIRE. NO ERRORS REPORTED HERE $("#container-error").html(data.toString()); });

As you can see from the code above, we try to use the cart object to FETCH cart information and also to add a new line item. Both of these ACTIONS fail.   

I have been trying different ways to make this work since couple of days and am now out of ideas.

 

If anyone has any experience, kindly advice. 

Shopify Experts. I am happy to share link to the repo if you think it'll help in debugging. 

Since we are creating this app for an end-client, we are up against a deadline and would appreciate any insights you could provide.

 

Thanking in advance

 

 

0 Likes
Shopify Staff
Shopify Staff
29 13 1

Hi @runTimeZero , I am looking into this. I will get back to you as soon as possible.

0 Likes

Success.

Shopify Staff
Shopify Staff
29 13 1

Hi @runTimeZero ,

 

You need to subscribe to `Cart.Action.UPDATE` instead of `Cart.Action.FETCH`. Please check https://help.shopify.com/en/api/embedded-apps/app-bridge/actions/cart#fetch-cart

 

 

0 Likes
New Member
16 0 0

Hi Henry,

 

Thank you for responding and looking into this.

Cart.Action.Fetch should retrieve the cart details.

 

I switched over to ShopifyPOS library and the fetchCart method works great in the same situation.

 

best,

 

0 Likes
New Member
1 0 0

I am subscribed to `Cart.Action.UPDATE` as detailed in the documentation for fetch cart. However, I experience the same issues as mentioned above. The callbacks never fire, though I can see that the Cart object has the correct event subscription ( for eventType: "UPDATE" ) when I log the cart object.

0 Likes

Success.