Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ This guide will walk you through how to build a custom user interface for a chec
'use client'
import * as React from 'react'
import { SignedIn, ClerkLoaded } from '@clerk/nextjs'
import { useRouter } from 'next/navigation'
import { CheckoutProvider, useCheckout, usePaymentMethods } from '@clerk/nextjs/experimental'
import { useMemo, useState } from 'react'

Expand Down Expand Up @@ -99,6 +100,8 @@ This guide will walk you through how to build a custom user interface for a chec
const [isProcessing, setIsProcessing] = useState(false)
const [paymentMethodId, setPaymentMethodId] = useState<string | null>(null)

const router = useRouter()

const defaultMethod = useMemo(() => data?.find((method) => method.isDefault), [data])

const submitSelectedMethod = async () => {
Expand All @@ -110,7 +113,9 @@ This guide will walk you through how to build a custom user interface for a chec
// Confirm checkout with payment method
await confirm({ paymentSourceId })
// Complete checkout and redirect
finalize({ redirectUrl: '/dashboard' })
await finalize({
navigate: () => router.push('/dashboard'),
})
} catch (error) {
console.error('Payment failed:', error)
} finally {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ For the custom flow that allows users to add a new payment method to their accou
PaymentElement,
usePaymentElement,
} from '@clerk/nextjs/experimental'
import { useRouter } from 'next/navigation'

export default function CheckoutPage() {
return (
Expand Down Expand Up @@ -106,6 +107,8 @@ For the custom flow that allows users to add a new payment method to their accou
const { isFormReady, submit } = usePaymentElement()
const [isProcessing, setIsProcessing] = React.useState(false)

const router = useRouter()

const handleSubmit = async (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault()
if (!isFormReady || isProcessing) return
Expand All @@ -121,7 +124,9 @@ For the custom flow that allows users to add a new payment method to their accou
// Confirm checkout with payment method
await confirm(data)
// Complete checkout and redirect
finalize({ redirectUrl: '/dashboard' })
await finalize({
navigate: () => router.push('/dashboard'),
})
} catch (error) {
console.error('Payment failed:', error)
} finally {
Expand Down
11 changes: 8 additions & 3 deletions docs/reference/hooks/use-checkout.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -152,9 +152,9 @@ There are two ways to use `useCheckout()`:
---

- `finalize()`
- `(params?: { redirectUrl: string }) => void`
- `(params?: { navigate?: SetActiveNavigate }) => void`

A function that finalizes the checkout process. Can optionally accept a `redirectUrl` to navigate the user to upon completion.
A function that finalizes the checkout process. Can optionally accept a `navigate()` function to redirect the user after completion.

---

Expand Down Expand Up @@ -226,6 +226,7 @@ The `useCheckout()` hook can be used with a context provider for managing state
'use client'

import { useCheckout } from '@clerk/nextjs/experimental'
import { useRouter } from 'next/navigation'

export function CheckoutFlow() {
const { checkout } = useCheckout()
Expand Down Expand Up @@ -262,6 +263,8 @@ The `useCheckout()` hook can be used with a context provider for managing state
const [isProcessing, setIsProcessing] = useState(false)
const [paymentMethodId, setPaymentMethodId] = useState<string | null>(null)

const router = useRouter()

const submitSelectedMethod = async () => {
if (isProcessing || !paymentMethodId) return
setIsProcessing(true)
Expand All @@ -273,7 +276,9 @@ The `useCheckout()` hook can be used with a context provider for managing state
})
// Calling `.finalize` enables you to sync the client-side state with the server-side state of your users.
// It revalidates all authorization checks computed within server components.
finalize({ redirectUrl: '/dashboard' })
await finalize({
navigate: () => router.push('/dashboard'),
})
} catch (error) {
console.error('Payment failed:', error)
} finally {
Expand Down
7 changes: 6 additions & 1 deletion docs/reference/hooks/use-payment-methods.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -198,18 +198,23 @@ The following example demonstrates how to use `usePaymentMethods()` in a checkou

```tsx
import { usePaymentMethods, useCheckout } from '@clerk/nextjs/experimental'
import { useRouter } from 'next/navigation'

function CheckoutPaymentSelection() {
const { data, isLoading } = usePaymentMethods({ for: 'user' })
const { checkout } = useCheckout()
const { confirm, finalize } = checkout

const router = useRouter()

const handlePaymentSubmit = async (paymentMethodId: string) => {
try {
// Confirm checkout with selected payment method
await confirm({ paymentSourceId: paymentMethodId })
// Complete checkout and redirect
finalize({ redirectUrl: '/dashboard' })
await finalize({
navigate: () => router.push('/dashboard'),
})
} catch (error) {
console.error('Payment failed:', error)
}
Expand Down