docs: improved cart documentation (#2027)

This commit is contained in:
Shahed Nasser
2022-08-10 14:54:15 +03:00
committed by GitHub
parent cef081d2f2
commit 1bc517da64
5 changed files with 415 additions and 167 deletions

View File

@@ -18,6 +18,8 @@ Its recommended to go through the [Shipping Architecture Overview](../backend
This document assumes youve already taken care of the add-to-cart flow. So, you should have a [cart created](https://docs.medusajs.com/api/store/cart/create-a-cart) for the customer with at least [one product in it](https://docs.medusajs.com/api/store/cart/add-a-line-item).
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
@@ -325,5 +327,6 @@ If the order is placed successfully, you can access the order data in `response.
## Whats Next 🚀
- Learn more about the [JS Client and how to use it](../../js-client/overview.md).
- Check out available plugins for popular payment providers such as [Stripe](../../add-plugins/stripe.md) and [PayPal](/add-plugins/paypal.md).
- Learn more about the [Payment](../backend/payment/overview.md) and [Shipping](../backend/shipping/overview.md) Architectures.

View File

@@ -1,163 +0,0 @@
---
title: Carts
---
# Carts
In Medusa a Cart serves the purpose of collecting the information needed to create an Order, including what products to purchase, what address to send the products to and which payment method the purchase will be processed by.
To create a cart using the `@medusajs/medusa-js` SDK you can use:
```javascript
const client = new Medusa({ baseUrl: "http://localhost:9000" })
const { cart } = await client.carts.create()
```
A Cart will always belong to a Region and you may provide a `region_id` upon Cart creation. If no `region_id` is specified Medusa will assign the Cart to a random Region. Regions specify information about how the Cart should be taxed, what currency the Cart should be paid with and what payment and fulfillment options will be available at checkout. Below are some of the properties that can be found on the Cart response. For a full example of a Cart response [check our fixtures](https://github.com/medusajs/medusa/blob/docs/api/docs/api/fixtures/store/GetCartsCart.json).
```json
"cart": {
"id": "cart_01FEWZSRFWT8QWMHJ7ZCPRP3BZ",
"email": null,
"billing_address": null,
"shipping_address": null,
"items": [ ... ],
"region": {
"id": "reg_01FEWZSRD7HVHBSQRC4KYMG5XM",
"name": "United States",
"currency_code": "usd",
"tax_rate": "0",
...
},
"discounts": [],
"gift_cards": [],
"customer_id": null,
"payment_sessions": [],
"payment": null,
"shipping_methods": [],
"type": "default",
"metadata": null,
"shipping_total": 0,
"discount_total": 0,
"tax_total": 0,
"gift_card_total": 0,
"subtotal": 1000,
"total": 1000,
...
}
```
## Adding products to the Cart
Customers can add products to the Cart in order to start gathering the items that will eventually be purchased. In Medusa adding a product to a Cart will result in a _Line Item_ being generated. To add a product using the SDK use:
```javascript
const { cart } = await client.carts.lineItems.create(cartId, {
variant_id: "[id-of-variant-to-add]",
quantity: 1,
})
```
The resulting response will look something like this:
```json
{
"cart": {
"id": "cart_01FEWZSRFWT8QWMHJ7ZCPRP3BZ",
"items": [
{
"id": "item_01FEWZSRMBAN85SKPCRMM30N6W",
"cart_id": "cart_01FEWZSRFWT8QWMHJ7ZCPRP3BZ",
"title": "Basic Tee",
"description": "Small",
"thumbnail": null,
"is_giftcard": false,
"should_merge": true,
"allow_discounts": true,
"has_shipping": false,
"unit_price": 1000,
"variant": {
"id": "variant_01FEWZSRDNWABVFZTZ21JWKHRG",
"title": "Small",
"product_id": "prod_01FEWZSRDHDDSHQV6ATG6MS2MF",
"sku": null,
"barcode": null,
"ean": null,
"upc": null,
"allow_backorder": false,
"hs_code": null,
"origin_country": null,
"mid_code": null,
"material": null,
"weight": null,
"length": null,
"height": null,
"width": null,
"metadata": null,
...
},
"quantity": 1,
"metadata": {},
...
}
],
...
}
}
```
The properties stored on a Line Item are useful for explaining and displaying the contents of the Cart. For example, Line Items can have a thumbnail assigned which can be used to display a pack shot of the product that is being purchased, a title to show name the products in the cart and a description to give further details about the product. By default the Line Item will be generated with properties inherited from the Product that is being added to the Cart, but the behaviour can be customized for other purposes as well.
## Adding Customer information to a Cart
After adding products to the Cart, you should gather information about where to send the products, this is done using the `update` method in the SDK.
```javascript
const { cart } = await client.carts.update(cartId, {
email: "jane.doe@mail.com",
shipping_address: {
first_name: "Jane",
last_name: "Doe",
address_1: "4242 Hollywood Dr",
postal_code: "12345",
country_code: "us",
city: "Los Angeles",
region: "CA",
},
})
```
Note that the country code in the shipping address must be the country code for one of the countries in a Region - otherwise this method will fail.
## Initializing Payment Sessions
In Medusa payments are handled through the long lived entities called _Payment Sessions_. Payment Sessions cary provider specific data that can later be used to authorize the payments, which is the step required before an order can be created. The SDK provides a `createPaymentSessions` method that can be used to initialize the payment sessions with the Payment Providers available in the Region.
```javascript
const { cart } = await client.carts.createPaymentSessions(cartId)
```
You can read more about Payment Sessions in our [guide to checkouts](https://docs.medusajs.com/guides/checkouts).
## Changing the Cart region
To update the Region that the cart belongs to you should also use the `update` method from the SDK.
```javascript
const { cart } = await client.carts.update(cartId, {
region_id: "[id-of-region-to-switch-to]",
})
```
When changing the Cart region you should be aware of a couple of things:
- If switching to a Region with a different currency the line item prices and cart totals will change
- If switching to a Region with a different tax rate prices and totals will change
- If switching to a Region serving only one country the `shipping_address.country_code` will automatically be set to that country
- If the Cart already has initialized payment sessions all of these will be canceled and a new call to `createPaymentSessions` will have to be made
## What's next?
Carts are at the core of the shopping process in Medusa and provide all the necessary functionality to gather products for purchase. If you want to read a more detailed guide about how to complete checkouts please go to our [Checkout Guide](https://docs.medusajs.com/guides/checkout).
If you have questions or issues feel free to reach out via our [Discord server](https://discord.gg/xpCwq3Kfn8) for direct access to the Medusa engineering team.

View File

@@ -0,0 +1,404 @@
# How to Add Cart Functionality
This document guides you through how you can add cart-related functionalities to your storefront. That includes creating and updating a cart and managing items in the cart.
## Overview
Carts are necessary for ecommerce platforms to allow customers to buy products. Each customer, whether logged in or as a guest, should have a cart associated with them. The customer can then add products to the cart.
This document helps you understand how to add the cart functionality to your storefront. This is helpful if youre creating the storefront from scratch, or you want to understand how the process generally works in Medusas starter storefronts.
:::note
This document does not cover implementing the checkout flow. You can refer to [this documentation instead to learn how to implement the checkout flow](../advanced/storefront/how-to-implement-checkout-flow.mdx).
:::
### Glossary
- **Line Item**: When products are added to the cart in Medusa, they are referred to as line items. Line items have, by default, the same properties and attributes as a product. However, you can customize line items specifically for a cart if necessary.
## 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).
It is also assumed you already have a storefront set up. It can be a custom storefront or one of Medusas storefronts. If you dont 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
It is recommended to use Medusas JS Client in your storefront. You can install it using the following command:
```bash npm2yarn
npm install @medusajs/medusa-js
```
:::note
This document alternatively shows code examples using [JavaScripts Fetch API](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch). Make sure to replace `<SERVER_URL>` 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: '<SERVER_URL>',
maxRetries: 3
});
```
Where `<SERVER_URL>` is the URL of your server. If youre 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.
:::
## Create a Cart
You can create a cart with the following code snippet:
<Tabs groupId="request-tyoe">
<TabItem value="client" label="Medusa JS Client" default>
```jsx
client.carts.create()
.then(({cart}) => {
localStorage.setItem('cart_id', cart.id);
//assuming you have a state variable to store the cart
setCart(cart);
});
```
</TabItem>
<TabItem value="fetch" label="Fetch API">
```jsx
fetch(`<SERVER_URL>/store/carts`, {
method: 'POST'
})
.then((response) => response.json())
.then(({cart}) => {
localStorage.setItem('cart_id', cart.id);
//assuming you have a state variable to store the cart
setCart(cart)
});
```
</TabItem>
</Tabs>
A cart will be created with a random region assigned to it.
:::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.
:::
Otherwise, you can assign it a specific region during creation:
<Tabs groupId="request-tyoe">
<TabItem value="client" label="Medusa JS Client" default>
```jsx
client.carts.create({
region_id
})
.then(({cart}) => {
localStorage.setItem('cart_id', cart.id);
//assuming you have a state variable to store the cart
setCart(cart);
});
```
</TabItem>
<TabItem value="fetch" label="Fetch API">
```jsx
fetch(`<SERVER_URL>/store/carts`, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
region_id
})
})
.then((response) => response.json())
.then(({cart}) => {
localStorage.setItem('cart_id', cart.id);
//assuming you have a state variable to store the cart
setCart(cart)
});
```
</TabItem>
</Tabs>
To learn about what parameters you can pass during the carts creation, check out the [JS Client Reference](../references/js-client/classes/CartsResource.md#create) or the [API Reference](/api/store#tag/Cart/operation/PostCart).
## Retrieve a Cart
Notice that in the previous code snippets, you set the carts ID in the local storage. This is helpful to persist the customers cart even when they leave the website and come back later.
You can retrieve the cart at any given point using its ID with the following code snippet:
<Tabs groupId="request-tyoe">
<TabItem value="client" label="Medusa JS Client" default>
```jsx
const id = localStorage.getItem('cart_id');
if (id) {
client.carts.retrieve(id)
.then(({cart}) => setCart(cart));
}
```
</TabItem>
<TabItem value="fetch" label="Fetch API">
```jsx
const id = localStorage.getItem('cart_id');
if (id) {
fetch(`<SERVER_URL>/store/carts/${id}`)
.then((response) => response.json())
.then(({cart}) => setCart(cart));
}
```
</TabItem>
</Tabs>
You can run this code snippet every time the storefront is opened. If a customer has a cart ID stored in their local storage, its loaded from the server.
:::tip
Make sure to remove the ID from the local storage after the customer places an order with this cart.
:::
## Update a Cart
A cart has different data associated with it including the region, email, address, customer, and more.
You can use the following snippet to update any of the carts data:
```jsx
client.carts.update(cart.id, {
region_id
})
.then(({cart}) => setCart(cart));
```
```jsx
fetch(`<SERVER_URL>/store/carts/${cart.id}`, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
region_id
})
})
.then((response) => response.json())
.then(({cart}) => setCart(cart));
```
This updates the region in the cart.
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).
### 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:
<Tabs groupId="request-tyoe">
<TabItem value="client" label="Medusa JS Client" default>
```jsx
client.carts.update(cart.id, {
customer_id
})
.then(({cart}) => setCart(cart));
```
</TabItem>
<TabItem value="fetch" label="Fetch API">
```jsx
fetch(`<SERVER_URL>/store/carts/${cart.id}`, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
customer_id
})
})
.then((response) => response.json())
.then(({cart}) => setCart(cart));
```
</TabItem>
</Tabs>
This updates the `customer_id` associated with the cart to make sure it belongs to a specific customer.
### 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.
This can be done using the same update operation:
<Tabs groupId="request-tyoe">
<TabItem value="client" label="Medusa JS Client" default>
```jsx
client.carts.update(cart.id, {
email: 'user@example.com'
})
.then(({cart}) => setCart(cart));
```
</TabItem>
<TabItem value="fetch" label="Fetch API">
```jsx
fetch(`<SERVER_URL>/store/carts/${cart.id}`, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
email: 'user@example.com'
})
})
.then((response) => response.json())
.then(({cart}) => setCart(cart));
```
</TabItem>
</Tabs>
## Add Line Item to the Cart
To create a line item of a product and add it to a cart, you can use the following code snippet:
<Tabs groupId="request-tyoe">
<TabItem value="client" label="Medusa JS Client" default>
```jsx
client.carts.lineItems.create(cart.id, {
variant_id,
quantity: 1
})
.then(({cart}) => setCart(cart));
```
</TabItem>
<TabItem value="fetch" label="Fetch API">
```jsx
fetch(`<SERVER_URL>/store/carts/${cart.id}/line-items`, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
variant_id,
quantity: 1
})
})
.then((response) => response.json())
.then(({cart}) => setCart(cart));
```
</TabItem>
</Tabs>
Where `variant_id` is the variant of the product you want to add to the cart.
:::note
If youre using Sales Channels, make sure that the cart and the product belong to the same sales channel. You can update the carts sales channel by [updating the cart](#update-a-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).
## Update Line Item in the Cart
To update a line item in the cart, you can use the following code snippet:
<Tabs groupId="request-tyoe">
<TabItem value="client" label="Medusa JS Client" default>
```jsx
client.carts.lineItems.update(cart.id, line_item_id, {
quantity: 3
})
.then(({cart}) => setCart(cart))
```
</TabItem>
<TabItem value="fetch" label="Fetch API">
```jsx
fetch(`<SERVER_URL>/store/carts/${cart.id}/line-items/${line_item_id}`, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
quantity: 3
})
})
.then((response) => response.json())
.then(({cart}) => setCart(cart));
```
</TabItem>
</Tabs>
This updates the quantity of the line item in the cart using the items ID.
## Delete a Line Item from the Cart
To delete a line item from the cart, you can use the following code snippet:
<Tabs groupId="request-tyoe">
<TabItem value="client" label="Medusa JS Client" default>
```jsx
client.carts.lineItems.delete(cart.id, line_item_id)
.then(({cart}) => setCart(cart))
```
</TabItem>
<TabItem value="fetch" label="Fetch API">
```jsx
fetch(`<SERVER_URL>/store/carts/${cart.id}/line-items/${line_item_id}`, {
method: 'DELETE'
})
.then((response) => response.json())
.then(({cart}) => setCart(cart));
```
</TabItem>
</Tabs>
This deletes a line item from the cart using the items ID.
## Whats Next 🚀
- Learn [how to implement the checkout flow in your storefront](../advanced/storefront/how-to-implement-checkout-flow.mdx).
- Learn more about the [JS Client and how to use it](../js-client/overview.md).

View File

@@ -268,10 +268,6 @@ module.exports = {
}
]
},
{
type: "doc",
id: "guides/carts-in-medusa",
},
{
type: "doc",
id: "advanced/backend/migrations",
@@ -304,6 +300,10 @@ module.exports = {
type: "doc",
id: "advanced/storefront/how-to-implement-checkout-flow",
},
{
type: "doc",
id: "guides/carts-in-medusa",
},
]
}
]

View File

@@ -299,6 +299,10 @@ details summary {
text-decoration: none;
}
[data-theme="dark"] a:hover {
color: rgba(255, 255, 255, 0.8);
}
.DocSearch-Container {
z-index: 1001 !important;
}