Setting the file. One moment.
Wix Store Cart · Wix Vibe Headless · wix/skills · Skills Docs
ContentsBack to the top of the page Wix Blog
references/storefront/app/rest/ wix-store-cart.js
JavaScript · 147 lines · 7 KB
14 * lineItems[].id {string} — lineItemId for update/remove (NOT catalogItemId),
15 * lineItems[].quantity {number},
16 * lineItems[].catalogReference.catalogItemId {string},
17 * lineItems[].productName.original {string},
18 * lineItems[].price.formattedAmount {string} — after discounts with currency symbol,
19 * lineItems[].fullPrice.formattedAmount {string} — before discount (strikethrough),
20 * lineItems[].descriptionLines {array} — human-readable option/modifier labels:
21 * [{ name: { original }, plainText: { original } OR colorInfo: { original, code } }],
22 * lineItems[].image.url {string},
23 * lineItems[].availability.status {string} — "AVAILABLE"|"NOT_AVAILABLE"|"PARTIALLY_AVAILABLE"|"NOT_FOUND"
24 */
25
26 /**
27 * Add a product to the visitor's current cart.
28 *
29 * For products with options (variants), pass the chosen variantId — resolve it from
30 * product.variantsInfo.variants (from getProductBySlug) by matching the buyer's selected
31 * option choices to variant.choices[].optionChoiceIds.
32 *
33 * For products with modifiers:
34 * - TEXT_CHOICES: pass modifierChoices: { [modifier.key]: choiceKey }
35 * - FREE_TEXT: pass customTextFields: { [modifier.freeTextSettings.key]: userInput }
36 * Mandatory modifiers (modifier.mandatory === true) MUST be included.
37 *
38 * Throws on out-of-stock so the buyer can't reach checkout with an unbuyable line.
39 * Full catalogReference reference: https://dev.wix.com/docs/api-reference/business-solutions/stores/catalog-v3/e-commerce-integration.md
40 *
41 * @param {string} catalogItemId Product GUID (product.id).
42 * @param {string} [variantId] variantsInfo.variants[].id — required for products with variants.
43 * @param {number} [quantity]
44 * @param {{ modifierChoices?: Record<string,string>, customTextFields?: Record<string,string> }} [extras]
45 * @returns {Promise<object>} Updated cart.
46 */
47 export async function addToCart ( catalogItemId , variantId , quantity = 1 , { modifierChoices , customTextFields } = {}) {
48 const catalogReferenceOptions = {};
49 if (variantId) catalogReferenceOptions.variantId = variantId;
50 if (modifierChoices && Object. keys (modifierChoices). length ) catalogReferenceOptions.options = modifierChoices;
51 if (customTextFields && Object. keys (customTextFields). length ) catalogReferenceOptions.customTextFields = customTextFields;
52
53 const catalogReference = { appId: STORES_APP_ID , catalogItemId };
54 if (Object. keys (catalogReferenceOptions). length ) catalogReference.options = catalogReferenceOptions;
55 const res = await wixApiRequest ( "/ecom/v1/carts/current/add-to-cart" , {
56 method: "POST" ,
57 body: { lineItems: [{ catalogReference, quantity }] },
58 });
59 const line = (res?.cart?.lineItems ?? []). find (
60 ( l ) => l.catalogReference?.catalogItemId === catalogItemId && ( ! variantId || l.catalogReference?.options?.variantId === variantId),
61 );
62 // Wix returns 200 even when the line is silently rejected — guard both signals:
63 // 1. availability.status set to something other than AVAILABLE
64 // 2. no matching line at all (quantity 0 / line absent)
65 if (line?.availability?.status && line.availability.status !== "AVAILABLE" ) {
66 throw new Error ( `Item not available for sale (status: ${ line . availability . status }). Is it in stock?` );
67 }
68 if ( ! line || line.quantity === 0 ) {
69 // A missing line usually means a required selection wasn't sent — a mandatory modifier
70 // (pass modifierChoices/customTextFields) or the variantId for a product with options —
71 // not necessarily out of stock. Verify every required choice is included in this call.
72 throw new Error (
73 "Item could not be added to the cart. Check that every required selection was sent: " +
74 "the variantId for a product with options, and all mandatory modifiers " +
75 "(modifierChoices for TEXT_CHOICES, customTextFields for FREE_TEXT). It may also be out of stock." ,
76 );
77 }
78 return res?.cart;
79 }
80
81 /** Read the visitor's current cart. Returns null if no cart exists yet. */
82 export async function getCurrentCart () {
83 try {
84 const res = await wixApiRequest ( "/ecom/v1/carts/current" , { method: "GET" });
85 return res?.cart ?? null ;
86 } catch {
87 return null ;
88 }
89 }
90
91 /**
92 * Create a checkout from the current cart and return the hosted checkout URL.
93 * Throws on empty cart, unavailable lines, or a missing redirect URL.
94 * Usage: window.location.href = await checkout()
95 * @returns {Promise<string>}
96 */
97 export async function checkout () {
98 const cart = await getCurrentCart ();
99 const lines = cart?.lineItems ?? [];
100 if ( ! lines. length ) throw new Error ( "Cannot check out: the cart is empty." );
101 const unavailable = lines. filter (( l ) => l.availability?.status && l.availability.status !== "AVAILABLE" );
102 if (unavailable. length ) {
103 const names = unavailable. map (( l ) => l.productName?.original ?? l.catalogReference?.catalogItemId). join ( ", " );
104 throw new Error ( `Cannot check out: ${ unavailable . length } item(s) not available — ${ names }.` );
105 }
106
107 const checkoutRes = await wixApiRequest ( "/ecom/v1/carts/current/create-checkout" , {
108 method: "POST" ,
109 body: { channelType: "WEB" },
110 });
111 const checkoutId = checkoutRes?.checkoutId;
112 if ( ! checkoutId) throw new Error ( "Failed to create checkout from the current cart." );
113
114 const redirect = await wixApiRequest ( "/headless/v1/redirect-session" , {
115 method: "POST" ,
116 body: { ecomCheckout: { checkoutId }, callbacks: { postFlowUrl: window.location.href } },
117 });
118 const url = redirect?.redirectSession?.fullUrl;
119 if ( ! url) throw new Error ( "Failed to create the checkout redirect session." );
120 return url;
121 }
122
123 /**
124 * Update the quantity of a cart line. lineItemId is cart.lineItems[].id, not catalogItemId.
125 * Wix caps the result at remaining stock — returned quantity may be lower than requested.
126 * @returns {Promise<object>} Updated cart.
127 */
128 export async function updateCartItemQuantity ( lineItemId , quantity ) {
129 const res = await wixApiRequest ( "/ecom/v1/carts/current/update-line-items-quantity" , {
130 method: "POST" ,
131 body: { lineItems: [{ id: lineItemId, quantity }] },
132 });
133 return res?.cart;
134 }
135
136 /**
137 * Remove a line from the current cart by its cart.lineItems[].id.
138 * @param {string} lineItemId
139 * @returns {Promise<object>} Updated cart.
140 */
141 export async function removeFromCart ( lineItemId ) {
142 const res = await wixApiRequest ( "/ecom/v1/carts/current/remove-line-items" , {
143 method: "POST" ,
144 body: { lineItemIds: [lineItemId] },
145 });
146 return res?.cart;
147 }