docs: update create payment collection route usage in store development (#8736)

This commit is contained in:
Shahed Nasser
2024-08-27 11:35:22 +03:00
committed by GitHub
parent 5996089c9c
commit b36e2c3129
2 changed files with 243 additions and 234 deletions
@@ -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}