Tony
Tony

Reputation: 664

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?

Upvotes: 6

Views: 8324

Answers (3)

Ryan
Ryan

Reputation: 440

I have two utility functions that I've been using to flip back and forth between the gid and rest id:

export const getRestIdFromGid = (gid) => {
  return gid.split("/")[gid.split("/").length - 1];
}

export const getGidFromRestId = (id, type) => {
  return `gid://shopify/${type}/${id}`
}

like previous posts mentioned your response is a base64 encoded version of the gid://shopify/ProductVariant/${id} so you'd have to add that decoding/encoding into these, I think the GraphQL library I'm using automatically decodes ids.

Upvotes: 0

Mandeep Kumar
Mandeep Kumar

Reputation: 776

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()
                        )
                )
        );
    

Upvotes: 8

Adam Weber
Adam Weber

Reputation: 2395

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.

Upvotes: 9

Related Questions