From 52347c31bc9d358c4693337d3a4844e9ff642af0 Mon Sep 17 00:00:00 2001 From: Shahed Nasser Date: Fri, 7 Oct 2022 13:21:07 +0300 Subject: [PATCH] docs: updated how-to docs to be more consistent (#2379) * docs: updated how-to docs to be more consistent * fixed links --- .../how-to-implement-checkout-flow.mdx | 196 ++++++++++-------- docs/content/guides/carts-in-medusa.mdx | 167 +++++++-------- 2 files changed, 190 insertions(+), 173 deletions(-) diff --git a/docs/content/advanced/storefront/how-to-implement-checkout-flow.mdx b/docs/content/advanced/storefront/how-to-implement-checkout-flow.mdx index b4c445ccb4..1d3d09928c 100644 --- a/docs/content/advanced/storefront/how-to-implement-checkout-flow.mdx +++ b/docs/content/advanced/storefront/how-to-implement-checkout-flow.mdx @@ -19,31 +19,37 @@ It’s recommended to go through the [Shipping Architecture Overview](../backend ## Prerequisites +### Medusa Components + +It's assumed that you already have a Medusa server installed and set up. If not, you can follow our [quickstart guide](../../quickstart/quick-start.md) to get started. + +It is also assumed you already have a storefront set up. It can be a custom storefront or one of Medusa’s storefronts. If you don’t have a storefront set up, you can install either the [Next.js](../../starters/nextjs-medusa-starter.md) or [Gatsby](../../starters/gatsby-medusa-starter.md) storefronts. + +### JS Client + +This guide includes code snippets to send requests to your Medusa server using Medusa’s JS Client and JavaScript’s Fetch API. + +If you follow the JS Client code blocks, it’s assumed you already have [Medusa’s JS Client installed](../../js-client/overview.md) and have [created an instance of the client](../../js-client/overview.md#configuration). + +### Previous Steps + This document assumes you’ve already taken care of the add-to-cart flow. So, you should have a [cart created](https://docs.medusajs.com/api/store/#tag/Cart/operation/PostCart) for the customer with at least [one product in it](https://docs.medusajs.com/api/store/#tag/Cart/operation/PostCartsCartLineItems). You can learn how to implement the cart flow using [this documentation](../../guides/carts-in-medusa.mdx). -To follow along with this tutorial, you can make use of the [Medusa JS Client](https://www.npmjs.com/package/@medusajs/medusa-js). You can install it with this command: - -```bash npm2yarn -npm install @medusajs/medusa-js -``` - -There’s also an alternative approach in this document using [JavaScript’s Fetch API](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch) in case you’re unable to use Medusa’s JS Client. Make sure to replace `` in those examples with your server URL. - ## Shipping Step In this step, the customer generally enters their shipping info, then chooses the available shipping option based on the entered info. ### Add Shipping Address -After the customer enters their shipping address information, you must send a `POST` request to the [Update a Cart](https://docs.medusajs.com/api/store/#tag/Cart/operation/PostCartsCart) API endpoint passing it the new shipping address: +After the customer enters their shipping address information, you must send a `POST` request to the [Update a Cart](https://docs.medusajs.com/api/store/#tag/Cart/operation/PostCartsCart) API endpoint: ```jsx -medusa.carts.update(cart.id, { +medusa.carts.update(cartId, { shipping_address: { company, first_name, @@ -56,8 +62,9 @@ medusa.carts.update(cart.id, { postal_code, phone }, -}).then((response) => { - //updated cart is in response.cart +}) +.then(({ cart }) => { + console.log(cart.shipping_address); }) ``` @@ -65,7 +72,7 @@ medusa.carts.update(cart.id, { ```jsx -fetch(`/store/carts/${cart.id}`, { +fetch(`/store/carts/${cartId}`, { method: 'POST', body: JSON.stringify({ shipping_address: { @@ -84,46 +91,51 @@ fetch(`/store/carts/${cart.id}`, { headers: { 'Content-Type': 'application/json' } -}).then((response) => response.json()) - .then((response) => { - //updated cart is in response.cart - }) +}) +.then((response) => response.json()) +.then(({ cart }) => { + console.log(cart.shipping_address); +}); ``` -You can have access to the updated cart in `response.cart`, which now has the shipping address you added in `response.cart.shipping_address`. +This request accepts the ID of the cart as a path parameter and the new shipping address in the request body. + +The request returns the updated cart, with the new shipping address available in `cart.shipping_address`. ### List Shipping Options -After updating the cart with the customer’s address, the list of available [shipping options](../backend/shipping/overview.md#shipping-option) for that cart might change. So, you should retrieve the updated list of options by sending a `GET` request to the [Retrieve Shipping Options for Cart API](https://docs.medusajs.com/api/store/#tag/Shipping-Option/operation/GetShippingOptionsCartId) endpoint: +After updating the cart with the customer’s address, the list of available [shipping options](../backend/shipping/overview.md#shipping-option) for that cart might change. So, you should retrieve the updated list of options. + +You can retrieve the list of shipping options by sending a `GET` request to the [Retrieve Shipping Options for Cart API](https://docs.medusajs.com/api/store/#tag/Shipping-Option/operation/GetShippingOptionsCartId) endpoint: ```jsx -medusa.shippingOptions.listCartOptions(cart.id) - .then((response) => { - //shipping options available in response.shipping_options - }) +medusa.shippingOptions.listCartOptions(cartId) +.then(({ shipping_options }) => { + console.log(shipping_options.length); +}) ``` ```jsx -fetch(`/store/shipping-options/${cart.id}`) - .then((response) => response.json()) - .then((response) => { - //shipping options available in response.shipping_options - }) +fetch(`/store/shipping-options/${cartId}`) +.then((response) => response.json()) +.then(({ shipping_options }) => { + console.log(shipping_options.length); +}) ``` -You can access all shipping options available with their info in `response.shipping_options` which is an array of [shipping options](https://docs.medusajs.com/api/store/#tag/Shipping-Option/operation/GetShippingOptions). Typically you would display those options to the customer to choose from. +The request accepts the ID of the cart as a path parameter. It returns the array of [shipping options](https://docs.medusajs.com/api/store/#tag/Shipping-Option/operation/GetShippingOptions). Typically you would display those options to the customer to choose from. ### Choose Shipping Option @@ -133,35 +145,39 @@ Once the customer chooses one of the available shipping options, send a `POST` r ```jsx -medusa.carts.addShippingMethod(cart.id, { - option_id: shipping_option.id //shipping_option is the select option -}).then((response) => { - //updated cart is in response.cart - }) +medusa.carts.addShippingMethod(cartId, { + option_id: shippingOptionId //the ID of the selected option +}) +.then(({ cart }) => { + console.log(cart.shipping_methods) +}) ``` ```jsx -fetch(`/store/carts/${cart.id}/shipping-methods`, { +fetch(`/store/carts/${cartId}/shipping-methods`, { method: 'POST', body: JSON.stringify({ - option_id: shipping_option.id //shipping_option is the select option + option_id: shippingOptionId //the ID of the selected option }), headers: { 'Content-Type': 'application/json' } -}).then((response) => response.json()) - .then((response) => { - //updated cart is in response.cart - }) +}) +.then((response) => response.json()) +.then(({ cart }) => { + console.log(cart.shipping_methods) +}) ``` -You can have access to the updated cart in `response.cart`, which now has one item in the array value of the property `shipping_methods`. +The request accepts the ID of the cart as a path parameter and its body the ID of the selected shipping option. + +It returns the updated cart, with the created shipping method available in the array `cart.shipping_methods`. ## Payment Step @@ -177,28 +193,29 @@ To initialize the payment sessions, send a `POST` request to the [Initialize Pay ```jsx -medusa.carts.createPaymentSessions(cart.id) - .then((response) => { - //updated cart is in response.cart - }) +medusa.carts.createPaymentSessions(cartId) +.then(({ cart }) => { + console.log(cart.payment_sessions) +}) ``` ```jsx -fetch(`/store/carts/${cart.id}/payment-sessions`, { +fetch(`/store/carts/${cartId}/payment-sessions`, { method: 'POST' -}).then((response) => response.json()) - .then((response) => { - //updated cart is in response.cart - }) +}) +.then((response) => response.json()) +.then(({ cart }) => { + console.log(cart.payment_sessions) +}) ``` -You can then access the initialized payment sessions under the `payment_sessions` array in `response.cart`. +This endpoint accepts the ID of the cart as a path parameter. It returns the updated cart with the initialized payment sessions available on `cart.payment_sessions`. ### Select Payment Session @@ -208,10 +225,11 @@ When the customer chooses the payment provider they want to complete purchase wi ```jsx -medusa.carts.setPaymentSession(cart.id, { - provider_id: payment_session.provider_id //payment_session is the session chosen by the customer -}).then((response) => { - //updated cart is in response.cart +medusa.carts.setPaymentSession(cartId, { + provider_id: paymentProviderId // retrieved from the payment session selected by the customer +}) +.then(({ cart }) => { + console.log(cart.payment_session) }) ``` @@ -219,24 +237,27 @@ medusa.carts.setPaymentSession(cart.id, { ```jsx -fetch(`/store/carts/${cart.id}/payment-session`, { +fetch(`/store/carts/${cartId}/payment-session`, { method: 'POST', body: JSON.stringify({ - provider_id: payment_session.provider_id //payment_session is the session chosen by the customer + provider_id: paymentProviderId // retrieved from the payment session selected by the customer }), headers: { 'Content-Type': 'application/json' } -}).then((response) => response.json()) - .then((response) => { - //updated cart is in response.cart - }) +}) +.then((response) => response.json()) +.then(({ cart }) => { + console.log(cart.payment_session) +}) ``` -You can then access the selected payment session in `response.cart.payment_session`. +The request accepts the ID of the cart as a path parameter, and the ID of the payment provider in the request's body. + +It returns the updated cart, with the selected payment session available under `cart.payment_session`. :::tip @@ -248,20 +269,21 @@ If you have one payment provider or if only one payment provider is available fo This step is optional and is only necessary for some payment providers. As mentioned in the [Payment Architecture](../backend/payment/overview.md#overview) documentation, the `PaymentSession` model has a `data` attribute that holds any data required for the Payment Provider to perform payment operations such as capturing payment. -If you need to update that data at any point before the purchase is made, send a request to [Update a Payment Session](https://docs.medusajs.com/api/store/#tag/Cart/operation/PostCartsCartPaymentSessionUpdate) API endpoint passing it the updated data object: +If you need to update that data at any point before the purchase is made, send a request to [Update a Payment Session](https://docs.medusajs.com/api/store/#tag/Cart/operation/PostCartsCartPaymentSessionUpdate) API endpoint: ```jsx -medusa.carts.updatePaymentSession(cart.id, cart.payment_session.provider_id, { +medusa.carts.updatePaymentSession(cartId, paymentProviderId, { data: { //pass any data you want to add in the `data` attribute - //for example: + //for example: "test": true } -}).then((response) => { - //updated cart is in response.cart +}) +.then(({ cart }) => { + console.log(cart.payment_session.data) }) ``` @@ -269,7 +291,7 @@ medusa.carts.updatePaymentSession(cart.id, cart.payment_session.provider_id, { ```jsx -fetch(`/store/carts/${cart.id}/payment-sessions/${cart.payment_session.provider_id}`, { +fetch(`/store/carts/${cartId}/payment-sessions/${paymentProviderId}`, { method: 'POST', body: JSON.stringify({ data: { @@ -281,16 +303,19 @@ fetch(`/store/carts/${cart.id}/payment-sessions/${cart.payment_sessi headers: { 'Content-Type': 'application/json' } -}).then((response) => response.json()) - .then((response) => { - //updated cart is in response.cart - }) +}) +.then((response) => response.json()) +.then(({ cart }) => { + console.log(cart.payment_session.data) +}) ``` -You can have access to the updated data in the payment session in `response.cart.payment_session.data`. +This request accepts the ID of the cart and the ID of the payment session's payment provider as path parameters. In the request's body, it accepts a `data` object where you can pass any data relevant for the payment provider. + +It returns the updated cart. You can access the payment session's data on `cart.payment_session.data`. ### Complete Cart @@ -302,31 +327,36 @@ To complete a cart, send a `POST` request to the [Complete a Cart](https://docs. ```jsx -medusa.carts.complete(cart.id) - .then((response) => { - //order details is in response.data - }) +medusa.carts.complete(cartId) +.then(({ type, data }) => { + console.log(type, data); +}) ``` ```jsx -fetch(`/store/carts/${cart.id}/complete`, { +fetch(`/store/carts/${cartId}/complete`, { method: 'POST', headers: { 'Content-Type': 'application/json' } -}).then((response) => response.json()) - .then((response) => { - //order details is in response.data - }) +}) +.then((response) => response.json()) +.then(({ type, data }) => { + console.log(type, data); +}) ``` -If the order is placed successfully, you can access the order data in `response.data` and the value for `response.type` is `order`. Otherwise, `response.data` holds the cart details and `response.type` is `cart`. +This request accepts the ID of the cart as a path parameter. + +The request returns two properties: `type` and `data`. If the order was placed successfully, `type` will be `order` and `data` will be the order's data. + +If an error occurred while placing the order, `type` will be `cart` and `data` will be the cart's data. ## What’s Next 🚀 diff --git a/docs/content/guides/carts-in-medusa.mdx b/docs/content/guides/carts-in-medusa.mdx index 589b2ee56b..8926d050ff 100644 --- a/docs/content/guides/carts-in-medusa.mdx +++ b/docs/content/guides/carts-in-medusa.mdx @@ -20,53 +20,28 @@ This document does not cover implementing the checkout flow. You can refer to [t ## Prerequisites -It is assumed you already have a Medusa server installed before following along with this tutorial. If not, you can get started in minutes by following the [quickstart guide](../quickstart/quick-start.md). +### Medusa Components + +It's assumed that you already have a Medusa server installed and set up. If not, you can follow our [quickstart guide](../quickstart/quick-start.md) to get started. It is also assumed you already have a storefront set up. It can be a custom storefront or one of Medusa’s storefronts. If you don’t have a storefront set up, you can install either the [Next.js](../starters/nextjs-medusa-starter.md) or [Gatsby](../starters/gatsby-medusa-starter.md) storefronts. -## Install the JS Client +### JS Client -It is recommended to use Medusa’s JS Client in your storefront. You can install it using the following command: +This guide includes code snippets to send requests to your Medusa server using Medusa’s JS Client and JavaScript’s Fetch API. -```bash npm2yarn -npm install @medusajs/medusa-js -``` - -:::note - -This document alternatively shows code examples using [JavaScript’s Fetch API](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch). Make sure to replace `` in those examples with your server URL. - -::: - -Then, initialize the Medusa JS Client in a single file that all of your components can access: - -```jsx -import Medusa from '@medusajs/medusa-js'; - -export const client = new Medusa({ - baseUrl: '', - maxRetries: 3 -}); -``` - -Where `` is the URL of your server. If you’re using a local server, it runs on `http://localhost:9000` by default. - -:::caution - -Make sure to include `http://` in the URL when sending requests to the local server. Otherwise, all requests will fail. - -::: +If you follow the JS Client code blocks, it’s assumed you already have [Medusa’s JS Client installed](../js-client/overview.md) and have [created an instance of the client](../js-client/overview.md#configuration). ## Create a Cart You can create a cart with the following code snippet: - + ```jsx -client.carts.create() -.then(({cart}) => { +medusa.carts.create() +.then(({ cart }) => { localStorage.setItem('cart_id', cart.id); //assuming you have a state variable to store the cart setCart(cart); @@ -81,7 +56,7 @@ fetch(`/store/carts`, { method: 'POST' }) .then((response) => response.json()) -.then(({cart}) => { +.then(({ cart }) => { localStorage.setItem('cart_id', cart.id); //assuming you have a state variable to store the cart setCart(cart) @@ -91,24 +66,20 @@ fetch(`/store/carts`, { -A cart will be created with a random region assigned to it. +This request does not require any parameters. It returns the created cart in the response. -:::note - -The region a cart is associated with determines the currency the cart uses, the tax, payment, and fulfillment providers, and other details and options. So, make sure you use the correct region for a cart. - -::: +The cart by default will have a random region assigned to it. You can specify the cart's region by passing in the request's body a `region_id` parameter: Otherwise, you can assign it a specific region during creation: - + ```jsx -client.carts.create({ +medusa.carts.create({ region_id }) -.then(({cart}) => { +.then(({ cart }) => { localStorage.setItem('cart_id', cart.id); //assuming you have a state variable to store the cart setCart(cart); @@ -129,7 +100,7 @@ fetch(`/store/carts`, { }) }) .then((response) => response.json()) -.then(({cart}) => { +.then(({ cart }) => { localStorage.setItem('cart_id', cart.id); //assuming you have a state variable to store the cart setCart(cart) @@ -139,7 +110,13 @@ fetch(`/store/carts`, { -To learn about what parameters you can pass during the cart’s creation, check out the [JS Client Reference](../references/js-client/classes/CartsResource.md#create) or the [API Reference](/api/store#tag/Cart/operation/PostCart). +Check out the [API Reference](https://docs.medusajs.com/api/store/#tag/Cart/operation/PostCart) for a full list of available request body parameters. + +:::note + +The region a cart is associated with determines the currency the cart uses, the tax, payment, and fulfillment providers, and other details and options. So, make sure you use the correct region for a cart. + +::: ## Retrieve a Cart @@ -147,15 +124,15 @@ Notice that in the previous code snippets, you set the cart’s ID in the local You can retrieve the cart at any given point using its ID with the following code snippet: - + ```jsx const id = localStorage.getItem('cart_id'); if (id) { - client.carts.retrieve(id) - .then(({cart}) => setCart(cart)); + medusa.carts.retrieve(id) + .then(({ cart }) => setCart(cart)); } ``` @@ -168,13 +145,15 @@ const id = localStorage.getItem('cart_id'); if (id) { fetch(`/store/carts/${id}`) .then((response) => response.json()) - .then(({cart}) => setCart(cart)); + .then(({ cart }) => setCart(cart)); } ``` +This request accepts the ID of the cart as a path parameter and returns the cart of that ID. + You can run this code snippet every time the storefront is opened. If a customer has a cart ID stored in their local storage, it’s loaded from the server. :::tip @@ -190,14 +169,14 @@ A cart has different data associated with it including the region, email, addres You can use the following snippet to update any of the cart’s data: ```jsx -client.carts.update(cart.id, { +medusa.carts.update(cartId, { region_id }) -.then(({cart}) => setCart(cart)); +.then(({ cart }) => setCart(cart)); ``` ```jsx -fetch(`/store/carts/${cart.id}`, { +fetch(`/store/carts/${cartId}`, { method: 'POST', headers: { 'Content-Type': 'application/json' @@ -207,34 +186,36 @@ fetch(`/store/carts/${cart.id}`, { }) }) .then((response) => response.json()) -.then(({cart}) => setCart(cart)); +.then(({ cart }) => setCart(cart)); ``` -This updates the region in the cart. +This request accepts the ID of the cart as a path parameter. In its body, you can pass any data you want to update in the cart such as the region. -To find out what data you can update in the cart, check out the [JS Client reference](../references/js-client/classes/CartsResource.md#update) or the [API reference](/api/store/#tag/Cart/operation/PostCartsCart). +It returns the updated cart. + +Check out the full list of available request body parameters in the [API Reference](https://docs.medusajs.com/api/store/#tag/Cart/operation/PostCartsCart). ### Associate a Logged-In Customer with the Cart A customer might add items to their cart, then creates an account or log in. In that case, you should ensure that the cart is associated with the logged-in customer moving forward. -This can be done using the same update operation: +You can do that using the same update operation: - + ```jsx -client.carts.update(cart.id, { +medusa.carts.update(cartId, { customer_id }) -.then(({cart}) => setCart(cart)); +.then(({ cart }) => setCart(cart)); ``` ```jsx -fetch(`/store/carts/${cart.id}`, { +fetch(`/store/carts/${cartId}`, { method: 'POST', headers: { 'Content-Type': 'application/json' @@ -244,7 +225,7 @@ fetch(`/store/carts/${cart.id}`, { }) }) .then((response) => response.json()) -.then(({cart}) => setCart(cart)); +.then(({ cart }) => setCart(cart)); ``` @@ -254,25 +235,25 @@ This updates the `customer_id` associated with the cart to make sure it belongs ### Associate Guest Customers with a Cart using Email -In case the customer does not want to use their own account, you must at least associate an email address with the cart before completing the cart and placing the order. +In case the customer doesn't want to use their own account, you must at least associate an email address with the cart before completing the cart and placing the order. -This can be done using the same update operation: +You can do that using the same update operation: - + ```jsx -client.carts.update(cart.id, { +medusa.carts.update(cartId, { email: 'user@example.com' }) -.then(({cart}) => setCart(cart)); +.then(({ cart }) => setCart(cart)); ``` ```jsx -fetch(`/store/carts/${cart.id}`, { +fetch(`/store/carts/${cartId}`, { method: 'POST', headers: { 'Content-Type': 'application/json' @@ -282,7 +263,7 @@ fetch(`/store/carts/${cart.id}`, { }) }) .then((response) => response.json()) -.then(({cart}) => setCart(cart)); +.then(({ cart }) => setCart(cart)); ``` @@ -292,22 +273,22 @@ fetch(`/store/carts/${cart.id}`, { To create a line item of a product and add it to a cart, you can use the following code snippet: - + ```jsx -client.carts.lineItems.create(cart.id, { +medusa.carts.lineItems.create(cartId, { variant_id, quantity: 1 }) -.then(({cart}) => setCart(cart)); +.then(({ cart }) => setCart(cart)); ``` ```jsx -fetch(`/store/carts/${cart.id}/line-items`, { +fetch(`/store/carts/${cartId}/line-items`, { method: 'POST', headers: { 'Content-Type': 'application/json' @@ -318,13 +299,17 @@ fetch(`/store/carts/${cart.id}/line-items`, { }) }) .then((response) => response.json()) -.then(({cart}) => setCart(cart)); +.then(({ cart }) => setCart(cart)); ``` -Where `variant_id` is the variant of the product you want to add to the cart. +This request accepts the ID of the cart as a path parameter. In the body, it's required to send the ID of the product variant you want to add to the cart and its quantity. + +It returns the updated cart. + +This adds a new line item to the cart. Line items can be accessed using `cart.items` which is an array that holds all line items in the cart. You can learn more about what properties line items have in the [API reference](/api/store/#tag/Cart/operation/PostCartsCartLineItems). :::note @@ -332,27 +317,25 @@ If you’re using Sales Channels, make sure that the cart and the product belong ::: -This adds a new line item to the cart. Line items can be accessed using `cart.items` which is an array that holds all line items in the cart. You can learn more about what properties line items have in the [API reference](/api/store/#tag/Cart/operation/PostCartsCartLineItems). - ## Update Line Item in the Cart -To update a line item in the cart, you can use the following code snippet: +To update a line item's quantity in the cart, you can use the following code snippet: - + ```jsx -client.carts.lineItems.update(cart.id, line_item_id, { +medusa.carts.lineItems.update(cartId, lineItemId, { quantity: 3 }) -.then(({cart}) => setCart(cart)) +.then(({ cart }) => setCart(cart)) ``` ```jsx -fetch(`/store/carts/${cart.id}/line-items/${line_item_id}`, { +fetch(`/store/carts/${cartId}/line-items/${lineItemId}`, { method: 'POST', headers: { 'Content-Type': 'application/json' @@ -362,41 +345,45 @@ fetch(`/store/carts/${cart.id}/line-items/${line_item_id}`, { }) }) .then((response) => response.json()) -.then(({cart}) => setCart(cart)); +.then(({ cart }) => setCart(cart)); ``` -This updates the quantity of the line item in the cart using the item’s ID. +This request accepts the ID of the cart and the ID of the line item as path parameters. In the body, it accepts the quantity of the line item. + +It returns the updated cart. ## Delete a Line Item from the Cart To delete a line item from the cart, you can use the following code snippet: - + ```jsx -client.carts.lineItems.delete(cart.id, line_item_id) -.then(({cart}) => setCart(cart)) +medusa.carts.lineItems.delete(cartId, lineItemId) +.then(({ cart }) => setCart(cart)) ``` ```jsx -fetch(`/store/carts/${cart.id}/line-items/${line_item_id}`, { +fetch(`/store/carts/${cartId}/line-items/${lineItemId}`, { method: 'DELETE' }) .then((response) => response.json()) -.then(({cart}) => setCart(cart)); +.then(({ cart }) => setCart(cart)); ``` -This deletes a line item from the cart using the item’s ID. +This request accepts the ID of the cart and the ID of the line item as path parameters. + +It returns the updated cart. ## What’s Next 🚀