From 04def7820d3d169b0e1eb6565b24f53bcac01d6d Mon Sep 17 00:00:00 2001 From: Mervin Choun Date: Thu, 7 Aug 2025 16:19:11 -0400 Subject: [PATCH 1/3] card fields one time payment initial commit --- .../cardFields/oneTimePayment/html/README.md | 19 +++ .../oneTimePayment/html/package.json | 19 +++ .../oneTimePayment/html/src/index.html | 19 +++ .../html/src/recommended/app.js | 125 ++++++++++++++++++ .../html/src/recommended/index.html | 32 +++++ .../oneTimePayment/html/vite.config.js | 17 +++ 6 files changed, 231 insertions(+) create mode 100644 client/components/cardFields/oneTimePayment/html/README.md create mode 100644 client/components/cardFields/oneTimePayment/html/package.json create mode 100644 client/components/cardFields/oneTimePayment/html/src/index.html create mode 100644 client/components/cardFields/oneTimePayment/html/src/recommended/app.js create mode 100644 client/components/cardFields/oneTimePayment/html/src/recommended/index.html create mode 100644 client/components/cardFields/oneTimePayment/html/vite.config.js diff --git a/client/components/cardFields/oneTimePayment/html/README.md b/client/components/cardFields/oneTimePayment/html/README.md new file mode 100644 index 00000000..ecef219a --- /dev/null +++ b/client/components/cardFields/oneTimePayment/html/README.md @@ -0,0 +1,19 @@ +# One-Time Payments HTML Sample Integration + +This HTML sample integration uses HTML, JavaScript, and CSS. It does not require a build process to transpile the source code. It's just static files that can be served up by any web server. [Vite](https://vite.dev/) is used for the local web server to provide the following functionality: + +1. Serve up the static HTML and JavaScript files. +2. Proxy the API server so both the client and server are running on port 3000. + +## How to Run Locally + +```bash +npm install +npm start +``` + +### Sample Integrations + +| Sample Integration | Description | +| ----------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| [Recommended](src/recommended/index.html) | Start with this recommended sample integration. It displays all buttons supported by the v6 SDK and includes eligibility logic. It uses the "auto" presentation mode which attempts to launch a popup window and then automatically falls back to the modal presentation mode when the browser does not support popups. | diff --git a/client/components/cardFields/oneTimePayment/html/package.json b/client/components/cardFields/oneTimePayment/html/package.json new file mode 100644 index 00000000..755202c1 --- /dev/null +++ b/client/components/cardFields/oneTimePayment/html/package.json @@ -0,0 +1,19 @@ +{ + "name": "v6-web-sdk-sample-integration-client-html", + "version": "1.0.0", + "private": true, + "type": "module", + "scripts": { + "build": "vite build", + "preview": "vite preview", + "start": "vite", + "format": "prettier . --write", + "format:check": "prettier . --check", + "lint": "echo \"eslint is not set up\"" + }, + "license": "Apache-2.0", + "devDependencies": { + "prettier": "^3.6.2", + "vite": "^7.0.4" + } +} diff --git a/client/components/cardFields/oneTimePayment/html/src/index.html b/client/components/cardFields/oneTimePayment/html/src/index.html new file mode 100644 index 00000000..ee97364c --- /dev/null +++ b/client/components/cardFields/oneTimePayment/html/src/index.html @@ -0,0 +1,19 @@ + + + + + One-Time Payment Sample Integrations - PayPal Web SDK + + + +

One-Time Payment Integrations

+ + + + diff --git a/client/components/cardFields/oneTimePayment/html/src/recommended/app.js b/client/components/cardFields/oneTimePayment/html/src/recommended/app.js new file mode 100644 index 00000000..0d748ffa --- /dev/null +++ b/client/components/cardFields/oneTimePayment/html/src/recommended/app.js @@ -0,0 +1,125 @@ +async function onPayPalWebSdkLoaded() { + try { + const clientToken = await getBrowserSafeClientToken(); + const sdkInstance = await window.paypal.createInstance({ + clientToken, + components: ["card-fields"], + pageType: "checkout", + }); + + // const paymentMethods = await sdkInstance.findEligibleMethods({ + // currencyCode: "USD", + // }); + + // NOTE: Eligibility does not currently return card + // if (paymentMethods.isEligible("card")) { + // setupCardFields(sdkInstance); + // } + setupCardFields(sdkInstance); + } catch (error) { + console.error(error); + } +} + +async function setupCardFields(sdkInstance) { + const cardFieldsInstance = + sdkInstance.createCardFieldsOneTimePaymentSession(); + + const numberField = cardFieldsInstance.createCardFieldsComponent({ + type: "number", + placeholder: "Enter a number:", + ariaDescription: "card-number-field", + ariaLabel: "some-values", + style: { + input: { + color: "green", + }, + }, + // SDK to take care of aria-invalid when the value is invalid on Change + }); + const cvvField = cardFieldsInstance.createCardFieldsComponent({ + type: "cvv", + placeholder: "Enter CVV:", + }); + const expiryField = cardFieldsInstance.createCardFieldsComponent({ + type: "expiry", + placeholder: "Enter Expiry:", + }); + + document.querySelector("#paypal-card-fields-number").appendChild(numberField); + document.querySelector("#paypal-card-fields-cvv").appendChild(cvvField); + document.querySelector("#paypal-card-fields-expiry").appendChild(expiryField); + + const payButton = document.querySelector("#save-payment-method-button"); + payButton.addEventListener("click", async () => { + try { + const orderId = await createOrder(); + const { data, state } = await cardFieldsInstance.submit(orderId, { + billingAddress: { + postalCode: "95131", + }, + }); + + switch (state) { + case "succeeded": { + const { orderId, ...liabilityShift } = data; + const orderData = await captureOrder({ + orderId: data.orderId, + headers: { "X-CSRF-TOKEN": "<%= csrfToken %>" }, + }); + } + case "canceled": { + // specifically for if buyer cancels 3DS modal + const { orderId } = data; + } + case "failed": { + const { orderId, message } = data; + } + } + } catch (error) { + console.error(error); + } + }); +} + +async function getBrowserSafeClientToken() { + 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; +} + +async function createOrder() { + const response = await fetch( + "/paypal-api/checkout/orders/create-with-sample-data", + { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + }, + ); + const { id } = await response.json(); + + return { orderId: id }; +} + +async function captureOrder({ orderId }) { + const response = await fetch( + `/paypal-api/checkout/orders/${orderId}/capture`, + { + method: "POST", + headers: { + "Content-Type": "application/json", + }, + }, + ); + const data = await response.json(); + + return data; +} diff --git a/client/components/cardFields/oneTimePayment/html/src/recommended/index.html b/client/components/cardFields/oneTimePayment/html/src/recommended/index.html new file mode 100644 index 00000000..c8d3a13f --- /dev/null +++ b/client/components/cardFields/oneTimePayment/html/src/recommended/index.html @@ -0,0 +1,32 @@ + + + + + One-Time Payment - Recommended Integration - PayPal Web SDK + + + + +

One-Time Payment Recommended Integration - Card Fields

+ +
+
+
+
+
+ + + + + + diff --git a/client/components/cardFields/oneTimePayment/html/vite.config.js b/client/components/cardFields/oneTimePayment/html/vite.config.js new file mode 100644 index 00000000..cc128a59 --- /dev/null +++ b/client/components/cardFields/oneTimePayment/html/vite.config.js @@ -0,0 +1,17 @@ +import { defineConfig } from "vite"; + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [], + root: "src", + server: { + port: 3000, + proxy: { + "/paypal-api": { + target: "http://localhost:8080", + changeOrigin: true, + secure: false, + }, + }, + }, +}); From 400f6a5d72471fddb72c40f228bc4ce257257b78 Mon Sep 17 00:00:00 2001 From: Mervin Choun Date: Fri, 8 Aug 2025 13:40:35 -0400 Subject: [PATCH 2/3] cardfields styling --- .../cardFields/oneTimePayment/html/src/recommended/index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/components/cardFields/oneTimePayment/html/src/recommended/index.html b/client/components/cardFields/oneTimePayment/html/src/recommended/index.html index c8d3a13f..16631aa2 100644 --- a/client/components/cardFields/oneTimePayment/html/src/recommended/index.html +++ b/client/components/cardFields/oneTimePayment/html/src/recommended/index.html @@ -5,7 +5,7 @@ One-Time Payment - Recommended Integration - PayPal Web SDK + + + +

Save Payment Recommended Integration - Card Fields

+ +
+
+
+
+
+ + + + + + diff --git a/client/components/cardFields/savePayment/html/vite.config.js b/client/components/cardFields/savePayment/html/vite.config.js new file mode 100644 index 00000000..cc128a59 --- /dev/null +++ b/client/components/cardFields/savePayment/html/vite.config.js @@ -0,0 +1,17 @@ +import { defineConfig } from "vite"; + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [], + root: "src", + server: { + port: 3000, + proxy: { + "/paypal-api": { + target: "http://localhost:8080", + changeOrigin: true, + secure: false, + }, + }, + }, +});