From 008e0b4e0f964e09d20029fe5c02e2176c52674c Mon Sep 17 00:00:00 2001 From: Alejandro Gastelum Flores Date: Wed, 11 Mar 2026 11:35:51 -0700 Subject: [PATCH 1/6] Updated React README to include Card Fields. Also updated a few sections to match current repository state --- client/prebuiltPages/react/README.md | 193 +++++++++++++++++++-------- 1 file changed, 136 insertions(+), 57 deletions(-) diff --git a/client/prebuiltPages/react/README.md b/client/prebuiltPages/react/README.md index 62c69090..86e97e30 100644 --- a/client/prebuiltPages/react/README.md +++ b/client/prebuiltPages/react/README.md @@ -25,6 +25,7 @@ Browse all available examples at the [Examples Index](https://v6-web-sdk-sample- - **Venmo** - Standard Venmo Payments - **Pay Later** - PayPal's buy now, pay later option - **PayPal Basic Card** - Guest card payments without a PayPal account +- **PayPal Advanced Card** - Card payments with enhanced features and customization options - **PayPal Subscriptions** - Recurring billing subscriptions - **PayPal Save** - Vault payment methods without purchase - **PayPal Credit** - PayPal Credit one-time and save payments @@ -73,83 +74,87 @@ The Vite dev server proxies `/paypal-api` requests to the backend server on port ## Application Routes -| Route | Description | -| ---------------------------- | --------------------------------------- | -| `/` | Home page with navigation | -| `/one-time-payment` | One-Time Payment product page | -| `/one-time-payment/cart` | One-Time Payment cart page | -| `/one-time-payment/checkout` | One-Time Payment checkout page | -| `/one-time-payment/error` | One-Time Payment error boundary demo | -| `/save-payment` | Save Payment product page | -| `/save-payment/cart` | Save Payment cart page | -| `/save-payment/checkout` | Save Payment checkout page | -| `/save-payment/error` | Save Payment error boundary demo | -| `/subscription` | Subscription product page | -| `/subscription/cart` | Subscription cart page | -| `/subscription/checkout` | Subscription checkout page | -| `/subscription/error` | Subscription error boundary demo | -| `/error-boundary-test` | Standalone error handling demonstration | +| Route | Description | +| --------------------------------------- | --------------------------------------------------- | +| `/` | Home page with navigation | +| `/one-time-payment` | One-Time Payment product page | +| `/one-time-payment/cart` | One-Time Payment cart page | +| `/one-time-payment/checkout` | One-Time Payment checkout page | +| `/one-time-payment/error` | One-Time Payment error boundary demo | +| `/one-time-payment/card-fields` | One-Time Payment with Card Fields product page | +| `/one-time-payment/card-fields/cart` | One-Time Payment with Card Fields cart page | +| `/one-time-payment/card-fields/checkout`| One-Time Payment with Card Fields checkout page | +| `/vault-with-purchase` | Vault with Purchase product page | +| `/vault-with-purchase/cart` | Vault with Purchase cart page | +| `/vault-with-purchase/checkout` | Vault with Purchase checkout page | +| `/vault-with-purchase/error` | Vault with Purchase error boundary demo | +| `/save-payment` | Save Payment product page | +| `/save-payment/card-fields` | Save Payment with Card Fields product page | +| `/subscription` | Subscription product page | +| `/subscription/cart` | Subscription cart page | +| `/subscription/checkout` | Subscription checkout page | +| `/subscription/error` | Subscription error boundary demo | +| `/paypal-messages` | PayPal Messages demo page | +| `/error-boundary-test` | Standalone error handling demonstration | ## Project Structure ``` react/ ├── src/ -│ ├── App.tsx # Main app with routing and PayPalProvider -│ ├── main.tsx # React entry point -│ ├── utils.ts # Shared utilities for all payment flows +│ ├── App.tsx # Main app with routing and PayPalProvider +│ ├── main.tsx # React entry point +│ ├── utils.ts # Shared utilities for all payment flows │ ├── types/ -│ │ └── index.ts # Shared TypeScript interfaces +│ │ └── index.ts # Shared TypeScript interfaces │ ├── constants/ -│ │ └── products.ts # Client product catalog -│ ├── hooks/ # Custom React hooks for code reuse -│ │ ├── useCartTotals.ts # Hook for cart calculations (totalItems, total) -│ │ ├── useProducts.ts # Hook for loading products with prices from server -│ │ └── useQuantityChange.ts # Hook for handling product quantity updates -│ ├── pages/ # Base components (shared across flows) -│ │ ├── Home.tsx # Landing page with navigation -│ │ ├── BaseProduct.tsx # Base product selection page -│ │ ├── BaseCart.tsx # Base shopping cart page -│ │ ├── BaseCheckout.tsx # Base checkout page -│ │ ├── BaseStaticButtons.tsx # Base static buttons demo page -│ │ └── ErrorBoundary.tsx # Error handling demo page -│ ├── components/ # Shared UI components -│ │ ├── ProductDisplay.tsx # Product grid display -│ │ ├── PaymentModal.tsx # Success/error modal -│ │ ├── ErrorBoundary.tsx # Error boundary component -│ │ └── ErrorTest.tsx # Error test component -│ ├── styles/ # Shared CSS +│ │ └── products.ts # Client product catalog +│ ├── hooks/ # Custom React hooks for code reuse +│ │ ├── useCartTotals.ts # Hook for cart calculations (totalItems, total) +│ │ ├── useProducts.ts # Hook for loading products with prices from server +│ │ └── useQuantityChange.ts # Hook for handling product quantity updates +│ ├── pages/ # Base components (shared across flows) +│ │ ├── Home.tsx # Landing page with navigation +│ │ ├── BaseProduct.tsx # Base product selection page +│ │ ├── BaseCart.tsx # Base shopping cart page +│ │ ├── BaseCheckout.tsx # Base checkout page +│ │ ├── BaseCardFieldsCheckout.tsx # Base checkout page for Card Fields +│ │ ├── BaseStaticButtons.tsx # Base static buttons demo page +│ │ ├── SavePaymentSettings.tsx # Save Payment page +│ │ ├── CardFieldsSavePaymentSettings.tsx # Save Payment with Card Fields page +│ │ └── ErrorBoundary.tsx # Error handling demo page +│ ├── components/ # Shared UI components +│ │ ├── ProductDisplay.tsx # Product grid display +│ │ ├── PaymentModal.tsx # Success/error modal +│ │ ├── ErrorBoundary.tsx # Error boundary component +│ │ └── ErrorTest.tsx # Error test component +│ ├── styles/ # Shared CSS │ │ ├── Cart.css │ │ ├── Checkout.css │ │ ├── Modal.css │ │ ├── Product.css │ │ └── StaticButtons.css -│ ├── images/ # Product images +│ ├── images/ # Product images │ │ ├── world-cup.jpg │ │ ├── basket-ball.jpeg │ │ ├── base-ball.jpeg │ │ └── hockey-puck.jpeg -│ └── payments/ # Flow-specific implementations +│ ├── paymentFlowCheckoutPages/ # Flow-specific checkout implementations +│ │ ├── OneTimePaymentCheckout.tsx +│ │ ├── CardFieldsOneTimePaymentCheckout.tsx +│ │ ├── VaultWithPurchaseCheckout.tsx +│ │ └── SubscriptionCheckout.tsx +│ ├── paypalMessages/ # PayPal Messages integration +│ │ ├── PayPalMessagesDemo.tsx +│ │ └── PayPalMessages.tsx +│ └── payments/ # Payment method-specific components │ ├── oneTimePayment/ -│ │ ├── pages/ -│ │ │ ├── Checkout.tsx # Uses useEligibleMethods with ONE_TIME_PAYMENT -│ │ │ └── StaticButtons.tsx │ │ └── components/ -│ │ └── PayPalCreditOneTimeButton.tsx -│ ├── savePayment/ -│ │ ├── pages/ -│ │ │ ├── Checkout.tsx -│ │ │ └── StaticButtons.tsx -│ │ └── components/ -│ │ └── PayPalCreditSaveButton.tsx -│ └── subscription/ -│ ├── pages/ -│ │ ├── Checkout.tsx -│ │ └── StaticButtons.tsx +│ │ └── PayPalCardFieldsOneTimePayment.tsx +│ └── savePayment/ │ └── components/ -│ └── PayPalSubscriptionButton.tsx -├── index.html -├── vite.config.ts # Vite config with proxy settings +│ └── PayPalCardFieldsSavePayment.tsx +├── vite.config.ts # Vite config with proxy settings ├── package.json └── tsconfig.json ``` @@ -174,6 +179,7 @@ react/ "venmo-payments", "paypal-guest-payments", "paypal-subscriptions", + "card-fields", ]} pageType="checkout" > @@ -187,6 +193,7 @@ The `components` prop specifies which payment methods to load: - `venmo-payments` - Venmo button - `paypal-guest-payments` - Guest card payment button - `paypal-subscriptions` - Subscription buttons +- `card-fields` - Advanced card payment fields ### 2. Eligibility @@ -282,6 +289,66 @@ const PayPalButton = (props: UsePayPalOneTimePaymentSessionProps) => { }; ``` +### 3.1 Payment Session Hooks - Card Fields + +Card Fields provides specialized hooks to create payment sessions that work seamlessly with individual card field components: + +| Hook | Use Case | +| ------------------------------------------------- | -------------------- | +| `usePayPalCardFieldsOneTimePaymentSession` | One-time payments | +| `usePayPalCardFieldsSavePaymentSession` | Save payment methods | + +**Example Usage:** + +```tsx +import { + PayPalCardNumberField, + PayPalCardExpiryField, + PayPalCardCvvField, + usePayPalCardFieldsOneTimePaymentSession, +} from "@paypal/react-paypal-js/sdk-v6"; +import { useEffect } from "react"; + +const CardFieldsPayment = () => { + const { submit, submitResponse } = usePayPalCardFieldsOneTimePaymentSession(); + + const handleCreateOrder = async () => { + return await createOrder(); + }; + + const handleSubmit = async () => { + const { orderId } = await handleCreateOrder(); + await submit(orderId); + }; + + useEffect(() => { + if (!submitResponse) { + return; + } + + const { orderId, state } = submitResponse.data; + + switch(state) { + case "succeeded": + captureOrder({ orderId }); + break; + case "failed": + console.error(`One time payment failed: orderId: ${orderId}, message: ${message}`); + break; + } + }, [submitResponse]); + + return ( + <> + + + + + + ); +}; +``` + ### 4. Payment Flow 1. User clicks a payment button @@ -291,6 +358,15 @@ const PayPalButton = (props: UsePayPalOneTimePaymentSessionProps) => { 5. On approval, `onApprove` callback captures the order via the backend 6. Success/error modal displays the result +### 4.1 Payment Flow - Card Fields + +1. Customer enters card information directly into the Card Fields components +2. User clicks the submit button +3. `createOrder` creates an order via the backend API +4. `submit(orderId)` processes the card payment with the order ID +5. `submitResponse` callback provides the payment result +6. Handle submit response based on payment result + ## Backend Server The Node.js backend handles sensitive PayPal API interactions. @@ -385,6 +461,7 @@ The Node.js backend handles sensitive PayPal API interactions. import { PayPalProvider } from "@paypal/react-paypal-js/sdk-v6"; import { usePayPal, + usePayPalCardFields, usePayPalOneTimePaymentSession, useVenmoOneTimePaymentSession, usePayLaterOneTimePaymentSession, @@ -393,6 +470,8 @@ import { usePayPalSavePaymentSession, usePayPalCreditOneTimePaymentSession, usePayPalCreditSavePaymentSession, + usePayPalCardFieldsOneTimePaymentSession, + usePayPalCardFieldsSavePaymentSession, } from "@paypal/react-paypal-js/sdk-v6"; // Loading state constants From 9d8468e796b0d58f98172147028e3246b1c18955 Mon Sep 17 00:00:00 2001 From: Alejandro Gastelum Flores Date: Wed, 11 Mar 2026 11:47:37 -0700 Subject: [PATCH 2/6] Added missing index.html file in Project Structure section --- client/prebuiltPages/react/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/client/prebuiltPages/react/README.md b/client/prebuiltPages/react/README.md index 86e97e30..741ec614 100644 --- a/client/prebuiltPages/react/README.md +++ b/client/prebuiltPages/react/README.md @@ -154,6 +154,7 @@ react/ │ └── savePayment/ │ └── components/ │ └── PayPalCardFieldsSavePayment.tsx +├── index.html ├── vite.config.ts # Vite config with proxy settings ├── package.json └── tsconfig.json From c358f3a39d3d02b3c75d7aa7a911e111e771bc9b Mon Sep 17 00:00:00 2001 From: Alejandro Gastelum Flores Date: Wed, 11 Mar 2026 11:49:53 -0700 Subject: [PATCH 3/6] Updated with prettier fixes --- client/prebuiltPages/react/README.md | 60 ++++++++++++++-------------- 1 file changed, 31 insertions(+), 29 deletions(-) diff --git a/client/prebuiltPages/react/README.md b/client/prebuiltPages/react/README.md index 741ec614..ba1ffba0 100644 --- a/client/prebuiltPages/react/README.md +++ b/client/prebuiltPages/react/README.md @@ -74,28 +74,28 @@ The Vite dev server proxies `/paypal-api` requests to the backend server on port ## Application Routes -| Route | Description | -| --------------------------------------- | --------------------------------------------------- | -| `/` | Home page with navigation | -| `/one-time-payment` | One-Time Payment product page | -| `/one-time-payment/cart` | One-Time Payment cart page | -| `/one-time-payment/checkout` | One-Time Payment checkout page | -| `/one-time-payment/error` | One-Time Payment error boundary demo | -| `/one-time-payment/card-fields` | One-Time Payment with Card Fields product page | -| `/one-time-payment/card-fields/cart` | One-Time Payment with Card Fields cart page | -| `/one-time-payment/card-fields/checkout`| One-Time Payment with Card Fields checkout page | -| `/vault-with-purchase` | Vault with Purchase product page | -| `/vault-with-purchase/cart` | Vault with Purchase cart page | -| `/vault-with-purchase/checkout` | Vault with Purchase checkout page | -| `/vault-with-purchase/error` | Vault with Purchase error boundary demo | -| `/save-payment` | Save Payment product page | -| `/save-payment/card-fields` | Save Payment with Card Fields product page | -| `/subscription` | Subscription product page | -| `/subscription/cart` | Subscription cart page | -| `/subscription/checkout` | Subscription checkout page | -| `/subscription/error` | Subscription error boundary demo | -| `/paypal-messages` | PayPal Messages demo page | -| `/error-boundary-test` | Standalone error handling demonstration | +| Route | Description | +| ---------------------------------------- | ----------------------------------------------- | +| `/` | Home page with navigation | +| `/one-time-payment` | One-Time Payment product page | +| `/one-time-payment/cart` | One-Time Payment cart page | +| `/one-time-payment/checkout` | One-Time Payment checkout page | +| `/one-time-payment/error` | One-Time Payment error boundary demo | +| `/one-time-payment/card-fields` | One-Time Payment with Card Fields product page | +| `/one-time-payment/card-fields/cart` | One-Time Payment with Card Fields cart page | +| `/one-time-payment/card-fields/checkout` | One-Time Payment with Card Fields checkout page | +| `/vault-with-purchase` | Vault with Purchase product page | +| `/vault-with-purchase/cart` | Vault with Purchase cart page | +| `/vault-with-purchase/checkout` | Vault with Purchase checkout page | +| `/vault-with-purchase/error` | Vault with Purchase error boundary demo | +| `/save-payment` | Save Payment product page | +| `/save-payment/card-fields` | Save Payment with Card Fields product page | +| `/subscription` | Subscription product page | +| `/subscription/cart` | Subscription cart page | +| `/subscription/checkout` | Subscription checkout page | +| `/subscription/error` | Subscription error boundary demo | +| `/paypal-messages` | PayPal Messages demo page | +| `/error-boundary-test` | Standalone error handling demonstration | ## Project Structure @@ -294,10 +294,10 @@ const PayPalButton = (props: UsePayPalOneTimePaymentSessionProps) => { Card Fields provides specialized hooks to create payment sessions that work seamlessly with individual card field components: -| Hook | Use Case | -| ------------------------------------------------- | -------------------- | -| `usePayPalCardFieldsOneTimePaymentSession` | One-time payments | -| `usePayPalCardFieldsSavePaymentSession` | Save payment methods | +| Hook | Use Case | +| ------------------------------------------ | -------------------- | +| `usePayPalCardFieldsOneTimePaymentSession` | One-time payments | +| `usePayPalCardFieldsSavePaymentSession` | Save payment methods | **Example Usage:** @@ -308,7 +308,7 @@ import { PayPalCardCvvField, usePayPalCardFieldsOneTimePaymentSession, } from "@paypal/react-paypal-js/sdk-v6"; -import { useEffect } from "react"; +import { useEffect } from "react"; const CardFieldsPayment = () => { const { submit, submitResponse } = usePayPalCardFieldsOneTimePaymentSession(); @@ -329,12 +329,14 @@ const CardFieldsPayment = () => { const { orderId, state } = submitResponse.data; - switch(state) { + switch (state) { case "succeeded": captureOrder({ orderId }); break; case "failed": - console.error(`One time payment failed: orderId: ${orderId}, message: ${message}`); + console.error( + `One time payment failed: orderId: ${orderId}, message: ${message}`, + ); break; } }, [submitResponse]); From a2ff9b01ece24c94d690ed060dfdc834c4932a92 Mon Sep 17 00:00:00 2001 From: Alejandro Gastelum Flores Date: Wed, 11 Mar 2026 11:51:53 -0700 Subject: [PATCH 4/6] Fixed unclear description --- client/prebuiltPages/react/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/prebuiltPages/react/README.md b/client/prebuiltPages/react/README.md index ba1ffba0..3ed8db67 100644 --- a/client/prebuiltPages/react/README.md +++ b/client/prebuiltPages/react/README.md @@ -367,7 +367,7 @@ const CardFieldsPayment = () => { 2. User clicks the submit button 3. `createOrder` creates an order via the backend API 4. `submit(orderId)` processes the card payment with the order ID -5. `submitResponse` callback provides the payment result +5. `submitResponse` object gets updated with the payment result 6. Handle submit response based on payment result ## Backend Server From f38ff44c1a2578c4da72faa027e181bc9b083c21 Mon Sep 17 00:00:00 2001 From: Alejandro Gastelum Flores Date: Wed, 11 Mar 2026 11:55:22 -0700 Subject: [PATCH 5/6] Fixed typo --- client/prebuiltPages/react/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/prebuiltPages/react/README.md b/client/prebuiltPages/react/README.md index 3ed8db67..e10f8788 100644 --- a/client/prebuiltPages/react/README.md +++ b/client/prebuiltPages/react/README.md @@ -296,8 +296,8 @@ Card Fields provides specialized hooks to create payment sessions that work seam | Hook | Use Case | | ------------------------------------------ | -------------------- | -| `usePayPalCardFieldsOneTimePaymentSession` | One-time payments | -| `usePayPalCardFieldsSavePaymentSession` | Save payment methods | +| `usePayPalCardFieldsOneTimePaymentSession` | One-time payment | +| `usePayPalCardFieldsSavePaymentSession` | Save payment method | **Example Usage:** From 221e6c6ff6f9321bbdccea8b5bed5fb53d386940 Mon Sep 17 00:00:00 2001 From: Alejandro Gastelum Flores Date: Wed, 11 Mar 2026 12:00:30 -0700 Subject: [PATCH 6/6] Ran prettier --- client/prebuiltPages/react/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/prebuiltPages/react/README.md b/client/prebuiltPages/react/README.md index e10f8788..1ce8d809 100644 --- a/client/prebuiltPages/react/README.md +++ b/client/prebuiltPages/react/README.md @@ -294,8 +294,8 @@ const PayPalButton = (props: UsePayPalOneTimePaymentSessionProps) => { Card Fields provides specialized hooks to create payment sessions that work seamlessly with individual card field components: -| Hook | Use Case | -| ------------------------------------------ | -------------------- | +| Hook | Use Case | +| ------------------------------------------ | ------------------- | | `usePayPalCardFieldsOneTimePaymentSession` | One-time payment | | `usePayPalCardFieldsSavePaymentSession` | Save payment method |