= ({ product }) => {
return (
<>
diff --git a/client/prebuiltPages/react/oneTimePayment/src/components/VenmoButton.tsx b/client/prebuiltPages/react/oneTimePayment/src/components/VenmoButton.tsx
index f571472..65a72eb 100644
--- a/client/prebuiltPages/react/oneTimePayment/src/components/VenmoButton.tsx
+++ b/client/prebuiltPages/react/oneTimePayment/src/components/VenmoButton.tsx
@@ -4,6 +4,12 @@ import { createOrder } from "../utils";
import { PaymentSessionOptions, SessionOutput } from "../types/paypal";
import { useErrorBoundary } from "react-error-boundary";
+/**
+ * VenmoButton component renders a Venmo button and manages the Venmo payment session.
+ *
+ * @param {PaymentSessionOptions} paymentSessionOptions - The options for the Venmo payment session, including event handlers.
+ * @returns {JSX.Element} The rendered Venmo button component.
+ */
const VenmoButton: React.FC
= (
paymentSessionOptions,
) => {
@@ -19,6 +25,10 @@ const VenmoButton: React.FC = (
}
}, [sdkInstance, paymentSessionOptions]);
+ /**
+ * Handles the Venmo button click event, starts the payment session,
+ * and triggers error boundaries on failure.
+ */
const venmoOnClickHandler = async () => {
if (!venmoSession.current) return;
diff --git a/client/prebuiltPages/react/oneTimePayment/src/context/sdkContext.tsx b/client/prebuiltPages/react/oneTimePayment/src/context/sdkContext.tsx
index 9c9d8ff..cc67edb 100644
--- a/client/prebuiltPages/react/oneTimePayment/src/context/sdkContext.tsx
+++ b/client/prebuiltPages/react/oneTimePayment/src/context/sdkContext.tsx
@@ -9,6 +9,13 @@ import type {
SdkInstance,
} from "../types/paypal";
+/**
+ * Initializes the PayPal SDK instance and fetches eligible payment methods.
+ *
+ * @param {CreateInstanceOptions} options - Options for creating the PayPal SDK instance.
+ * @returns {Promise<{ sdkInstance: SdkInstance; eligiblePaymentMethods: EligiblePaymentMethods }>}
+ * An object containing the SDK instance and eligible payment methods.
+ */
async function initSdkInstance({
clientToken,
components,
@@ -30,27 +37,49 @@ async function initSdkInstance({
};
}
+/**
+ * Context properties for PayPal SDK.
+ */
interface PayPalSDKContextProps {
+ /** Eligible payment methods returned by the SDK. */
eligiblePaymentMethods: EligiblePaymentMethods | null;
+ /** The PayPal SDK instance. */
sdkInstance: SdkInstance | null;
}
+/** Initial context values for PayPalSDKContext. */
const initialContext: PayPalSDKContextProps = {
eligiblePaymentMethods: null,
sdkInstance: null,
};
+/**
+ * Props for the PayPalSDKProvider component.
+ */
interface PayPalSDKProviderProps {
+ /** List of PayPal SDK components to load. */
components: Component[];
+ /** React children nodes. */
children: React.ReactNode;
+ /** The page type for the SDK instance. */
pageType: PageType;
+ /** Optional client token for SDK initialization. */
clientToken?: string;
}
-// eslint-disable-next-line react-refresh/only-export-components
+/**
+ * React context for sharing PayPal SDK instance and eligible payment methods.
+ */
export const PayPalSDKContext =
createContext(initialContext);
+/**
+ * PayPalSDKProvider component initializes the PayPal SDK and provides
+ * the SDK instance and eligible payment methods to its children via context.
+ *
+ * @param {PayPalSDKProviderProps} props - The provider props.
+ * @returns {JSX.Element} The context provider with SDK values.
+ */
export const PayPalSDKProvider: React.FC = ({
clientToken,
components,
diff --git a/client/prebuiltPages/react/oneTimePayment/src/sections/SoccerBall.tsx b/client/prebuiltPages/react/oneTimePayment/src/sections/SoccerBall.tsx
index 05d6e43..a3d940b 100644
--- a/client/prebuiltPages/react/oneTimePayment/src/sections/SoccerBall.tsx
+++ b/client/prebuiltPages/react/oneTimePayment/src/sections/SoccerBall.tsx
@@ -11,15 +11,24 @@ import { captureOrder } from "../utils";
import "../static/styles/SoccerBall.css";
import "../static/styles/Modal.css";
-// Types
+/**
+ * ModalType defines the possible modal states for payment feedback.
+ */
type ModalType = "success" | "cancel" | "error" | null;
+/**
+ * ModalContent describes the content displayed in the modal dialog.
+ */
interface ModalContent {
+ /** The modal title text. */
title: string;
+ /** The modal message text. */
message: string;
}
-// Constants
+/**
+ * Product details for the World Cup Ball.
+ */
const PRODUCT = {
name: "World Cup Ball",
icon: "⚽️",
@@ -28,12 +37,24 @@ const PRODUCT = {
imageAlt: "Official World Cup Soccer Ball",
} as const;
+/**
+ * SoccerBall section component displays the product, handles PayPal and Venmo payments,
+ * and shows a modal dialog for payment status feedback.
+ *
+ * @returns {JSX.Element} The rendered SoccerBall section.
+ */
const SoccerBall: React.FC = () => {
const { sdkInstance, eligiblePaymentMethods } = useContext(PayPalSDKContext);
const [modalState, setModalState] = useState(null);
- // Payment handlers
+ /**
+ * Payment session event handlers for PayPal and Venmo buttons.
+ */
const handlePaymentCallbacks: PaymentSessionOptions = {
+ /**
+ * Called when the payment is approved.
+ * @param {OnApproveData} data - The approval data.
+ */
onApprove: async (data: OnApproveData) => {
console.log("Payment approved:", data);
const captureResult = await captureOrder({ orderId: data.orderId });
@@ -41,17 +62,30 @@ const SoccerBall: React.FC = () => {
setModalState("success");
},
+ /**
+ * Called when the payment is cancelled.
+ */
onCancel: () => {
console.log("Payment cancelled");
setModalState("cancel");
},
+ /**
+ * Called when an error occurs during payment.
+ * @param {Error} error - The error object.
+ */
onError: (error: Error) => {
console.error("Payment error:", error);
setModalState("error");
},
};
+ /**
+ * Returns the modal content based on the current modal state.
+ *
+ * @param {ModalType} state - The current modal state.
+ * @returns {ModalContent | null} The content to display in the modal.
+ */
const getModalContent = useCallback(
(state: ModalType): ModalContent | null => {
switch (state) {
diff --git a/client/prebuiltPages/react/oneTimePayment/src/utils.ts b/client/prebuiltPages/react/oneTimePayment/src/utils.ts
index 0d9505c..6532c38 100644
--- a/client/prebuiltPages/react/oneTimePayment/src/utils.ts
+++ b/client/prebuiltPages/react/oneTimePayment/src/utils.ts
@@ -1,18 +1,30 @@
-export const getBrowserSafeClientToken = async () => {
- {
- const response = await fetch("/paypal-api/auth/browser-safe-client-token", {
- method: "GET",
- headers: {
- "Content-Type": "application/json",
- },
- });
- const { accessToken } = await response.json();
+/**
+ * Fetches a browser-safe client token from the server for PayPal SDK initialization.
+ *
+ * @async
+ * @function
+ * @returns {Promise} The browser-safe client access token.
+ */
+export const getBrowserSafeClientToken = async (): Promise => {
+ const response = await fetch("/paypal-api/auth/browser-safe-client-token", {
+ method: "GET",
+ headers: {
+ "Content-Type": "application/json",
+ },
+ });
+ const { accessToken } = await response.json();
- return accessToken;
- }
+ return accessToken;
};
-export const createOrder = async () => {
+/**
+ * Creates a PayPal order by sending a request to the server.
+ *
+ * @async
+ * @function
+ * @returns {Promise<{ orderId: string }>} The created order object containing the order ID.
+ */
+export const createOrder = async (): Promise<{ orderId: string }> => {
const response = await fetch(
"/paypal-api/checkout/orders/create-with-sample-data",
{
@@ -26,7 +38,20 @@ export const createOrder = async () => {
return { orderId: id };
};
-export const captureOrder = async ({ orderId }: { orderId: string }) => {
+/**
+ * Captures a PayPal order by order ID.
+ *
+ * @async
+ * @function
+ * @param {Object} params - The parameters object.
+ * @param {string} params.orderId - The PayPal order ID.
+ * @returns {Promise} The capture order response data.
+ */
+export const captureOrder = async ({
+ orderId,
+}: {
+ orderId: string;
+}): Promise => {
const response = await fetch(
`/paypal-api/checkout/orders/${orderId}/capture`,
{
diff --git a/server/node/src/checkNodeVersion.ts b/server/node/src/checkNodeVersion.ts
index 9bf219e..2428fe2 100644
--- a/server/node/src/checkNodeVersion.ts
+++ b/server/node/src/checkNodeVersion.ts
@@ -2,11 +2,21 @@ import { readFileSync } from "node:fs";
import { join } from "node:path";
import { satisfies } from "semver";
+/**
+ * Reads the minimum required Node.js version from the .nvmrc file.
+ * @constant
+ * @type {string}
+ */
const minimumNodeVersion = readFileSync(
join(__dirname, "../", ".nvmrc"),
"utf-8",
);
+/**
+ * Checks if the current Node.js version satisfies the minimum required version.
+ * @constant
+ * @type {boolean}
+ */
const isValidNodeVersion = satisfies(
process.version,
`>= ${minimumNodeVersion}`,
@@ -17,6 +27,11 @@ if (isValidNodeVersion) {
process.exit(0);
}
+/**
+ * Output message displayed when the Node.js version is invalid.
+ * @constant
+ * @type {string}
+ */
const output = `
** Invalid Node.js Version **
current version: ${process.version}
diff --git a/server/node/src/paypalServerSdk.ts b/server/node/src/paypalServerSdk.ts
index 4b1cce9..43ebe6e 100644
--- a/server/node/src/paypalServerSdk.ts
+++ b/server/node/src/paypalServerSdk.ts
@@ -62,6 +62,13 @@ const vaultController = new VaultController(client);
* Token generation helpers
* ###################################################################### */
+/**
+ * Generates a browser-safe client token for PayPal SDK initialization.
+ *
+ * @async
+ * @function
+ * @returns {Promise<{ jsonResponse: object; httpStatusCode: number }>} The client token response and HTTP status code.
+ */
export async function getBrowserSafeClientToken() {
try {
const auth = Buffer.from(
@@ -82,8 +89,9 @@ export async function getBrowserSafeClientToken() {
fieldParameters,
);
- // the OAuthToken interface is too general
- // this interface is specific to the "client_token" response type
+ /**
+ * Interface for the client token response.
+ */
interface ClientToken {
accessToken: string;
expiresIn: number;
@@ -125,6 +133,16 @@ export async function getBrowserSafeClientToken() {
* Process orders
* ###################################################################### */
+/**
+ * Creates a PayPal order using the provided order request body.
+ *
+ * @async
+ * @function
+ * @param {Object} params - The parameters object.
+ * @param {OrderRequest} params.orderRequestBody - The order request body.
+ * @param {string} [params.paypalRequestId] - Optional PayPal request ID for idempotency.
+ * @returns {Promise<{ jsonResponse: object; httpStatusCode: number }>} The order creation response and HTTP status code.
+ */
export async function createOrder({
orderRequestBody,
paypalRequestId,
@@ -156,6 +174,13 @@ export async function createOrder({
}
}
+/**
+ * Creates a PayPal order with sample data for demonstration purposes.
+ *
+ * @async
+ * @function
+ * @returns {Promise<{ jsonResponse: object; httpStatusCode: number }>} The order creation response and HTTP status code.
+ */
export async function createOrderWithSampleData() {
const orderRequestBody = {
intent: CheckoutPaymentIntent.Capture,
@@ -171,6 +196,14 @@ export async function createOrderWithSampleData() {
return createOrder({ orderRequestBody });
}
+/**
+ * Captures a PayPal order by order ID.
+ *
+ * @async
+ * @function
+ * @param {string} orderId - The PayPal order ID to capture.
+ * @returns {Promise<{ jsonResponse: object; httpStatusCode: number }>} The capture response and HTTP status code.
+ */
export async function captureOrder(orderId: string) {
try {
const { result, statusCode } = await ordersController.captureOrder({
@@ -199,6 +232,15 @@ export async function captureOrder(orderId: string) {
* Save payment methods
* ###################################################################### */
+/**
+ * Creates a PayPal setup token for saving a payment method.
+ *
+ * @async
+ * @function
+ * @param {SetupTokenRequest} setupTokenRequestBody - The setup token request body.
+ * @param {string} [paypalRequestId] - Optional PayPal request ID for idempotency.
+ * @returns {Promise<{ jsonResponse: object; httpStatusCode: number }>} The setup token response and HTTP status code.
+ */
export async function createSetupToken(
setupTokenRequestBody: SetupTokenRequest,
paypalRequestId?: string,
@@ -227,6 +269,13 @@ export async function createSetupToken(
}
}
+/**
+ * Creates a PayPal setup token with sample data for PayPal payment method.
+ *
+ * @async
+ * @function
+ * @returns {Promise<{ jsonResponse: object; httpStatusCode: number }>} The setup token response and HTTP status code.
+ */
export async function createSetupTokenWithSampleDataForPayPal() {
const defaultSetupTokenRequestBody = {
paymentSource: {
@@ -244,6 +293,15 @@ export async function createSetupTokenWithSampleDataForPayPal() {
return createSetupToken(defaultSetupTokenRequestBody, Date.now().toString());
}
+/**
+ * Creates a PayPal payment token using a vault setup token.
+ *
+ * @async
+ * @function
+ * @param {string} vaultSetupToken - The vault setup token.
+ * @param {string} [paypalRequestId] - Optional PayPal request ID for idempotency.
+ * @returns {Promise<{ jsonResponse: object; httpStatusCode: number }>} The payment token response and HTTP status code.
+ */
export async function createPaymentToken(
vaultSetupToken: string,
paypalRequestId?: string,
diff --git a/server/node/src/server.ts b/server/node/src/server.ts
index e4c35c0..e2ac757 100644
--- a/server/node/src/server.ts
+++ b/server/node/src/server.ts
@@ -130,6 +130,16 @@ app.post(
},
);
+/**
+ * Saves the PayPal payment token to a database for future transactions.
+ * This is an example function to demonstrate storing the payment token.
+ * In a real implementation, this should persist the token securely.
+ *
+ * @async
+ * @function
+ * @param {PaymentTokenResponse} paymentTokenResponse - The payment token response object to save.
+ * @returns {Promise} A promise that resolves when the token is saved.
+ */
async function savePaymentTokenToDatabase(
paymentTokenResponse: PaymentTokenResponse,
) {