docs: update create payment collection route usage in store development (#8736)
This commit is contained in:
@@ -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()
|
||||
}
|
||||
```
|
||||
|
||||
</CodeTab>
|
||||
<CodeTab label="React" value="react">
|
||||
@@ -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<string | undefined>()
|
||||
const [loading, setLoading] = useState(false)
|
||||
export default function CheckoutPaymentStep() {
|
||||
const { cart, setCart } = useCart()
|
||||
const [paymentProviders, setPaymentProviders] = useState<
|
||||
HttpTypes.StorePaymentProvider[]
|
||||
>([])
|
||||
const [
|
||||
selectedPaymentProvider,
|
||||
setSelectedPaymentProvider,
|
||||
] = useState<string | undefined>()
|
||||
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<HTMLButtonElement, MouseEvent>
|
||||
) => {
|
||||
e.preventDefault()
|
||||
if (!cart || !selectedPaymentProvider) {
|
||||
return
|
||||
}
|
||||
const handleSelectProvider = async (
|
||||
e: React.MouseEvent<HTMLButtonElement, 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 (
|
||||
<span>
|
||||
You chose stripe!
|
||||
{/* TODO add stripe UI */}
|
||||
</span>
|
||||
)
|
||||
case activePaymentSession.provider_id
|
||||
.startsWith("pp_system_default"):
|
||||
return (
|
||||
<span>
|
||||
You chose manual payment! No additional actions required.
|
||||
</span>
|
||||
)
|
||||
default:
|
||||
return (
|
||||
<span>
|
||||
You chose {activePaymentSession.provider_id} which is
|
||||
in development.
|
||||
</span>
|
||||
)
|
||||
// re-fetch cart
|
||||
const {
|
||||
cart: updatedCart,
|
||||
} = await fetch(
|
||||
`http://localhost:9000/store/carts/${cart.id}`,
|
||||
{
|
||||
credentials: "include",
|
||||
}
|
||||
} , [cart])
|
||||
|
||||
return (
|
||||
<div>
|
||||
<form>
|
||||
<select
|
||||
value={selectedPaymentProvider}
|
||||
onChange={(e) => setSelectedPaymentProvider(e.target.value)}
|
||||
>
|
||||
{paymentProviders.map((provider) => (
|
||||
<option
|
||||
key={provider.id}
|
||||
value={provider.id}
|
||||
>
|
||||
{provider.id}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
<button
|
||||
disabled={loading}
|
||||
onClick={async (e) => {
|
||||
await handleSelectProvider(e)
|
||||
}}
|
||||
>
|
||||
Submit
|
||||
</button>
|
||||
</form>
|
||||
{getPaymentUi()}
|
||||
</div>
|
||||
)
|
||||
.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 (
|
||||
<span>
|
||||
You chose stripe!
|
||||
{/* TODO add stripe UI */}
|
||||
</span>
|
||||
)
|
||||
case activePaymentSession.provider_id
|
||||
.startsWith("pp_system_default"):
|
||||
return (
|
||||
<span>
|
||||
You chose manual payment! No additional actions required.
|
||||
</span>
|
||||
)
|
||||
default:
|
||||
return (
|
||||
<span>
|
||||
You chose {activePaymentSession.provider_id} which is
|
||||
in development.
|
||||
</span>
|
||||
)
|
||||
}
|
||||
} , [cart])
|
||||
|
||||
return (
|
||||
<div>
|
||||
<form>
|
||||
<select
|
||||
value={selectedPaymentProvider}
|
||||
onChange={(e) => setSelectedPaymentProvider(e.target.value)}
|
||||
>
|
||||
{paymentProviders.map((provider) => (
|
||||
<option
|
||||
key={provider.id}
|
||||
value={provider.id}
|
||||
>
|
||||
{provider.id}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
<button
|
||||
disabled={loading}
|
||||
onClick={async (e) => {
|
||||
await handleSelectProvider(e)
|
||||
}}
|
||||
>
|
||||
Submit
|
||||
</button>
|
||||
</form>
|
||||
{getPaymentUi()}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
</CodeTab>
|
||||
</CodeTabs>
|
||||
@@ -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.
|
||||
@@ -153,6 +153,7 @@ export const MDXComponents: MDXComponentsType = {
|
||||
<li
|
||||
className={clsx(
|
||||
"text-medusa-fg-subtle [&:not(:last-child)]:mb-docs_0.5",
|
||||
"[&_ol]:mt-docs_0.5 [&_ul]:mt-docs_0.5",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
|
||||
Reference in New Issue
Block a user