On this page
No Headings
Last updated: July 14, 2026
To integrate PayPal, Venmo, Pay Later, and other payment methods into React applications, use the PayPal React SDK v6 (@paypal/react-paypal-js/sdk-v6). This reference covers the provider component, hooks, payment session hooks, payment button components, card fields, server utilities, types, and common patterns.
PayPalProvider is a context provider that initializes the PayPal SDK and provides payment functionality to child components.
| Prop | Type | Required | Description |
|---|---|---|---|
clientId | string | Promise<string> | undefined | yes | PayPal client ID for authenticating SDK requests. Use either
|
clientToken | string | Promise<string> | undefined | yes | PayPal client token for authenticating SDK requests. Use either
|
components | string[] | yes | Array of components to load. Values include
|
environment | string | yes | Target environment. Values are |
pageType | string | no | Page context type, for example, |
locale | string | no | Locale for the SDK, for example, |
clientMetadataId | string | no | Client metadata ID for tracking |
partnerAttributionId | string | no | Partner attribution ID |
shopperSessionId | string | no | Shopper session ID for personalization |
testBuyerCountry | string | no | Test buyer country for sandbox testing |
merchantId | string | string[] | no | Merchant ID or array of merchant IDs |
eligibleMethodsResponse | object | no | Pre-fetched eligible methods response from server-side
|
debug | boolean | no | Enable debug mode |
dataNamespace | string | no | Custom namespace for the SDK data attribute |
PayPalProvider requires a clientId or
clientToken to authenticate your integration.
Replace YOUR_PAYPAL_CLIENT_ID with your app's PayPal client ID when initializing the provider.
Place PayPalProvider at your app root so payment buttons render sooner.
import { PayPalProvider } from "@paypal/react-paypal-js/sdk-v6";
function App() {
return (
<PayPalProvider
clientId="YOUR_PAYPAL_CLIENT_ID"
environment="sandbox"
components={["paypal-payments", "venmo-payments", "paypal-subscriptions"]}
pageType="checkout"
>
{/* Child components */}
</PayPalProvider>
); }
import { useMemo } from "react";
import { PayPalProvider } from "@paypal/react-paypal-js/sdk-v6";
function App() {
// Memoize the promise to prevent re-fetching on every render
const tokenPromise = useMemo(() => fetchClientToken(), []);
return (
<PayPalProvider
clientToken={tokenPromise}
environment="sandbox"
components={["paypal-payments"]}
pageType="checkout"
>
{/* Child components */}
</PayPalProvider>
);
}Hooks provide access to SDK state and payment eligibility data inside your React components. Use them to check SDK internals or conditionally render UI based on which payment methods are available.
usePayPal()usePayPal provides access to the PayPal SDK state and payment eligibility information. Must be used within a PayPalProvider.
| Property | Type | Description |
|---|---|---|
loadingStatus | INSTANCE_LOADING_STATE | Current SDK loading state. Compare against
|
eligiblePaymentMethods | object | null | Available payment methods for the current user |
sdkInstance | object | null | The underlying SDK instance |
error | Error | null | Any error that occurred during SDK initialization |
isHydrated | boolean | Whether the component has been hydrated on the client |
Use usePayPal to access the SDK state and payment eligibility in any component inside PayPalProvider.
import {
usePayPal,
INSTANCE_LOADING_STATE,
} from "@paypal/react-paypal-js/sdk-v6";
function CheckoutForm() {
const { loadingStatus, error } = usePayPal();
if (loadingStatus === INSTANCE_LOADING_STATE.PENDING) {
return <div>Loading...</div>;
}
if (loadingStatus === INSTANCE_LOADING_STATE.REJECTED) {
return <div>Failed to load PayPal SDK: {error?.message}</div>;
}
return <PaymentButtons />;
}useEligibleMethods(options)useEligibleMethods returns eligible payment methods from the PayPal SDK. It prevents duplicate API calls across components.
| Parameter | Required | Description |
|---|---|---|
payload.amount | no | string. Order amount, for example,
|
payload.currencyCode | no | string. Three-letter ISO 4217 currency code, for
example, |
payload.paymentFlow | no | string. The payment flow type. Values are
|
| Property | Type | Description |
|---|---|---|
eligiblePaymentMethods | object | null | Available payment methods for the current user.
|
isLoading | boolean | Whether eligibility data is still being fetched |
error | Error | null | Any error that occurred during the fetch |
The following example fetches eligible payment methods for a one-time USD payment and conditionally renders a Pay Later button that is based on the result.
import {
useEligibleMethods,
usePayLaterOneTimePaymentSession,
} from "@paypal/react-paypal-js/sdk-v6";
function PayLaterCheckout(props) {
const { handleClick } = usePayLaterOneTimePaymentSession(props);
const { eligiblePaymentMethods, isLoading, error } = useEligibleMethods({
payload: { currencyCode: "USD" },
});
const payLaterDetails = eligiblePaymentMethods?.getDetails?.("paylater");
const countryCode = payLaterDetails?.countryCode;
const productCode = payLaterDetails?.productCode;
if (isLoading) return <div>Loading...</div>;
if (error) return <div>Error: {error.message}</div>;
return (
<paypal-pay-later-button
onClick={handleClick}
countryCode={countryCode}
productCode={productCode}
/>
);
}usePayPalMessages(options)usePayPalMessages creates a PayPal Messages session to fetch messaging content and create learn more modals.
| Parameter | Required | Description |
|---|---|---|
buyerCountry | no | string. Buyer's country code |
currencyCode | no | string. Currency code |
shopperSessionId | no | string. Shopper session ID |
| Property | Type | Description |
|---|---|---|
error | Error | null | Any session error |
isReady | boolean | Whether the session is created |
handleFetchContent | function | Fetches message content |
handleCreateLearnMore | function | Creates a learn more modal |
The following example uses auto-bootstrap mode to display a PayPal message with a learn more modal.
import { usePayPalMessages } from "@paypal/react-paypal-js/sdk-v6";
function PayPalMessaging({ amount }: { amount: string }) {
const { error } = usePayPalMessages({});
if (error) return null;
return (
<paypal-message
auto-bootstrap={true}
amount={amount}
currency-code="USD"
buyer-country="US"
/>
);
}Payment session hooks give you control over the payment flow for advanced integrations. Each button component has a session hook. All payment session hooks return a BasePaymentSessionReturn object.
| Property | Type | Description |
|---|---|---|
error | Error | null | Any session error |
isPending | boolean | Whether the SDK instance is still loading |
handleClick | () => Promise | Starts the payment session |
handleCancel | () => void | Cancels the session |
handleDestroy | () => void | Cleans up the session |
usePayPalOneTimePaymentSessionThe following example creates an order on your server and renders a custom PayPal button that starts the payment session when selected.
import { usePayPalOneTimePaymentSession } from "@paypal/react-paypal-js/sdk-v6";
function CustomPayPalButton() {
const { isPending, error, handleClick } = usePayPalOneTimePaymentSession({
createOrder: async () => {
const res = await fetch("/api/orders", { method: "POST" });
const { id } = await res.json();
return { orderId: id };
},
onApprove: async (data) => {
console.log("Approved:", data.orderId);
},
presentationMode: "auto",
});
if (isPending) return null;
if (error) return <div>Error: {error.message}</div>;
return <paypal-button onClick={handleClick} type="pay" />;
}useVenmoOneTimePaymentSessionThe following example creates an order and renders a custom Venmo button for one-time payments.
import { useVenmoOneTimePaymentSession } from "@paypal/react-paypal-js/sdk-v6";
function CustomVenmoButton() {
const { isPending, error, handleClick } = useVenmoOneTimePaymentSession({
createOrder: async () => {
const res = await fetch("/api/orders", { method: "POST" });
const { id } = await res.json();
return { orderId: id };
},
onApprove: async (data) => {
console.log("Approved:", data.orderId);
},
presentationMode: "auto",
});
if (isPending) return null;
if (error) return <div>Error: {error.message}</div>;
return <venmo-button onClick={handleClick} type="pay" />;
}usePayLaterOneTimePaymentSessionThe following example retrieves Pay Later eligibility details from usePayPal and passes countryCode and productCode to a custom Pay Later button.
import {
usePayLaterOneTimePaymentSession,
usePayPal,
} from "@paypal/react-paypal-js/sdk-v6";
function CustomPayLaterButton() {
const { eligiblePaymentMethods } = usePayPal();
const { isPending, error, handleClick } = usePayLaterOneTimePaymentSession({
createOrder: async () => {
const res = await fetch("/api/orders", { method: "POST" });
const { id } = await res.json();
return { orderId: id };
},
onApprove: async (data) => {
console.log("Approved:", data.orderId);
},
presentationMode: "auto",
});
const payLaterDetails = eligiblePaymentMethods?.getDetails("paylater");
if (isPending) return null;
if (error) return <div>Error: {error.message}</div>;
return (
<paypal-pay-later-button
onClick={handleClick}
countryCode={payLaterDetails?.countryCode}
productCode={payLaterDetails?.productCode}
/>
);
}usePayPalCreditOneTimePaymentSessionThe following example retrieves PayPal Credit eligibility details and renders a custom credit button with the buyer's countryCode.
import {
usePayPalCreditOneTimePaymentSession,
usePayPal,
} from "@paypal/react-paypal-js/sdk-v6";
function CustomCreditButton() {
const { eligiblePaymentMethods } = usePayPal();
const { isPending, error, handleClick } =
usePayPalCreditOneTimePaymentSession({
createOrder: async () => {
const res = await fetch("/api/orders", { method: "POST" });
const { id } = await res.json();
return { orderId: id };
},
onApprove: async (data) => {
console.log("Approved:", data.orderId);
},
presentationMode: "auto",
});
const creditDetails = eligiblePaymentMethods?.getDetails?.("credit");
if (isPending) return null;
if (error) return <div>Error: {error.message}</div>;
return (
<paypal-credit-button
onClick={handleClick}
countryCode={creditDetails?.countryCode}
/>
);
}usePayPalGuestPaymentSessionusePayPalGuestPaymentSession returns an additional buttonRef to pass to the <paypal-basic-card-button> element. The following example renders a guest checkout button inside a <paypal-basic-card-container> wrapper.
import { usePayPalGuestPaymentSession } from "@paypal/react-paypal-js/sdk-v6";
function CustomGuestButton() {
const { buttonRef, isPending, error, handleClick } =
usePayPalGuestPaymentSession({
createOrder: async () => {
const res = await fetch("/api/orders", { method: "POST" });
const { id } = await res.json();
return { orderId: id };
},
onApprove: async (data) => {
console.log("Approved:", data.orderId);
},
});
if (isPending) return null;
if (error) return <div>Error: {error.message}</div>;
return (
<paypal-basic-card-container>
<paypal-basic-card-button ref={buttonRef} onClick={handleClick} />
</paypal-basic-card-container>
);
}usePayPalSavePaymentSessionThe following example creates a vault setup token on your server and renders a button that saves the payment method when selected.
import { usePayPalSavePaymentSession } from "@paypal/react-paypal-js/sdk-v6";
function CustomSaveButton() {
const { isPending, error, handleClick } = usePayPalSavePaymentSession({
createVaultToken: async () => {
const res = await fetch("/api/vault-setup-token", { method: "POST" });
const { id } = await res.json();
return { vaultSetupToken: id };
},
onApprove: async (data) => {
console.log("Saved:", data.vaultSetupToken);
},
presentationMode: "auto",
});
if (isPending) return null;
if (error) return <div>Error: {error.message}</div>;
return <paypal-button onClick={handleClick} type="pay" />;
}usePayPalCreditSavePaymentSessionThe following example saves a PayPal Credit payment method to the vault and passes the buyer's countryCode from eligibility data to the credit button.
import {
usePayPalCreditSavePaymentSession,
usePayPal,
} from "@paypal/react-paypal-js/sdk-v6";
function CustomCreditSaveButton() {
const { eligiblePaymentMethods } = usePayPal();
const { isPending, error, handleClick } = usePayPalCreditSavePaymentSession({
createVaultToken: async () => {
const res = await fetch("/api/vault-setup-token", { method: "POST" });
const { id } = await res.json();
return { vaultSetupToken: id };
},
onApprove: async (data) => {
console.log("Saved:", data.vaultSetupToken);
},
presentationMode: "auto",
});
const creditDetails = eligiblePaymentMethods?.getDetails?.("credit");
if (isPending) return null;
if (error) return <div>Error: {error.message}</div>;
return (
<paypal-credit-button
onClick={handleClick}
countryCode={creditDetails?.countryCode}
/>
);
}usePayPalSubscriptionPaymentSessionThe following example creates a subscription on your server and renders a custom subscribe button that starts the subscription flow when selected.
import { usePayPalSubscriptionPaymentSession } from "@paypal/react-paypal-js/sdk-v6";
function CustomSubscriptionButton() {
const { isPending, error, handleClick } = usePayPalSubscriptionPaymentSession(
{
createSubscription: async () => {
const res = await fetch("/api/subscriptions", { method: "POST" });
const { id } = await res.json();
return { subscriptionId: id };
},
onApprove: async (data) => {
console.log("Subscription approved:", data.payerId);
},
presentationMode: "auto",
},
);
if (isPending) return null;
if (error) return <div>Error: {error.message}</div>;
return <paypal-button onClick={handleClick} type="subscribe" />;
}useApplePayOneTimePaymentSessionThe following example configures an Apple Pay session with a payment request and renders a native Apple Pay button.
import { useApplePayOneTimePaymentSession } from "@paypal/react-paypal-js/sdk-v6";
function CustomApplePayButton({ applePayConfig }) {
const { isPending, error, handleClick } = useApplePayOneTimePaymentSession({
applePayConfig,
paymentRequest: {
countryCode: "US",
currencyCode: "USD",
total: { label: "Demo Store", amount: "100.00", type: "final" },
},
applePaySessionVersion: 4,
createOrder: async () => {
const res = await fetch("/api/orders", { method: "POST" });
const { id } = await res.json();
return { orderId: id };
},
onApprove: (data) => console.log("Approved:", data),
onError: (err) => console.error(err),
});
if (isPending) return null;
if (error) return <div>Error: {error.message}</div>;
return (
<apple-pay-button onClick={handleClick} buttonstyle="black" type="pay" />
);
}The following components render PayPal payment buttons in your React app. Each component wraps a specific payment flow and accepts callback props to handle the payment lifecycle.
PayPalOneTimePaymentButton renders a button for one-time PayPal payments. It uses usePayPalOneTimePaymentSession internally.
The following example renders a PayPal button that creates an order on your server and handles approval when the buyer completes payment.
import {
PayPalOneTimePaymentButton,
type OnApproveDataOneTimePayments,
} from "@paypal/react-paypal-js/sdk-v6";
function Checkout() {
const handleCreateOrder = async () => {
const response = await fetch("/api/orders", { method: "POST" });
const { id } = await response.json();
return { orderId: id };
};
return (
<PayPalOneTimePaymentButton
createOrder={handleCreateOrder}
onApprove={async (data: OnApproveDataOneTimePayments) => {
console.log("Order approved:", data.orderId);
}}
presentationMode="auto"
/>
);
}VenmoOneTimePaymentButton renders a button for one-time Venmo payments (US only). It uses useVenmoOneTimePaymentSession internally.
VenmoOneTimePaymentButton accepts the same props as PayPalOneTimePaymentButton.
The following example renders a Venmo payment button with order creation and approval callbacks.
import { VenmoOneTimePaymentButton } from "@paypal/react-paypal-js/sdk-v6";
<VenmoOneTimePaymentButton
createOrder={handleCreateOrder}
onApprove={handleApprove}
presentationMode="auto"
/>;PayLaterOneTimePaymentButton renders a button for the Pay Later payment option (Pay in 4, financing). It requires useEligibleMethods to fetch eligibility data, which provides the countryCode and productCode needed for the button.
The following example renders a Pay Later button that lets buyers choose financing options like Pay in 4.
import {
PayLaterOneTimePaymentButton,
useEligibleMethods,
} from "@paypal/react-paypal-js/sdk-v6";
function PayLaterCheckout() {
const { error, isLoading } = useEligibleMethods();
return (
!error &&
!isLoading && (
<PayLaterOneTimePaymentButton
createOrder={handleCreateOrder}
onApprove={handleApprove}
presentationMode="auto"
/>
)
);
}PayPalCreditOneTimePaymentButton renders a button for PayPal Credit one-time payments. It requires useEligibleMethods to fetch eligibility data, which provides the countryCode needed for the button.
The following example checks eligibility before rendering a PayPal Credit button for one-time payments.
import {
PayPalCreditOneTimePaymentButton,
useEligibleMethods,
} from "@paypal/react-paypal-js/sdk-v6";
function CreditCheckout() {
const { error, isLoading } = useEligibleMethods();
return (
!error &&
!isLoading && (
<PayPalCreditOneTimePaymentButton
createOrder={handleCreateOrder}
onApprove={handleApprove}
presentationMode="auto"
/>
)
);
}PayPalGuestPaymentButton renders a button for guest checkout that does not require a PayPal account. It automatically wraps the button with <paypal-basic-card-container>.
This component does not accept presentationMode. It renders a <paypal-basic-card-button> inside a <paypal-basic-card-container> automatically.
| Prop | Type | Description |
|---|---|---|
createOrder | () => Promise<{ orderId: string }> | Function that calls your server to create a PayPal order and returns the
resulting |
orderId | string | Order ID for an order you already created on your server. Use this when
your app creates the order before rendering the button. Use either
|
onApprove | | Callback when payment is approved |
onCancel | (data: OnCancelDataOneTimePayments) => void | Callback when user cancels |
onError | (data: OnErrorData) => void | Callback on payment error |
onComplete | (data: OnCompleteData) => void | Callback when payment session completes |
fullPageOverlay | { enabled: boolean } | Whether to show a full-page overlay |
onShippingAddressChange | | Callback when shipping address changes |
onShippingOptionsChange | | Callback when shipping options change |
disabled | boolean | Whether the button is disabled |
The following example renders a guest checkout button that allows buyers to pay without a PayPal account.
import { PayPalGuestPaymentButton } from "@paypal/react-paypal-js/sdk-v6";
<PayPalGuestPaymentButton
createOrder={handleCreateOrder}
onApprove={handleApprove}
/>;PayPalSavePaymentButton renders a button that saves payment methods to a vault.
The following example creates a vault setup token on your server and renders a button that saves the buyer's payment method.
import {
PayPalSavePaymentButton,
type OnApproveDataSavePayments,
} from "@paypal/react-paypal-js/sdk-v6";
function SavePayment() {
const handleCreateVaultToken = async () => {
const response = await fetch("/api/vault-setup-token", { method: "POST" });
const { id } = await response.json();
return { vaultSetupToken: id };
};
return (
<PayPalSavePaymentButton
createVaultToken={handleCreateVaultToken}
onApprove={(data: OnApproveDataSavePayments) => {
console.log("Payment saved with token:", data.vaultSetupToken);
}}
presentationMode="auto"
/>
);
}PayPalCreditSavePaymentButton renders a button that saves PayPal Credit payment methods. It requires useEligibleMethods to fetch eligibility data, which provides the countryCode needed for the button.
The following example checks eligibility before rendering a button that saves a PayPal Credit payment method to the vault.
import {
PayPalCreditSavePaymentButton,
useEligibleMethods,
} from "@paypal/react-paypal-js/sdk-v6";
function CreditSavePayment() {
const { error, isLoading } = useEligibleMethods();
return (
!error &&
!isLoading && (
<PayPalCreditSavePaymentButton
createVaultToken={handleCreateVaultToken}
onApprove={handleApprove}
presentationMode="auto"
/>
)
);
}PayPalSubscriptionButton renders a button that creates subscriptions.
Subscriptions only support "auto", "popup", "modal", or
"payment-handler" presentation modes.
| Prop | Type | Description |
|---|---|---|
createSubscription | | Function that creates a subscription and returns an object with
|
onApprove | | Callback when subscription is approved. Receives
|
onCancel | (data: OnCancelDataOneTimePayments) => void | Callback when user cancels |
onError | (data: OnErrorData) => void | Callback on error |
onComplete | (data: OnCompleteData) => void | Callback when session completes |
presentationMode | string | string. Controls how the payment interface is displayed to the buyer. Available modes:
Default: The SDK will automatically fall back to alternative modes if the requested mode is unavailable. |
type | string | Button type. Defaults to |
disabled | boolean | Whether the button is disabled |
The following example creates a subscription on your server and renders a button that starts the subscription approval flow.
import {
PayPalSubscriptionButton,
type OnApproveDataSubscriptions,
} from "@paypal/react-paypal-js/sdk-v6";
function Subscription() {
const handleCreateSubscription = async () => {
const response = await fetch("/api/subscriptions", { method: "POST" });
const { id } = await response.json();
return { subscriptionId: id };
};
return (
<PayPalSubscriptionButton
createSubscription={handleCreateSubscription}
onApprove={(data: OnApproveDataSubscriptions) => {
console.log("Subscription ID:", data.subscriptionId);
}}
presentationMode="auto"
/>
);
}ApplePayOneTimePaymentButton renders a native <apple-pay-button> element for Apple Pay payments with Safari-compatible styling.
| Prop | Type | Description |
|---|---|---|
applePayConfig | ApplePayConfig | Apple Pay configuration from |
paymentRequest | ApplePayPaymentRequest | Payment request with country, currency, and total |
applePaySessionVersion | number | Apple Pay JS API version (4 or later) |
createOrder | () => Promise<{ orderId: string }> | Function that creates an order |
onApprove | (data: ConfirmOrderResponse) => void | Callback when payment is approved |
onCancel | () => void | Callback when payment is cancelled |
onError | (error: Error) => void | Callback on error |
displayName | string | Merchant display name |
domainName | string | Merchant domain name |
buttonstyle | string | Button style, for example, |
type | string | Button type, for example, |
locale | string | Locale, such as |
disabled | boolean | Whether the button is disabled |
The following example renders an Apple Pay button configured with a payment request and order creation callback.
import { ApplePayOneTimePaymentButton } from "@paypal/react-paypal-js/sdk-v6";
<ApplePayOneTimePaymentButton
applePayConfig={applePayConfig}
paymentRequest={{
countryCode: "US",
currencyCode: "USD",
total: { label: "Demo Store", amount: "100.00", type: "final" },
}}
applePaySessionVersion={4}
createOrder={async () => {
const res = await fetch("/api/orders", { method: "POST" });
const data = await res.json();
return { orderId: data.id };
}}
onApprove={(data) => console.log("Approved:", data)}
onError={(err) => console.error(err)}
/>;Card fields let you render individual, PCI-compliant input fields for card number, expiration, and CVV within your checkout form.
PayPalCardFieldsProvider creates a Card Fields session and provides it to child field components. Only the children prop is required. All other props are optional and can be used to configure the session and listen to field events.
| Prop | Type | Description |
|---|---|---|
| ReactNode | Child components |
amount | { value?: string, currencyCode?: string } | Order amount, which you can update dynamically |
isCobrandedEligible | boolean | Whether co-branded card eligibility is enabled |
blur | (event) => void | Callback when a card field loses focus |
validitychange | (event) => void | Callback when field validity changes |
cardtypechange | (event) => void | Callback when card type changes or is detected |
focus | (event) => void | Callback when a card field gains focus |
change | (event) => void | Callback when card field value changes |
empty | (event) => void | Callback when a card field is empty |
inputsubmit | (event) => void | Callback when a card field is submitted |
notempty | (event) => void | Callback when a card field is not empty |
The following example renders card number, expiry, and CVV fields inside a provider that listens for validity and card type changes.
import {
PayPalCardFieldsProvider,
PayPalCardNumberField,
PayPalCardExpiryField,
PayPalCardCvvField,
} from "@paypal/react-paypal-js/sdk-v6";
function CardFieldsCheckout() {
return (
<PayPalCardFieldsProvider
amount={{ value: "10.00", currencyCode: "USD" }}
validitychange={(event) => console.log("Validity change event:", event)}
cardtypechange={(event) => console.log("Card type change event:", event)}
>
<PayPalCardNumberField placeholder="Card number" />
<PayPalCardExpiryField placeholder="MM/YY" />
<PayPalCardCvvField placeholder="CVV" />
<SubmitButton />
</PayPalCardFieldsProvider>
);
}PayPalCardNumberField renders a card number input field. Use within a PayPalCardFieldsProvider. All props are optional.
PayPalCardExpiryField renders a card expiry input field. Use within a PayPalCardFieldsProvider. All props are optional.
PayPalCardCvvField renders a CVV input field. Use within a PayPalCardFieldsProvider. All props are optional.
usePayPalCardFields()usePayPalCardFields returns the Card Fields state from the PayPalCardFieldsProvider context. Use within a PayPalCardFieldsProvider.
usePayPalCardFieldsOneTimePaymentSession()usePayPalCardFieldsOneTimePaymentSession submits card field data for one-time payments.
| Property | Type | Description |
|---|---|---|
submit | | Submit the card fields for payment |
submitResponse | object | null | The response from the submit operation |
error | Error | null | Any error that occurred |
The following example renders styled card fields, submits the card data for a one-time payment, and handles both success and failure responses.
import {
PayPalCardCvvField,
PayPalCardExpiryField,
PayPalCardNumberField,
usePayPalCardFields,
usePayPalCardFieldsOneTimePaymentSession,
} from "@paypal/react-paypal-js/sdk-v6";
import { useEffect } from "react";
import { captureOrder } from "../../../utils";
const PayPalCardFieldsOneTimePayment = () => {
const { error: cardFieldsError } = usePayPalCardFields();
const {
error: submitError,
submit,
submitResponse,
} = usePayPalCardFieldsOneTimePaymentSession();
useEffect(() => {
if (!submitResponse) {
return;
}
const { orderId, message } = submitResponse.data;
switch (submitResponse.state) {
case "succeeded":
console.log(`One time payment succeeded: orderId: ${orderId}`);
captureOrder({ orderId }).then((captureResult) => {
console.log("Payment capture result:", captureResult);
});
break;
case "failed":
console.error(
`One time payment failed: orderId: ${orderId}, message: ${message}`,
);
break;
}
}, [submitResponse]);
useEffect(() => {
if (cardFieldsError) {
console.error("Error loading PayPal Card Fields", cardFieldsError);
}
if (submitError) {
console.error("Error submitting PayPal Card Fields payment", submitError);
}
}, [cardFieldsError, submitError]);
const handleSubmit = async () => {
const { orderId } = await handleCreateOrder();
await submit(orderId);
};
return (
<div>
<div
style={{
display: "flex",
flexDirection: "column",
gap: "1rem",
}}
>
<PayPalCardNumberField
containerStyles={{
height: "3rem",
}}
placeholder="Enter card number"
/>
<PayPalCardExpiryField
containerStyles={{
height: "3rem",
}}
placeholder="MM/YY"
/>
<PayPalCardCvvField
containerStyles={{
height: "3rem",
}}
placeholder="Enter CVV"
/>
</div>
{!cardFieldsError && (
<button className="card-fields-pay-button" onClick={handleSubmit}>
Pay
</button>
)}
</div>
);
};
export default PayPalCardFieldsOneTimePayment;usePayPalCardFieldsSavePaymentSession()usePayPalCardFieldsSavePaymentSession submits card field data to save a payment method.
| Property | Type | Description |
|---|---|---|
submit | | Submit the card fields for vaulting |
submitResponse | object | null | The response from the submit operation |
error | Error | null | Any error that occurred |
The following example renders card fields and submits the card data to save it as a vaulted payment method.
import {
PayPalCardCvvField,
PayPalCardExpiryField,
PayPalCardNumberField,
usePayPalCardFields,
usePayPalCardFieldsSavePaymentSession,
} from "@paypal/react-paypal-js/sdk-v6";
import { useEffect } from "react";
import { createCardVaultToken } from "../../../utils";
const PayPalCardFieldsSavePayment = () => {
const { error: cardFieldsError } = usePayPalCardFields();
const {
error: submitError,
submit,
submitResponse,
} = usePayPalCardFieldsSavePaymentSession();
useEffect(() => {
if (!submitResponse) {
return;
}
const { vaultSetupToken, message } = submitResponse.data;
switch (submitResponse.state) {
case "succeeded":
console.log(
`Save payment method succeeded: vaultSetupToken: ${vaultSetupToken}`,
);
break;
case "failed":
console.error(
`Save payment method failed: vaultSetupToken: ${vaultSetupToken}, message: ${message}`,
);
break;
}
}, [submitResponse]);
useEffect(() => {
if (cardFieldsError) {
console.error("Error loading PayPal Card Fields", cardFieldsError);
}
if (submitError) {
console.error("Error submitting PayPal Card Fields payment", submitError);
}
}, [cardFieldsError, submitError]);
const handleSubmit = async () => {
const { vaultSetupToken } = await createCardVaultToken();
await submit(vaultSetupToken);
};
return (
<div>
<div
style={{
display: "flex",
flexDirection: "column",
gap: "1rem",
}}
>
<PayPalCardNumberField
containerStyles={{
height: "3rem",
}}
placeholder="Enter card number"
/>
<PayPalCardExpiryField
containerStyles={{
height: "3rem",
}}
placeholder="MM/YY"
/>
<PayPalCardCvvField
containerStyles={{
height: "3rem",
}}
placeholder="Enter CVV"
/>
</div>
{!cardFieldsError && (
<button className="card-fields-pay-button" onClick={handleSubmit}>
Save Payment Method
</button>
)}
</div>
);
};
export default PayPalCardFieldsSavePayment;useFetchEligibleMethods(options)useFetchEligibleMethods pre-fetches eligible payment methods on the server. Import from @paypal/react-paypal-js/sdk-v6/server.
| Parameter | Required | Description |
|---|---|---|
options.headers | no | HeadersInit. HTTP headers including the
|
options.environment | yes | string. Target environment ( |
options.payload | no | object. Optional request payload with customer and purchase details |
options.signal | no | AbortSignal. Optional abort signal |
The following example pre-fetches eligible payment methods on the server and passes the result to PayPalProvider.
import { useFetchEligibleMethods } from "@paypal/react-paypal-js/sdk-v6/server";
// In a server component or loader
const eligibleMethodsResponse = await useFetchEligibleMethods({
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${clientToken}`,
},
environment: "sandbox",
payload: {
purchase_units: [{ amount: { currency_code: "USD", value: "100.00" } }],
},
});
// Pass to provider
<PayPalProvider
eligibleMethodsResponse={eligibleMethodsResponse}
clientToken={token}
pageType="checkout"
>
<Checkout />
</PayPalProvider>;type FindEligiblePaymentMethodsRequestPayload = {
customer?: {
channel?: {
browser_type?: string;
client_os?: string;
device_type?: string;
};
country_code?: string;
id?: string;
email?: string;
phone?: PhoneNumber;
};
purchase_units?: ReadonlyArray<{
amount: {
currency_code: string;
value?: string;
};
payee?: {
client_id?: string;
display_data?: {
business_email?: string;
business_phone?: PhoneNumber & {
extension_number: string;
};
brand_name?: string;
};
email_address?: string;
merchant_id?: string;
};
}>;
preferences?: {
// runs advanced customer eligibility checks when set to true
include_account_details?: boolean;
include_vault_tokens?: boolean;
payment_flow?: PaymentFlow;
payment_source_constraint?: {
constraint_type: string;
payment_sources: Uppercase<EligiblePaymentMethods>[];
};
};
shopper_session_id?: string;
};The following types define the data structures passed to and from SDK callbacks.
Data passed to onApprove for one-time payments.
| Property | Type | Description |
|---|---|---|
orderId | string | The PayPal order ID |
payerId |
| The PayPal payer ID |
billingToken |
| The billing token |
Data passed to onApprove for subscription payments.
| Property | Type | Description |
|---|---|---|
subscriptionId | string | The PayPal subscription ID |
payerId |
| The PayPal payer ID |
Data passed to onApprove for save payment operations.
| Property | Type | Description |
|---|---|---|
vaultSetupToken | string | Token representing the saved payment method |
payerId |
| The PayPal payer ID |
Data passed to onCancel for one-time payments.
| Property | Type | Description |
|---|---|---|
orderId |
| The PayPal order ID |
Data passed to onCancel for save payment operations.
| Property | Type | Description |
|---|---|---|
vaultSetupToken |
| The vault setup token |
Data passed to onError when an error occurs. Extends Error.
| Property | Type | Description |
|---|---|---|
code | string | Error code |
name | string | Error name |
message | string | Error message |
isRecoverable | boolean | Whether the error is recoverable |
Data passed to onComplete when payment session completes.
| Property | Type | Description |
|---|---|---|
paymentSessionState | string | Session result. Values are |
Return type for all payment session hooks.
| Property | Type | Description |
|---|---|---|
error | Error | null | Any session error |
isPending | boolean | Whether the SDK instance is still loading |
handleClick | | Starts the payment session |
handleCancel | () => void | Cancels the session |
handleDestroy | () => void | Cleans up the session |
Data passed to Card Fields event callbacks such as blur, focus, change, and validitychange.
| Property | Type | Description |
|---|---|---|
data | EventState | The state of the card fields when the event was triggered |
sender | CardFieldTypes | The card field that triggered the event: |
The state of all card fields at the time an event is triggered.
| Property | Type | Description |
|---|---|---|
cards | Card[] | Detected card types based on the current card number input |
emittedBy | CardFieldTypes | The card field that emitted the event: |
number | FieldState | State of the card number field |
cvv | FieldState | State of the CVV field |
expiry | FieldState | State of the expiry field |
The state of an individual card field.
| Property | Type | Description |
|---|---|---|
isFocused | boolean | Whether the field currently has focus |
isValid | boolean | Whether the field value is valid |
isEmpty | boolean | Whether the field is empty |
isPotentiallyValid | boolean | Whether the field value could become valid with additional input |
Represents a detected card type based on the current card number input.
| Property | Type | Description |
|---|---|---|
niceType | string | Human-readable card name, for example, |
type | string | Machine-readable card type, for example, |
code.name | string | Security code label for the card type, for example, |
code.size | number | Expected length of the security code, for example, |
Enum for SDK loading states. Use with usePayPal() to check SDK readiness.
| Value | Description |
|---|---|
INSTANCE_LOADING_STATE.PENDING | SDK is loading |
INSTANCE_LOADING_STATE.RESOLVED | SDK loaded successfully |
INSTANCE_LOADING_STATE.REJECTED | SDK failed to load |
The following example checks the SDK loading state and renders different UI for each state.
import {
INSTANCE_LOADING_STATE,
usePayPal,
} from "@paypal/react-paypal-js/sdk-v6";
function Component() {
const { loadingStatus } = usePayPal();
if (loadingStatus === INSTANCE_LOADING_STATE.PENDING) {
return <div>Loading...</div>;
}
if (loadingStatus === INSTANCE_LOADING_STATE.REJECTED) {
return <div>Failed to load PayPal SDK</div>;
}
return <div>Ready to process payments</div>;
}The following examples cover common integration patterns for error handling, eligibility checks, and conditional rendering.
The following example shows how to capture error details, log them, and conditionally prompt a retry if the error is recoverable.
import {
PayPalOneTimePaymentButton,
type OnErrorData,
} from "@paypal/react-paypal-js/sdk-v6";
function Payment() {
const handleError = (error: OnErrorData) => {
console.error("Payment failed:", error.message);
if (error.isRecoverable) {
// Prompt user to retry
}
};
return (
<PayPalOneTimePaymentButton
createOrder={createOrder}
onApprove={handleApprove}
onError={handleError}
presentationMode="auto"
/>
);
}The following example checks payment method availability for the current user and conditionally renders payment buttons based on eligibility.
import { useEligibleMethods } from "@paypal/react-paypal-js/sdk-v6";
function CheckoutFlow() {
const { eligiblePaymentMethods, isLoading } = useEligibleMethods();
if (isLoading) return <div>Loading...</div>;
return (
<>
<PayPalOneTimePaymentButton {...props} />
{eligiblePaymentMethods?.isEligible("venmo") && (
<VenmoOneTimePaymentButton {...props} />
)}
{eligiblePaymentMethods?.isEligible("paylater") && (
<PayLaterOneTimePaymentButton {...props} />
)}
</>
);
}The following example renders loading indicators while the PayPal SDK initializes and displays payment components only when ready.
function Checkout() {
const { loadingStatus } = usePayPal();
const isLoading = loadingStatus === INSTANCE_LOADING_STATE.PENDING;
return isLoading ? (
<div>Initializing payment methods...</div>
) : (
<PaymentButtons />
);
}All one-time payment buttons support passing a pre-created orderId directly instead of a createOrder callback.
<PayPalOneTimePaymentButton
orderId="ORDER-123"
onApprove={handleApprove}
presentationMode="auto"
/>Save payment buttons support passing a pre-created vaultSetupToken directly.
<PayPalSavePaymentButton
vaultSetupToken="VAULT-TOKEN-123"
onApprove={handleApprove}
presentationMode="auto"
/>