on GitHub" data-tooltip-id=":Rblcldb:">v2.6·
In this document, you'll learn how to use Stripe for payment during checkout in a React-based storefront.
In your storefront, use the following command to install Stripe's JS and React SDKs:
Next, add an environment variable holding your Stripe publishable API key.
For example:
NEXT_PUBLIC
. If your storefront's framework requires a different prefix, make sure to change it.Then, create a file holding the following Stripe component:
1"use client" // include with Next.js 13+2 3import { 4 CardElement, 5 Elements, 6 useElements, 7 useStripe,8} from "@stripe/react-stripe-js"9import { loadStripe } from "@stripe/stripe-js"10import { useCart } from "../../providers/cart"11import { useState } from "react"12 13const stripePromise = loadStripe(14 process.env.NEXT_PUBLIC_STRIPE_PK || "temp"15)16 17export default function StripePayment() {18 const { cart } = useCart()19 const clientSecret = cart?.payment_collection?.20 payment_sessions?.[0].data.client_secret as string21 22 return (23 <div>24 <Elements stripe={stripePromise} options={{25 clientSecret,26 }}>27 <StripeForm clientSecret={clientSecret} />28 </Elements>29 </div>30 )31}32 33const StripeForm = ({ 34 clientSecret,35}: {36 clientSecret: string | undefined37}) => {38 const { cart, refreshCart } = useCart()39 const [loading, setLoading] = useState(false)40 41 const stripe = useStripe()42 const elements = useElements()43 44 async function handlePayment(45 e: React.MouseEvent<HTMLButtonElement, MouseEvent>46 ) {47 e.preventDefault()48 const card = elements?.getElement(CardElement)49 50 if (51 !stripe || 52 !elements ||53 !card ||54 !cart ||55 !clientSecret56 ) {57 return58 }59 60 setLoading(true)61 stripe?.confirmCardPayment(clientSecret, {62 payment_method: {63 card,64 billing_details: {65 name: cart.billing_address?.first_name,66 email: cart.email,67 phone: cart.billing_address?.phone,68 address: {69 city: cart.billing_address?.city,70 country: cart.billing_address?.country_code,71 line1: cart.billing_address?.address_1,72 line2: cart.billing_address?.address_2,73 postal_code: cart.billing_address?.postal_code,74 },75 },76 },77 })78 .then(({ error }) => {79 if (error) {80 // TODO handle errors81 console.error(error)82 return83 }84 85 fetch(86 `http://localhost:9000/store/carts/${cart.id}/complete`,87 {88 credentials: "include",89 headers: {90 "x-publishable-api-key": process.env.NEXT_PUBLIC_MEDUSA_PUBLISHABLE_KEY || "temp",91 },92 method: "POST",93 }94 )95 .then((res) => res.json())96 .then(({ type, cart, order, error }) => {97 if (type === "cart" && cart) {98 // an error occured99 console.error(error)100 } else if (type === "order" && order) {101 // TODO redirect to order success page102 alert("Order placed.")103 console.log(order)104 refreshCart()105 }106 })107 })108 .finally(() => setLoading(false))109 }110 111 return (112 <form>113 <CardElement />114 <button115 onClick={handlePayment}116 disabled={loading}117 >118 Place Order119 </button>120 </form>121 )122}
In the code snippet above, you:
StripePayment
component that wraps the actual form with Stripe's Elements
component.
StripePayment
component, you obtain the client secret from the payment session's data
field. This is set in the Medusa application.StripeForm
component that holds the actual form. In this component, you implement a handlePayment
function that does the following:
confirmCardPayment
method to accept the card details from the customer.confirmCardPayment
method is executed.type
is cart
, it means that the cart completion failed. The error is set in the error
response field.type
is order
, it means the card was completed and the order was placed successfully. You can access the order in the order
response field.You can now use the Stripe component in the checkout flow. You should render it after the customer chooses Stripe as a payment provider.
For example, you can use it in the getPaymentUi
function defined in the Payment Checkout Step guide:
1const getPaymentUi = useCallback(() => {2 const activePaymentSession = cart?.payment_collection?.3 payment_sessions?.[0]4 if (!activePaymentSession) {5 return6 }7 8 switch(true) {9 case activePaymentSession.provider_id.startsWith("pp_stripe_"):10 return <StripePayment />11 // ...12 }13} , [cart])
Refer to Stripe's documentation for more details on integrating it in your storefront.