diff --git a/www/apps/resources/app/storefront-development/checkout/payment/page.mdx b/www/apps/resources/app/storefront-development/checkout/payment/page.mdx index 2b72bd505c..f96505a0fe 100644 --- a/www/apps/resources/app/storefront-development/checkout/payment/page.mdx +++ b/www/apps/resources/app/storefront-development/checkout/payment/page.mdx @@ -36,113 +36,122 @@ export const fetchHighlights = [ ["7", "fetch", "Retrieve available payment providers."], ["18", "selectPaymentProvider", "This function is executed when the customer submits their chosen payment provider."], ["25", "fetch", "Create a payment collection for the cart when it doesn't have one."], - ["47", "fetch", "Initialize the payment session in the payment collection for the chosen provider."], - ["65", "fetch", "Retrieve the cart again to update its data."], - ["76", "getPaymentUi", "This function shows the necessary UI based on the selected payment provider."], - ["77", "activePaymentSession", "The active session is the first in the payment collection's sessions."], - ["83", "", "Test which payment provider is chosen based on the prefix of the provider ID."], - ["84", `"pp_stripe_"`, "Check if the chosen provider is Stripe."], - ["88", `"pp_system_default"`, "Check if the chosen provider is the default systen provider."], - ["90", "default", "Handle unrecognized providers."], + ["44", "fetch", "Initialize the payment session in the payment collection for the chosen provider."], + ["62", "fetch", "Retrieve the cart again to update its data."], + ["73", "getPaymentUi", "This function shows the necessary UI based on the selected payment provider."], + ["74", "activePaymentSession", "The active session is the first in the payment collection's sessions."], + ["80", "", "Test which payment provider is chosen based on the prefix of the provider ID."], + ["81", `"pp_stripe_"`, "Check if the chosen provider is Stripe."], + ["85", `"pp_system_default"`, "Check if the chosen provider is the default systen provider."], + ["87", "default", "Handle unrecognized providers."], + ["94", "handlePayment", "The function that handles the payment process using the above functions."] ] - ```ts highlights={fetchHighlights} - // assuming the cart is previously fetched - const cart = { - // cart object... - } +```ts highlights={fetchHighlights} +// assuming the cart is previously fetched +const cart = { + // cart object... +} - const retrievePaymentProviders = async () => { - const { payment_providers } = await fetch( - `http://localhost:9000/store/payment-providers?region_id=${ - cart.region_id - }`, { - credentials: "include", - }) - .then((res) => res.json()) - - return payment_providers - } - - const selectPaymentProvider = async ( - selectedPaymentProviderId: string - ) => { - let paymentCollectionId = cart.payment_collection?.id - - if (!paymentCollectionId) { - // create payment collection - const { payment_collection } = await fetch( - `http://localhost:9000/store/payment-collections`, - { - credentials: "include", - method: "POST", - headers: { - "Content-Type": "application/json", - }, - body: JSON.stringify({ - cart_id: cart.id, - region_id: cart.region_id, - currency_code: cart.currency_code, - amount: cart.total, - }), - } - ) - .then((res) => res.json()) - - paymentCollectionId = payment_collection.id - } - - // initialize payment session - await fetch(`http://localhost:9000/store/payment-collections/${ - paymentCollectionId - }/payment-sessions`, - { +const retrievePaymentProviders = async () => { + const { payment_providers } = await fetch( + `http://localhost:9000/store/payment-providers?region_id=${ + cart.region_id + }`, { credentials: "include", - method: "POST", - headers: { - "Content-Type": "application/json", - }, - body: JSON.stringify({ - provider_id: selectedPaymentProviderId, - }), }) .then((res) => res.json()) - // re-fetch cart - const { - cart: updatedCart, - } = await fetch( - `http://localhost:9000/store/carts/${cart.id}`, + return payment_providers +} + +const selectPaymentProvider = async ( + selectedPaymentProviderId: string +) => { + let paymentCollectionId = cart.payment_collection?.id + + if (!paymentCollectionId) { + // create payment collection + const { payment_collection } = await fetch( + `http://localhost:9000/store/payment-collections`, { credentials: "include", + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ + cart_id: cart.id, + }), } ) .then((res) => res.json()) - return updatedCart + paymentCollectionId = payment_collection.id } - const getPaymentUi = () => { - const activePaymentSession = cart?.payment_collection?. - payment_sessions?.[0] - if (!activePaymentSession) { - return - } + // initialize payment session + await fetch(`http://localhost:9000/store/payment-collections/${ + paymentCollectionId + }/payment-sessions`, + { + credentials: "include", + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ + provider_id: selectedPaymentProviderId, + }), + }) + .then((res) => res.json()) - switch(true) { - case activePaymentSession.provider_id.startsWith("pp_stripe_"): - // TODO handle Stripe UI - return "You chose stripe!" - case activePaymentSession.provider_id - .startsWith("pp_system_default"): - return "You chose manual payment! No additional actions required." - default: - return `You chose ${ - activePaymentSession.provider_id - } which is in development.` + // re-fetch cart + const { + cart: updatedCart, + } = await fetch( + `http://localhost:9000/store/carts/${cart.id}`, + { + credentials: "include", } + ) + .then((res) => res.json()) + + return updatedCart +} + +const getPaymentUi = () => { + const activePaymentSession = cart?.payment_collection?. + payment_sessions?.[0] + if (!activePaymentSession) { + return } - ``` + + switch(true) { + case activePaymentSession.provider_id.startsWith("pp_stripe_"): + // TODO handle Stripe UI + return "You chose stripe!" + case activePaymentSession.provider_id + .startsWith("pp_system_default"): + return "You chose manual payment! No additional actions required." + default: + return `You chose ${ + activePaymentSession.provider_id + } which is in development.` + } +} + +const handlePayment = () => { + retrievePaymentProviders() + + // ... customer chooses payment provider + // const providerId = ... + + selectPaymentProvider(providerId) + + getPaymentUi() +} +``` @@ -164,171 +173,168 @@ export const highlights = [ ["160", "getPaymentUi", "If a provider is chosen, render its UI."] ] - ```tsx highlights={highlights} - "use client" // include with Next.js 13+ +```tsx highlights={highlights} +"use client" // include with Next.js 13+ - import { useCallback, useEffect, useState } from "react" - import { useCart } from "../../../providers/cart" - import { HttpTypes } from "@medusajs/types" +import { useCallback, useEffect, useState } from "react" +import { useCart } from "../../../providers/cart" +import { HttpTypes } from "@medusajs/types" - export default function CheckoutPaymentStep() { - const { cart, setCart } = useCart() - const [paymentProviders, setPaymentProviders] = useState< - HttpTypes.StorePaymentProvider[] - >([]) - const [ - selectedPaymentProvider, - setSelectedPaymentProvider, - ] = useState() - const [loading, setLoading] = useState(false) +export default function CheckoutPaymentStep() { + const { cart, setCart } = useCart() + const [paymentProviders, setPaymentProviders] = useState< + HttpTypes.StorePaymentProvider[] + >([]) + const [ + selectedPaymentProvider, + setSelectedPaymentProvider, + ] = useState() + const [loading, setLoading] = useState(false) - useEffect(() => { - if (!cart) { - return - } + useEffect(() => { + if (!cart) { + return + } - fetch(`http://localhost:9000/store/payment-providers?region_id=${ - cart.region_id - }`, { - credentials: "include", - }) - .then((res) => res.json()) - .then(({ payment_providers }) => { - setPaymentProviders(payment_providers) - setSelectedPaymentProvider( - cart.payment_collection?.payment_sessions?.[0]?.id - ) - }) - }, [cart]) + fetch(`http://localhost:9000/store/payment-providers?region_id=${ + cart.region_id + }`, { + credentials: "include", + }) + .then((res) => res.json()) + .then(({ payment_providers }) => { + setPaymentProviders(payment_providers) + setSelectedPaymentProvider( + cart.payment_collection?.payment_sessions?.[0]?.id + ) + }) + }, [cart]) - const handleSelectProvider = async ( - e: React.MouseEvent - ) => { - e.preventDefault() - if (!cart || !selectedPaymentProvider) { - return - } + const handleSelectProvider = async ( + e: React.MouseEvent + ) => { + e.preventDefault() + if (!cart || !selectedPaymentProvider) { + return + } - setLoading(false) + setLoading(false) - let paymentCollectionId = cart.payment_collection?.id + let paymentCollectionId = cart.payment_collection?.id - if (!paymentCollectionId) { - // create payment collection - const { payment_collection } = await fetch( - `http://localhost:9000/store/payment-collections`, - { - credentials: "include", - method: "POST", - headers: { - "Content-Type": "application/json", - }, - body: JSON.stringify({ - cart_id: cart.id, - region_id: cart.region_id, - currency_code: cart.currency_code, - amount: cart.total, - }), - } - ) - .then((res) => res.json()) - - paymentCollectionId = payment_collection.id - } - - // initialize payment session - await fetch(`http://localhost:9000/store/payment-collections/${ - paymentCollectionId - }/payment-sessions`, - { - credentials: "include", - method: "POST", - headers: { - "Content-Type": "application/json", - }, - body: JSON.stringify({ - provider_id: selectedPaymentProvider, - }), - }) - .then((res) => res.json()) - - // re-fetch cart - const { - cart: updatedCart, - } = await fetch( - `http://localhost:9000/store/carts/${cart.id}`, + if (!paymentCollectionId) { + // create payment collection + const { payment_collection } = await fetch( + `http://localhost:9000/store/payment-collections`, { credentials: "include", + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ + cart_id: cart.id, + }), } ) .then((res) => res.json()) - setCart(updatedCart) - setLoading(false) + paymentCollectionId = payment_collection.id } - const getPaymentUi = useCallback(() => { - const activePaymentSession = cart?.payment_collection?. - payment_sessions?.[0] - if (!activePaymentSession) { - return - } + // initialize payment session + await fetch(`http://localhost:9000/store/payment-collections/${ + paymentCollectionId + }/payment-sessions`, + { + credentials: "include", + method: "POST", + headers: { + "Content-Type": "application/json", + }, + body: JSON.stringify({ + provider_id: selectedPaymentProvider, + }), + }) + .then((res) => res.json()) - switch(true) { - case activePaymentSession.provider_id.startsWith("pp_stripe_"): - return ( - - You chose stripe! - {/* TODO add stripe UI */} - - ) - case activePaymentSession.provider_id - .startsWith("pp_system_default"): - return ( - - You chose manual payment! No additional actions required. - - ) - default: - return ( - - You chose {activePaymentSession.provider_id} which is - in development. - - ) + // re-fetch cart + const { + cart: updatedCart, + } = await fetch( + `http://localhost:9000/store/carts/${cart.id}`, + { + credentials: "include", } - } , [cart]) - - return ( -
-
- - -
- {getPaymentUi()} -
) + .then((res) => res.json()) + + setCart(updatedCart) + setLoading(false) } - ``` + + const getPaymentUi = useCallback(() => { + const activePaymentSession = cart?.payment_collection?. + payment_sessions?.[0] + if (!activePaymentSession) { + return + } + + switch(true) { + case activePaymentSession.provider_id.startsWith("pp_stripe_"): + return ( + + You chose stripe! + {/* TODO add stripe UI */} + + ) + case activePaymentSession.provider_id + .startsWith("pp_system_default"): + return ( + + You chose manual payment! No additional actions required. + + ) + default: + return ( + + You chose {activePaymentSession.provider_id} which is + in development. + + ) + } + } , [cart]) + + return ( +
+
+ + +
+ {getPaymentUi()} +
+ ) +} +```
@@ -340,3 +346,5 @@ In the example above, you: 1. Check whether the cart has a payment collection. If not, create one using the [Create Payment Collection API route](!api!/store#payment-collections_postpaymentcollections). 2. Initialize the payment session for the chosen payment provider using the [Initialize Payment Session API route](!api!/store#payment-collections_postpaymentcollectionsidpaymentsessions). - Once the cart has a payment session, you optionally render the UI to perform additional actions. For example, if the customer chose stripe, you can show them the card form to enter their credit card. + +In the `Fetch API` example, the `handlePayment` function implements this flow. \ No newline at end of file diff --git a/www/packages/docs-ui/src/components/MDXComponents/index.tsx b/www/packages/docs-ui/src/components/MDXComponents/index.tsx index 6e720ef64c..3cbb253216 100644 --- a/www/packages/docs-ui/src/components/MDXComponents/index.tsx +++ b/www/packages/docs-ui/src/components/MDXComponents/index.tsx @@ -153,6 +153,7 @@ export const MDXComponents: MDXComponentsType = {