Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Shopify Storefront API. adding item to cart

Im using the Shopify storefront API to query for a list of products and add a selected item to the cart.

I am able to use API to list all the products, and returns the variantID for the product found

Here is the GraphQL query to return a product

{
  shop {
    name
    products(first: 1, query:"title=configurable-handmade-concrete-ball") {
      edges {
        cursor
        node {
          id
          title
          handle
          variants(first:1) {
            edges {
              node {
                id
                title
              }
            }
          }
        }
      }
    }
  }
}

and the result

{
  "data": {
    "shop": {
      "name": "VonageTest",
      "products": {
        "edges": [
          {
            "cursor": "eyJvZmZzZXQiOjF9",
            "node": {
              "id": "Z2lkOi8vc2hvcGlmeS9Qcm9kdWN0LzEwNTU2MjYxNTE4",
              "title": "Configurable Handmade Concrete Ball",
              "handle": "configurable-handmade-concrete-ball",
              "variants": {
                "edges": [
                  {
                    "node": {
                      "id": "Z2lkOi8vc2hvcGlmeS9Qcm9kdWN0VmFyaWFudC80MDIwOTc1NjQzMA==",
                      "title": "Default Title"
                    }
                  }
                ]
              }
            }
          }
        ]
      }
    }
  }
}

In order to add items to the cart, you can make a POST request that contains the following

https://{store_name}.myshopify.com/cart/{variant_id}

performing this call using the variant_id from the graphQL response returns a 404. But if you get the variant_id from the page, you can inspect the xml page and use the variant_id there This shows how that is done https://help.shopify.com/themes/customization/cart/use-permalinks-to-preload-cart

so why does the variant_id from the storefront API different from the variant_id on the page?

like image 810
Tony Avatar asked May 15 '17 18:05

Tony


People also ask

How do I get a cart token on Shopify?

Put a customized button(ex. My Checkout) on shopify cart page to proceed for your custom checkout option. On the click of your customized button get the cart token to your custom checkout page and retrieve the cart data using it. You can use session for authentication.


2 Answers

I just encountered the same problem and was finally able to track down the answer in the Shopify GraphQL docs - https://help.shopify.com/api/storefront-api/reference/scalar/id

Basically, the id returned in Shopify GraphQL responses is a base64-encoded representation of the actual Shopify id. So if you base64-decode the variant id from the result you posted, the value is gid://shopify/ProductVariant/40209756430

You would need to parse the numerical id from the end of that value and that would be the id that Shopify uses for all other APIs.

like image 166
Adam Weber Avatar answered Feb 07 '23 03:02

Adam Weber


I have implemented the shopify shop and cart using GraphQL provided by shopify . Follow these steps -

  1. Create Storefront.CheckoutCreateInput() object.
  2. Add lineItems to it - Storefront.CheckoutLineItemInput(quantity,new ID(productVariantId)); Don't be confused with productId with productVariantID . You need to use productVariantId here
  3. Now you need to mutate line items on CheckoutCreateInput object -

    Storefront.MutationQuery query = Storefront.mutation(mutationQuery -> mutationQuery
            .checkoutCreate(checkoutCreateInputObject, createPayloadQuery -> createPayloadQuery
                    .checkout(checkoutQuery -> checkoutQuery
                            .webUrl()
                    )
                    .userErrors(userErrorQuery -> userErrorQuery
                            .field()
                            .message()
                    )
            )
    );
    

You will get a checkout Id here , save it .

4.Now you need to create Storefront.MailingAddressInput() , taking inputs from user (city , state , email , name etc).Then you need to update this mailing address on CheckoutCreateInput() object like this checkoutCreateInputObj.setShippingAddress() .

5.Now you need to fetch Shipping Rates -

            Storefront.QueryRootQuery query = Storefront.query(rootQuery -> rootQuery
            .node(checkoutId, nodeQuery -> nodeQuery
                    .onCheckout(checkoutQuery -> checkoutQuery
                            .availableShippingRates(availableShippingRatesQuery -> availableShippingRatesQuery
                                    .ready()
                                    .shippingRates(shippingRateQuery -> shippingRateQuery
                                            .handle()
                                            .price()
                                            .title()
                                    )
                            )
                    )
            )
    );
  1. Fetch the total price user need to pay -

    Storefront.QueryRootQuery query = Storefront.query(rootQuery -> rootQuery
            .node(checkoutId, nodeQuery -> nodeQuery
                    .onCheckout(checkoutQuery -> checkoutQuery
                            .subtotalPrice()
                            .totalPrice()
                            .availableShippingRates(availableShippingRateQuery -> availableShippingRateQuery
                                .ready()
                                    .shippingRates(shippingRateQuery -> shippingRateQuery
                                            .price()
                                    )
                            )
                    )
            )
    );
    
  2. Apply coupons if any -

    Storefront.MutationQuery query = Storefront.mutation(mutationQuery -> mutationQuery
            .checkoutDiscountCodeApply(couponCode,checkoutId,discountQuery -> discountQuery
                    .userErrors(userErrorQuery -> userErrorQuery
                            .message()
                            .field()
                    )
                    .checkout(checkoutQuery -> checkoutQuery
                            .webUrl()
                            .totalPrice()
                            .appliedGiftCards(giftCardQuery -> giftCardQuery
                                .amountUsed()
                                    .balance()
                            )
                    )
            )
    );
    
  3. Get the cardVaultURL -

    Storefront.QueryRootQuery query = Storefront.query(rootQueryBuilder ->
            rootQueryBuilder
                    .shop(shopQueryBuilder ->
                            shopQueryBuilder
                                    .paymentSettings(paymentQueryBuilder -> paymentQueryBuilder
                                            .cardVaultUrl()
                                    )
                    )
    );
    
  4. Get the payment token -

    CardClient cardClient = new CardClient();
    CreditCard creditCard = CreditCard.builder()
            .firstName(firstName)
            .lastName(lastName)
            .number(cardNumber)
            .expireMonth(expiryMonth)
            .expireYear(expiryYear)
            .verificationCode(cvv)
            .build();
    

    cardClient.vault(creditCard, cardVaultURL).enqueue(new CreditCardVaultCall.Callback() { @Override public void onResponse(@NonNull String token) { // proceed to complete checkout with token paymentToken = token; }

        @Override public void onFailure(@NonNull IOException error) {
            // handle error
            Log.d("error occured are just ",error.toString());
        }
    });
    
  5. Charge amount -

    String idempotencyKey = UUID.randomUUID().toString();
        Storefront.CreditCardPaymentInput input = new Storefront.CreditCardPaymentInput(amount, idempotencyKey, billingAddress,
                paymentToken);
    
    
    
        Storefront.MutationQuery query = Storefront.mutation(mutationQuery -> mutationQuery
                .checkoutCompleteWithCreditCard(shopifyHandler.checkoutId, input, payloadQuery -> payloadQuery
                        .payment(paymentQuery -> paymentQuery
                                .ready()
                                .errorMessage()
                        )
                        .checkout(checkoutQuery -> checkoutQuery
                                .ready()
                        )
                        .userErrors(userErrorQuery -> userErrorQuery
                                .field()
                                .message()
                        )
                )
        );
    
like image 31
Mandeep Kumar Avatar answered Feb 07 '23 02:02

Mandeep Kumar