diff --git a/client/components/fastlane/html/src/fastlane.js b/client/components/fastlane/html/src/fastlane.js index f33cc5a..638136f 100644 --- a/client/components/fastlane/html/src/fastlane.js +++ b/client/components/fastlane/html/src/fastlane.js @@ -1,3 +1,10 @@ +/** + * Initializes the Fastlane SDK, sets up event listeners for email submission, + * handles authentication flow, and renders the appropriate user experience. + * @async + * @function + * @returns {Promise} + */ async function setupFastlaneSdk() { fastlane.setLocale("en_us"); @@ -41,6 +48,17 @@ async function setupFastlaneSdk() { }); } +/** + * Displays the shipping address information in the UI. + * @param {Object} shippingAddress - The shipping address object. + * @param {Object} shippingAddress.name - Name object containing fullName. + * @param {string} shippingAddress.name.fullName - Full name of the recipient. + * @param {Object} shippingAddress.address - Address object. + * @param {string} shippingAddress.address.addressLine1 - Street address. + * @param {string} shippingAddress.address.adminArea2 - City or locality. + * @param {string} shippingAddress.address.adminArea1 - State or region. + * @param {string} shippingAddress.address.postalCode - Postal or ZIP code. + */ function setShippingAddressDisplay(shippingAddress) { const { name: { fullName }, @@ -53,6 +71,15 @@ function setShippingAddressDisplay(shippingAddress) { shippingDisplayContainer.innerHTML = `${fullName}
${adminArea2}
${adminArea1}
${postalCode}`; } +/** + * Renders the Fastlane member checkout experience, including shipping address, + * payment component, and order submission. + * @async + * @function + * @param {Object} profileData - The user's profile data. + * @param {Object} profileData.shippingAddress - The user's shipping address. + * @returns {Promise} + */ async function renderFastlaneMemberExperience(profileData) { if (profileData.shippingAddress) { setShippingAddressDisplay(profileData.shippingAddress); @@ -97,6 +124,13 @@ async function renderFastlaneMemberExperience(profileData) { } } +/** + * Renders the Fastlane guest checkout experience, including payment component + * and order submission. + * @async + * @function + * @returns {Promise} + */ async function renderFastlaneGuestExperience() { const cardTestingInfo = document.getElementById("card-testing-info"); cardTestingInfo.removeAttribute("hidden"); @@ -119,6 +153,13 @@ async function renderFastlaneGuestExperience() { }); } +/** + * Creates an order by sending a request to the server with the payment token. + * @async + * @function + * @param {string} paymentToken - The payment token from Fastlane. + * @returns {Promise} The response from the order creation API. + */ async function createOrder(paymentToken) { const response = await fetch("/paypal-api/checkout/orders/create", { method: "POST", diff --git a/client/components/fastlane/html/src/fastlaneSdkComponent.js b/client/components/fastlane/html/src/fastlaneSdkComponent.js index 287ea46..847182c 100644 --- a/client/components/fastlane/html/src/fastlaneSdkComponent.js +++ b/client/components/fastlane/html/src/fastlaneSdkComponent.js @@ -1,4 +1,16 @@ +/** + * Global variable to hold the Fastlane SDK instance. + * @type {Object} + */ let fastlane; + +/** + * Initializes the PayPal Web SDK, creates a Fastlane instance, + * and sets up the Fastlane SDK experience. + * @async + * @function + * @returns {Promise} + */ async function onPayPalWebSdkLoaded() { const clientToken = await getBrowserSafeClientToken(); @@ -13,6 +25,12 @@ async function onPayPalWebSdkLoaded() { setupFastlaneSdk(); } +/** + * Fetches a browser-safe client token from the server for PayPal SDK initialization. + * @async + * @function + * @returns {Promise} The browser-safe client access token. + */ async function getBrowserSafeClientToken() { const response = await fetch("/paypal-api/auth/browser-safe-client-token", { method: "GET", diff --git a/client/components/googlePayPayments/oneTimePayment/html/src/app.js b/client/components/googlePayPayments/oneTimePayment/html/src/app.js index 0471371..9544026 100644 --- a/client/components/googlePayPayments/oneTimePayment/html/src/app.js +++ b/client/components/googlePayPayments/oneTimePayment/html/src/app.js @@ -1,3 +1,10 @@ +/** + * Initializes the PayPal Web SDK, creates a Google Pay Payments instance, + * and sets up the Google Pay button. + * @async + * @function + * @returns {Promise} + */ async function onPayPalWebSdkLoaded() { try { const clientToken = await getBrowserSafeClientToken(); @@ -13,6 +20,12 @@ async function onPayPalWebSdkLoaded() { } } +/** + * Generates the PayPal order payload for a given purchase amount. + * @function + * @param {string} purchaseAmount - The total purchase amount. + * @returns {Object} The PayPal order payload. + */ function getPayPalOrderPayload(purchaseAmount) { return { intent: "CAPTURE", @@ -42,6 +55,13 @@ function getPayPalOrderPayload(purchaseAmount) { }; } +/** + * Generates the Google Pay transaction info object. + * @function + * @param {string} purchaseAmount - The total purchase amount. + * @param {string} countryCode - The country code (e.g., "US"). + * @returns {Object} The Google Pay transaction info. + */ function getGoogleTransactionInfo(purchaseAmount, countryCode) { const totalAmount = parseFloat(purchaseAmount); const subtotal = (totalAmount * 0.9).toFixed(2); @@ -68,6 +88,14 @@ function getGoogleTransactionInfo(purchaseAmount, countryCode) { }; } +/** + * Builds the Google PaymentDataRequest object for Google Pay API. + * @async + * @function + * @param {string} purchaseAmount - The total purchase amount. + * @param {Object} googlePayConfig - The Google Pay configuration object. + * @returns {Promise} The PaymentDataRequest object. + */ async function getGooglePaymentDataRequest(purchaseAmount, googlePayConfig) { const { allowedPaymentMethods, @@ -95,6 +123,16 @@ async function getGooglePaymentDataRequest(purchaseAmount, googlePayConfig) { return paymentDataRequest; } +/** + * Handles the payment authorization callback from Google Pay. + * Creates and confirms the PayPal order, and captures it if possible. + * @async + * @function + * @param {string} purchaseAmount - The total purchase amount. + * @param {Object} paymentData - The payment data from Google Pay. + * @param {Object} googlePaySession - The Google Pay session instance. + * @returns {Promise} The transaction state result. + */ async function onPaymentAuthorized( purchaseAmount, paymentData, @@ -126,6 +164,16 @@ async function onPaymentAuthorized( } } +/** + * Handles the Google Pay button click event. + * Loads the payment data request using the PaymentsClient. + * @async + * @function + * @param {string} purchaseAmount - The total purchase amount. + * @param {Object} paymentsClient - The Google PaymentsClient instance. + * @param {Object} googlePayConfig - The Google Pay configuration object. + * @returns {Promise} + */ async function onGooglePayButtonClick( purchaseAmount, paymentsClient, @@ -143,6 +191,13 @@ async function onGooglePayButtonClick( } } +/** + * Sets up the Google Pay button and session, and appends the button to the DOM if ready. + * @async + * @function + * @param {Object} sdkInstance - The PayPal SDK instance. + * @returns {Promise} + */ async function setupGooglePayButton(sdkInstance) { const googlePaySession = sdkInstance.createGooglePayOneTimePaymentSession(); const purchaseAmount = "10.00"; @@ -181,6 +236,12 @@ async function setupGooglePayButton(sdkInstance) { } } +/** + * Fetches a browser-safe client token from the server for PayPal SDK initialization. + * @async + * @function + * @returns {Promise} The browser-safe client access token. + */ async function getBrowserSafeClientToken() { const response = await fetch("/paypal-api/auth/browser-safe-client-token", { method: "GET", @@ -193,6 +254,13 @@ async function getBrowserSafeClientToken() { return accessToken; } +/** + * Creates a PayPal order by sending the order payload to the server. + * @async + * @function + * @param {Object} orderPayload - The PayPal order payload. + * @returns {Promise} The created order ID. + */ async function createOrder(orderPayload) { const response = await fetch("/paypal-api/checkout/orders/create", { method: "POST", @@ -206,6 +274,14 @@ async function createOrder(orderPayload) { return id; } +/** + * 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. + */ async function captureOrder({ orderId }) { const response = await fetch( `/paypal-api/checkout/orders/${orderId}/capture`, diff --git a/client/components/paypalMessages/html/src/advanced/app.js b/client/components/paypalMessages/html/src/advanced/app.js index b33b992..2428ea3 100644 --- a/client/components/paypalMessages/html/src/advanced/app.js +++ b/client/components/paypalMessages/html/src/advanced/app.js @@ -1,3 +1,10 @@ +/** + * Initializes the PayPal Web SDK, creates a PayPal Messages instance, + * and renders the PayPal message on the page. + * @async + * @function + * @returns {Promise} + */ async function onPayPalWebSdkLoaded() { try { const clientToken = await getBrowserSafeClientToken(); @@ -11,6 +18,12 @@ async function onPayPalWebSdkLoaded() { } } +/** + * Fetches a browser-safe client token from the server for PayPal SDK initialization. + * @async + * @function + * @returns {Promise} The browser-safe client access token. + */ async function getBrowserSafeClientToken() { const response = await fetch("/paypal-api/auth/browser-safe-client-token", { method: "GET", @@ -23,6 +36,13 @@ async function getBrowserSafeClientToken() { return accessToken; } +/** + * Creates and renders a PayPal message using the SDK instance. + * @async + * @function + * @param {Object} sdkInstance - The PayPal SDK instance. + * @returns {Promise} The fetched message content. + */ async function createMessage(sdkInstance) { const messagesInstance = sdkInstance.createPayPalMessages(); const messageElement = document.querySelector("#paypal-message"); diff --git a/client/components/paypalMessages/html/src/recommended/app.js b/client/components/paypalMessages/html/src/recommended/app.js index e2d8e4e..061bd17 100644 --- a/client/components/paypalMessages/html/src/recommended/app.js +++ b/client/components/paypalMessages/html/src/recommended/app.js @@ -1,3 +1,10 @@ +/** + * Initializes the PayPal Web SDK, creates a PayPal Messages instance, + * and sets up the product interaction event listener. + * @async + * @function + * @returns {Promise} + */ async function onPayPalWebSdkLoaded() { try { const clientToken = await getBrowserSafeClientToken(); @@ -12,6 +19,12 @@ async function onPayPalWebSdkLoaded() { } } +/** + * Fetches a browser-safe client token from the server for PayPal SDK initialization. + * @async + * @function + * @returns {Promise} The browser-safe client access token. + */ async function getBrowserSafeClientToken() { const response = await fetch("/paypal-api/auth/browser-safe-client-token", { method: "GET", @@ -24,7 +37,12 @@ async function getBrowserSafeClientToken() { return accessToken; } -// basic example product interaction +/** + * Adds an event listener to update the displayed quantity, total amount, + * and PayPal message amount when the product quantity input changes. + * @function + * @returns {void} + */ function addAmountEventListener() { const messageElement = document.querySelector("#paypal-message"); const quantityInput = document.querySelector("#quantity-input"); diff --git a/client/components/paypalPayments/oneTimePayment/html/src/advanced/paymentHandler/app.js b/client/components/paypalPayments/oneTimePayment/html/src/advanced/paymentHandler/app.js index 5fe89fb..24a038d 100644 --- a/client/components/paypalPayments/oneTimePayment/html/src/advanced/paymentHandler/app.js +++ b/client/components/paypalPayments/oneTimePayment/html/src/advanced/paymentHandler/app.js @@ -1,3 +1,10 @@ +/** + * Initializes the PayPal Web SDK, creates a PayPal Payments instance, + * and sets up the PayPal button. + * @async + * @function + * @returns {Promise} + */ async function onPayPalWebSdkLoaded() { try { const clientToken = await getBrowserSafeClientToken(); @@ -13,6 +20,14 @@ async function onPayPalWebSdkLoaded() { } } +/** + * Sets up the PayPal button, handles payment session events, + * and manages presentation modes for the payment flow. + * @async + * @function + * @param {Object} sdkInstance - The PayPal SDK instance. + * @returns {Promise} + */ async function setupPayPalButton(sdkInstance) { const paymentSessionOptions = { async onApprove(data) { @@ -76,6 +91,12 @@ async function setupPayPalButton(sdkInstance) { }); } +/** + * Fetches a browser-safe client token from the server for PayPal SDK initialization. + * @async + * @function + * @returns {Promise} The browser-safe client access token. + */ async function getBrowserSafeClientToken() { const response = await fetch("/paypal-api/auth/browser-safe-client-token", { method: "GET", @@ -88,6 +109,12 @@ async function getBrowserSafeClientToken() { return accessToken; } +/** + * Creates a PayPal order by sending a request to the server. + * @async + * @function + * @returns {Promise} The created order object containing the order ID. + */ async function createOrder() { const response = await fetch( "/paypal-api/checkout/orders/create-with-sample-data", @@ -103,6 +130,14 @@ async function createOrder() { return { orderId: id }; } +/** + * 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. + */ async function captureOrder({ orderId }) { const response = await fetch( `/paypal-api/checkout/orders/${orderId}/capture`, diff --git a/client/components/paypalPayments/oneTimePayment/html/src/advanced/redirect/app.js b/client/components/paypalPayments/oneTimePayment/html/src/advanced/redirect/app.js index e74d2cd..06cb1e5 100644 --- a/client/components/paypalPayments/oneTimePayment/html/src/advanced/redirect/app.js +++ b/client/components/paypalPayments/oneTimePayment/html/src/advanced/redirect/app.js @@ -1,3 +1,10 @@ +/** + * Initializes the PayPal Web SDK, creates a PayPal Payments instance, + * and sets up the PayPal button or resumes the payment session if returning from redirect. + * @async + * @function + * @returns {Promise} + */ async function onPayPalWebSdkLoaded() { try { const clientToken = await getBrowserSafeClientToken(); @@ -20,6 +27,14 @@ async function onPayPalWebSdkLoaded() { } } +/** + * Options object for PayPal payment session event handlers. + * @typedef {Object} PaymentSessionOptions + * @property {function(Object): Promise} onApprove - Called when the payment is approved. + * @property {function(Object): void} onCancel - Called when the payment is cancelled. + * @property {function(Error): void} onError - Called when an error occurs. + */ + const paymentSessionOptions = { async onApprove(data) { console.log("onApprove", data); @@ -36,6 +51,13 @@ const paymentSessionOptions = { }, }; +/** + * Sets up the PayPal button, handles click events, and manages redirect flow. + * @async + * @function + * @param {Object} paypalPaymentSession - The PayPal payment session instance. + * @returns {Promise} + */ async function setupPayPalButton(paypalPaymentSession) { const enableAutoRedirect = document.querySelector("#enable-auto-redirect"); const paypalButton = document.querySelector("#paypal-button"); @@ -64,6 +86,12 @@ async function setupPayPalButton(paypalPaymentSession) { }); } +/** + * Fetches a browser-safe client token from the server for PayPal SDK initialization. + * @async + * @function + * @returns {Promise} The browser-safe client access token. + */ async function getBrowserSafeClientToken() { const response = await fetch("/paypal-api/auth/browser-safe-client-token", { method: "GET", @@ -76,6 +104,12 @@ async function getBrowserSafeClientToken() { return accessToken; } +/** + * Creates a PayPal order for redirect flow by sending a request to the server. + * @async + * @function + * @returns {Promise} The created order object containing the order ID. + */ async function createRedirectOrder() { const orderPayload = { intent: "CAPTURE", @@ -116,6 +150,14 @@ async function createRedirectOrder() { return { orderId: id }; } +/** + * 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. + */ async function captureOrder({ orderId }) { const response = await fetch( `/paypal-api/checkout/orders/${orderId}/capture`, diff --git a/client/components/paypalPayments/oneTimePayment/html/src/advanced/sandboxedIframe/src/merchant-example/app.js b/client/components/paypalPayments/oneTimePayment/html/src/advanced/sandboxedIframe/src/merchant-example/app.js index 0152421..bc0ae11 100644 --- a/client/components/paypalPayments/oneTimePayment/html/src/advanced/sandboxedIframe/src/merchant-example/app.js +++ b/client/components/paypalPayments/oneTimePayment/html/src/advanced/sandboxedIframe/src/merchant-example/app.js @@ -1,34 +1,64 @@ +/** + * Class to manage and synchronize page state with the DOM. + */ class PageState { + /** + * Internal state object. + * @type {{presentationMode: string|null, lastPostMessage: Object|null, merchantDomain: string|null}} + */ state = { presentationMode: null, lastPostMessage: null, merchantDomain: null, }; + /** + * Initializes the merchant domain to the current window origin. + */ constructor() { this.merchantDomain = window.location.origin; } + /** + * Sets the current presentation mode and updates the DOM. + * @param {string} value - The presentation mode value. + */ set presentationMode(value) { this.state.presentationMode = value; const element = document.getElementById("presentationMode"); element.innerHTML = value; } + /** + * Gets the current presentation mode. + * @returns {string|null} + */ get presentationMode() { return this.state.presentationMode; } + /** + * Sets the last postMessage event and updates the DOM. + * @param {MessageEvent} event - The postMessage event. + */ set lastPostMessage(event) { const statusContainer = document.getElementById("postMessageStatus"); statusContainer.innerHTML = JSON.stringify(event.data); this.state.lastPostMessage = event; } + /** + * Gets the last postMessage event. + * @returns {MessageEvent|null} + */ get lastPostMessage() { return this.state.lastPostMessage; } + /** + * Sets the merchant domain and updates the DOM. + * @param {string} value - The merchant domain. + */ set merchantDomain(value) { document.getElementById("merchantDomain").innerHTML = value; this.state.merchantDomain = value; @@ -37,6 +67,10 @@ class PageState { const pageState = new PageState(); +/** + * Handles postMessage events for the "popup" presentation mode. + * @param {MessageEvent} event - The postMessage event. + */ function popupPresentationModePostMessageHandler(event) { const { eventName, data } = event.data; const overlay = document.getElementById("overlayContainer"); @@ -52,6 +86,10 @@ function popupPresentationModePostMessageHandler(event) { } } +/** + * Handles postMessage events for the "modal" presentation mode. + * @param {MessageEvent} event - The postMessage event. + */ function modalPresentationModePostMessageHandler(event) { const { eventName, data } = event.data; const iframe = document.getElementById("iframeWrapper"); @@ -67,6 +105,10 @@ function modalPresentationModePostMessageHandler(event) { } } +/** + * Sets up a window message event listener to handle postMessage events + * from the child iframe, updating state and presentation as needed. + */ function setupPostMessageListener() { window.addEventListener("message", (event) => { // It's very important to check that the `origin` is expected to prevent XSS attacks! @@ -90,6 +132,9 @@ function setupPostMessageListener() { }); } +/** + * Sets up the overlay dialog and its close event listeners. + */ function setupOverlay() { const overlay = document.getElementById("overlayContainer"); @@ -105,6 +150,9 @@ function setupOverlay() { closeBackdrop.addEventListener("click", hideOverlay); } +/** + * Initializes the overlay and postMessage listener on page load. + */ function onLoad() { if (window.setupComplete) { return; @@ -116,6 +164,10 @@ function onLoad() { window.setupComplete = true; } +/** + * Sends a postMessage to the child iframe with the given payload. + * @param {Object} payload - The message payload to send. + */ function sendPostMessageToChild(payload) { const iframe = document.getElementById("iframeWrapper"); const childOrigin = new URL(iframe.getAttribute("src")).origin; diff --git a/client/components/paypalPayments/oneTimePayment/html/src/advanced/sandboxedIframe/src/paypal-iframe/integration.js b/client/components/paypalPayments/oneTimePayment/html/src/advanced/sandboxedIframe/src/paypal-iframe/integration.js index 8b272fa..1bdaf96 100644 --- a/client/components/paypalPayments/oneTimePayment/html/src/advanced/sandboxedIframe/src/paypal-iframe/integration.js +++ b/client/components/paypalPayments/oneTimePayment/html/src/advanced/sandboxedIframe/src/paypal-iframe/integration.js @@ -1,12 +1,27 @@ +/** + * Class to manage the page state, specifically the PayPal payment session. + */ class PageState { + /** + * Internal state object. + * @type {{paymentSession: Object|null}} + */ state = { paymentSession: null, }; + /** + * Gets the current PayPal payment session. + * @returns {Object|null} + */ get paymentSession() { return this.state.paymentSession; } + /** + * Sets the PayPal payment session. + * @param {Object} value - The PayPal payment session instance. + */ set paymentSession(value) { this.state.paymentSession = value; } @@ -14,6 +29,11 @@ class PageState { const pageState = new PageState(); +/** + * Retrieves the parent window's origin from the URL query parameters. + * @function + * @returns {string|null} The parent origin. + */ function getParentOrigin() { const parentOrigin = new URLSearchParams(window.location.search).get( "origin", @@ -21,6 +41,12 @@ function getParentOrigin() { return parentOrigin; } +/** + * Sets up a window message event listener to handle postMessage events + * from the parent window, updating state and handling payment flow events. + * @function + * @returns {void} + */ function setupPostMessageListener() { window.addEventListener("message", (event) => { // It's very important to check that the `origin` is expected to prevent XSS attacks! @@ -39,14 +65,30 @@ function setupPostMessageListener() { }); } +/** + * Sends a postMessage to the parent window with the given payload. + * @function + * @param {Object} payload - The message payload to send. + */ function sendPostMessageToParent(payload) { window.parent.postMessage(payload, getParentOrigin()); } +/** + * Gets the selected presentation mode from the radio inputs. + * @function + * @returns {string} The selected presentation mode value. + */ function getSelectedPresentationMode() { return document.querySelector("input[name='presentationMode']:checked").value; } +/** + * Sets up event listeners for presentation mode radio buttons and + * notifies the parent window of the selected mode. + * @function + * @returns {void} + */ function setupPresentationModeRadio() { const selector = document.querySelectorAll("input[name='presentationMode']"); Array.from(selector).forEach((element) => { @@ -69,13 +111,29 @@ function setupPresentationModeRadio() { }); } +/** + * Displays the iframe's origin in the DOM. + * @function + * @returns {void} + */ function setupIframeOriginDisplay() { const origin = window.location.origin; document.querySelector("#iframeDomain").innerHTML = origin; } +/** + * Sets up the PayPal button, creates a payment session, and handles payment events. + * @async + * @function + * @param {Object} sdkInstance - The PayPal SDK instance. + * @returns {Promise} + */ async function setupPayPalButton(sdkInstance) { pageState.paymentSession = sdkInstance.createPayPalOneTimePaymentSession({ + /** + * Called when the payment is approved. + * @param {Object} data - The approval data. + */ onApprove: async (data) => { const orderData = await captureOrder({ orderId: data.orderId, @@ -86,6 +144,10 @@ async function setupPayPalButton(sdkInstance) { data: orderData, }); }, + /** + * Called when the payment is canceled. + * @param {Object} data - The cancellation data. + */ onCancel: (data) => { sendPostMessageToParent({ eventName: "payment-flow-canceled", @@ -94,6 +156,10 @@ async function setupPayPalButton(sdkInstance) { }, }); }, + /** + * Called when an error occurs during payment. + * @param {Object} data - The error data. + */ onError: (data) => { sendPostMessageToParent({ eventName: "payment-flow-canceled", @@ -124,6 +190,12 @@ async function setupPayPalButton(sdkInstance) { }); } +/** + * Initializes the iframe integration, sets up event listeners, and loads the PayPal SDK. + * @async + * @function + * @returns {Promise} + */ async function onPayPalWebSdkLoaded() { if (window.setupComplete) { return; @@ -149,6 +221,12 @@ async function onPayPalWebSdkLoaded() { window.setupComplete = true; } +/** + * Fetches a browser-safe client token from the server for PayPal SDK initialization. + * @async + * @function + * @returns {Promise} The browser-safe client access token. + */ async function getBrowserSafeClientToken() { const response = await fetch("/paypal-api/auth/browser-safe-client-token", { method: "GET", @@ -161,6 +239,12 @@ async function getBrowserSafeClientToken() { return accessToken; } +/** + * Creates a PayPal order by sending a request to the server. + * @async + * @function + * @returns {Promise} The created order object containing the order ID. + */ async function createOrder() { const response = await fetch( "/paypal-api/checkout/orders/create-with-sample-data", @@ -176,6 +260,14 @@ async function createOrder() { return { orderId: id }; } +/** + * 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. + */ async function captureOrder({ orderId }) { const response = await fetch( `/paypal-api/checkout/orders/${orderId}/capture`, diff --git a/client/components/paypalPayments/oneTimePayment/html/src/recommended/app.js b/client/components/paypalPayments/oneTimePayment/html/src/recommended/app.js index 0dac670..e3c64de 100644 --- a/client/components/paypalPayments/oneTimePayment/html/src/recommended/app.js +++ b/client/components/paypalPayments/oneTimePayment/html/src/recommended/app.js @@ -1,3 +1,10 @@ +/** + * Initializes the PayPal Web SDK, determines eligible payment methods, + * and sets up the appropriate payment buttons. + * @async + * @function + * @returns {Promise} + */ async function onPayPalWebSdkLoaded() { try { const clientToken = await getBrowserSafeClientToken(); @@ -31,6 +38,13 @@ async function onPayPalWebSdkLoaded() { } } +/** + * Options object for PayPal payment session event handlers. + * @typedef {Object} PaymentSessionOptions + * @property {function(Object): Promise} onApprove - Called when the payment is approved. + * @property {function(Object): void} onCancel - Called when the payment is cancelled. + * @property {function(Error): void} onError - Called when an error occurs. + */ const paymentSessionOptions = { async onApprove(data) { console.log("onApprove", data); @@ -47,6 +61,13 @@ const paymentSessionOptions = { }, }; +/** + * Sets up the PayPal button and handles payment session events. + * @async + * @function + * @param {Object} sdkInstance - The PayPal SDK instance. + * @returns {Promise} + */ async function setupPayPalButton(sdkInstance) { const paypalPaymentSession = sdkInstance.createPayPalOneTimePaymentSession( paymentSessionOptions, @@ -67,6 +88,14 @@ async function setupPayPalButton(sdkInstance) { }); } +/** + * Sets up the Pay Later button and handles payment session events. + * @async + * @function + * @param {Object} sdkInstance - The PayPal SDK instance. + * @param {Object} paylaterPaymentMethodDetails - The Pay Later payment method details. + * @returns {Promise} + */ async function setupPayLaterButton(sdkInstance, paylaterPaymentMethodDetails) { const paylaterPaymentSession = sdkInstance.createPayLaterOneTimePaymentSession(paymentSessionOptions); @@ -90,6 +119,14 @@ async function setupPayLaterButton(sdkInstance, paylaterPaymentMethodDetails) { }); } +/** + * Sets up the PayPal Credit button and handles payment session events. + * @async + * @function + * @param {Object} sdkInstance - The PayPal SDK instance. + * @param {Object} paypalCreditPaymentMethodDetails - The PayPal Credit payment method details. + * @returns {Promise} + */ async function setupPayPalCreditButton( sdkInstance, paypalCreditPaymentMethodDetails, @@ -115,6 +152,12 @@ async function setupPayPalCreditButton( }); } +/** + * Fetches a browser-safe client token from the server for PayPal SDK initialization. + * @async + * @function + * @returns {Promise} The browser-safe client access token. + */ async function getBrowserSafeClientToken() { const response = await fetch("/paypal-api/auth/browser-safe-client-token", { method: "GET", @@ -127,6 +170,12 @@ async function getBrowserSafeClientToken() { return accessToken; } +/** + * Creates a PayPal order by sending a request to the server. + * @async + * @function + * @returns {Promise} The created order object containing the order ID. + */ async function createOrder() { const response = await fetch( "/paypal-api/checkout/orders/create-with-sample-data", @@ -142,6 +191,14 @@ async function createOrder() { return { orderId: id }; } +/** + * 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. + */ async function captureOrder({ orderId }) { const response = await fetch( `/paypal-api/checkout/orders/${orderId}/capture`, diff --git a/client/components/paypalPayments/savePayment/html/src/app.js b/client/components/paypalPayments/savePayment/html/src/app.js index aed82c2..4124a2d 100644 --- a/client/components/paypalPayments/savePayment/html/src/app.js +++ b/client/components/paypalPayments/savePayment/html/src/app.js @@ -1,3 +1,10 @@ +/** + * Initializes the PayPal Web SDK, determines eligible payment methods for saving a payment, + * and sets up the PayPal button if eligible. + * @async + * @function + * @returns {Promise} + */ async function onPayPalWebSdkLoaded() { try { const clientToken = await getBrowserSafeClientToken(); @@ -20,6 +27,13 @@ async function onPayPalWebSdkLoaded() { } } +/** + * Options object for PayPal save payment session event handlers. + * @typedef {Object} PaymentSessionOptions + * @property {function(Object): Promise} onApprove - Called when the save payment is approved. + * @property {function(Object): void} onCancel - Called when the save payment is cancelled. + * @property {function(Error): void} onError - Called when an error occurs. + */ const paymentSessionOptions = { async onApprove(data) { console.log("onApprove", data); @@ -36,6 +50,13 @@ const paymentSessionOptions = { }, }; +/** + * Sets up the PayPal button for saving a payment method and handles session events. + * @async + * @function + * @param {Object} sdkInstance - The PayPal SDK instance. + * @returns {Promise} + */ async function setupPayPalButton(sdkInstance) { const paypalPaymentSession = sdkInstance.createPayPalSavePaymentSession( paymentSessionOptions, @@ -56,6 +77,12 @@ async function setupPayPalButton(sdkInstance) { }); } +/** + * Fetches a browser-safe client token from the server for PayPal SDK initialization. + * @async + * @function + * @returns {Promise} The browser-safe client access token. + */ async function getBrowserSafeClientToken() { const response = await fetch("/paypal-api/auth/browser-safe-client-token", { method: "GET", @@ -68,6 +95,12 @@ async function getBrowserSafeClientToken() { return accessToken; } +/** + * Creates a PayPal setup token by sending a request to the server. + * @async + * @function + * @returns {Promise} The created setup token object. + */ async function createSetupToken() { const response = await fetch("/paypal-api/vault/setup-token/create", { method: "POST", @@ -80,6 +113,13 @@ async function createSetupToken() { return { setupToken: id }; } +/** + * Creates a PayPal payment token using the provided vault setup token. + * @async + * @function + * @param {string} vaultSetupToken - The vault setup token. + * @returns {Promise} The created payment token response data. + */ async function createPaymentToken(vaultSetupToken) { const response = await fetch("/paypal-api/vault/payment-token/create", { method: "POST", diff --git a/client/components/venmoPayments/oneTimePayment/html/src/app.js b/client/components/venmoPayments/oneTimePayment/html/src/app.js index e896054..ba36f1b 100644 --- a/client/components/venmoPayments/oneTimePayment/html/src/app.js +++ b/client/components/venmoPayments/oneTimePayment/html/src/app.js @@ -1,3 +1,10 @@ +/** + * Initializes the PayPal Web SDK, determines if Venmo is eligible, + * and sets up the Venmo button if eligible. + * @async + * @function + * @returns {Promise} + */ async function onPayPalWebSdkLoaded() { try { const clientToken = await getBrowserSafeClientToken(); @@ -19,6 +26,13 @@ async function onPayPalWebSdkLoaded() { } } +/** + * Options object for Venmo payment session event handlers. + * @typedef {Object} PaymentSessionOptions + * @property {function(Object): Promise} onApprove - Called when the payment is approved. + * @property {function(Object): void} onCancel - Called when the payment is cancelled. + * @property {function(Error): void} onError - Called when an error occurs. + */ const paymentSessionOptions = { async onApprove(data) { console.log("onApprove", data); @@ -35,6 +49,13 @@ const paymentSessionOptions = { }, }; +/** + * Sets up the Venmo button and handles payment session events. + * @async + * @function + * @param {Object} sdkInstance - The PayPal SDK instance. + * @returns {Promise} + */ async function setupVenmoButton(sdkInstance) { const venmoPaymentSession = sdkInstance.createVenmoOneTimePaymentSession( paymentSessionOptions, @@ -54,6 +75,12 @@ async function setupVenmoButton(sdkInstance) { }); } +/** + * Fetches a browser-safe client token from the server for PayPal SDK initialization. + * @async + * @function + * @returns {Promise} The browser-safe client access token. + */ async function getBrowserSafeClientToken() { const response = await fetch("/paypal-api/auth/browser-safe-client-token", { method: "GET", @@ -66,6 +93,12 @@ async function getBrowserSafeClientToken() { return accessToken; } +/** + * Creates a PayPal order by sending a request to the server. + * @async + * @function + * @returns {Promise} The created order object containing the order ID. + */ async function createOrder() { const response = await fetch( "/paypal-api/checkout/orders/create-with-sample-data", @@ -81,6 +114,14 @@ async function createOrder() { return { orderId: id }; } +/** + * 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. + */ async function captureOrder({ orderId }) { const response = await fetch( `/paypal-api/checkout/orders/${orderId}/capture`, diff --git a/client/prebuiltPages/react/oneTimePayment/src/components/PayPalButton.tsx b/client/prebuiltPages/react/oneTimePayment/src/components/PayPalButton.tsx index 3fbf75f..39b5739 100644 --- a/client/prebuiltPages/react/oneTimePayment/src/components/PayPalButton.tsx +++ b/client/prebuiltPages/react/oneTimePayment/src/components/PayPalButton.tsx @@ -4,6 +4,12 @@ import { createOrder } from "../utils"; import { PaymentSessionOptions, SessionOutput } from "../types/paypal"; import { useErrorBoundary } from "react-error-boundary"; +/** + * PayPalButton component renders a PayPal button and manages the PayPal payment session. + * + * @param {PaymentSessionOptions} paymentSessionOptions - The options for the PayPal payment session, including event handlers. + * @returns {JSX.Element} The rendered PayPal button component. + */ const PayPalButton: React.FC = ( paymentSessionOptions, ) => { @@ -19,6 +25,10 @@ const PayPalButton: React.FC = ( } }, [sdkInstance, paymentSessionOptions]); + /** + * Handles the PayPal button click event, starts the payment session, + * and triggers error boundaries on failure. + */ const payPalOnClickHandler = async () => { if (!paypalSession.current) return; diff --git a/client/prebuiltPages/react/oneTimePayment/src/components/PaymentModal.tsx b/client/prebuiltPages/react/oneTimePayment/src/components/PaymentModal.tsx index 335ab57..7843b50 100644 --- a/client/prebuiltPages/react/oneTimePayment/src/components/PaymentModal.tsx +++ b/client/prebuiltPages/react/oneTimePayment/src/components/PaymentModal.tsx @@ -1,15 +1,31 @@ import React from "react"; +/** + * Interface for the content displayed in the modal. + */ interface ModalContent { + /** The modal title text. */ title: string; + /** The modal message text. */ message: string; } +/** + * Props for the PaymentModal component. + */ interface PaymentModalProps { + /** Content to display in the modal. */ content: ModalContent; + /** Callback fired when the modal is closed. */ onClose: () => void; } +/** + * PaymentModal component displays a modal dialog with a title, message, and close button. + * + * @param {PaymentModalProps} props - The props for the PaymentModal component. + * @returns {JSX.Element} The rendered modal component. + */ const PaymentModal: React.FC = ({ content, onClose }) => { return (
= ({ 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, ) {