Skip to content

Commit d9cb28c

Browse files
Adding redirect flow (#50)
* Adding redirect flow * Addressed review comments, fixed formatting * short format * prettier * fix for uncheck redirect * Rebasing with origin- custom to advanced * prettier issues * prettier issues 2 * bump prettier version * fix formatting issue * custom -> advanced * format * format --------- Co-authored-by: Nate Bierdeman <nbierdeman@paypal.com>
1 parent e60e02a commit d9cb28c

File tree

7 files changed

+177
-14
lines changed

7 files changed

+177
-14
lines changed

client/components/paypalPayments/oneTimePayment/html/README.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@ npm start
1414

1515
### Sample Integrations
1616

17-
| Sample Integration | Description |
18-
| --------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
19-
| [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. |
20-
| [Custom Payment Handler](src/custom/paymentHandler/index.html) | This custom integration uses the experimental "payment-handler" presentation mode. It teaches how to control the fallback logic for presentation modes based on what the browser supports. |
21-
| [Custom Sandboxed Iframe](src/custom/sandboxedIframe/README.md) | This custom integration demonstrates how a merchant can wrap the v6 SDK integration code into their own iframe and what values need to be passed to the [iframe sandbox attribute](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/iframe#sandbox). It does require two web servers to demonstrate the use case. Refer to the README in the src/custom/sandboxedIframe directory to learn more. |
17+
| Sample Integration | Description |
18+
| ----------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
19+
| [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. |
20+
| [Custom Payment Handler](src/advanced/paymentHandler/index.html) | This custom integration uses the experimental "payment-handler" presentation mode. It teaches how to control the fallback logic for presentation modes based on what the browser supports. |
21+
| [Custom Sandboxed Iframe](src/advanced/sandboxedIframe/README.md) | This custom integration demonstrates how a merchant can wrap the v6 SDK integration code into their own iframe and what values need to be passed to the [iframe sandbox attribute](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/iframe#sandbox). It does require two web servers to demonstrate the use case. Refer to the README in the src/advanced/sandboxedIframe directory to learn more. |

client/components/paypalPayments/oneTimePayment/html/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
},
1414
"license": "Apache-2.0",
1515
"devDependencies": {
16-
"prettier": "^3.5.3",
16+
"prettier": "^3.6.2",
1717
"vite": "^6.2.0"
1818
}
1919
}
Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
async function onPayPalLoaded() {
2+
try {
3+
const clientToken = await getBrowserSafeClientToken();
4+
const sdkInstance = await window.paypal.createInstance({
5+
clientToken,
6+
components: ["paypal-payments"],
7+
pageType: "checkout",
8+
});
9+
10+
setupPayPalButton(sdkInstance);
11+
} catch (error) {
12+
console.error(error);
13+
}
14+
}
15+
16+
const paymentSessionOptions = {
17+
async onApprove(data) {
18+
console.log("onApprove", data);
19+
const orderData = await captureOrder({
20+
orderId: data.orderId,
21+
});
22+
console.log("Capture result", orderData);
23+
},
24+
onCancel(data) {
25+
console.log("onCancel", data);
26+
},
27+
onError(error) {
28+
console.log("onError", error);
29+
},
30+
};
31+
32+
async function setupPayPalButton(sdkInstance) {
33+
const paypalPaymentSession = sdkInstance.createPayPalOneTimePaymentSession(
34+
paymentSessionOptions,
35+
);
36+
37+
const enableAutoRedirect = document.querySelector("#enable-auto-redirect");
38+
const paypalButton = document.querySelector("#paypal-button");
39+
paypalButton.removeAttribute("hidden");
40+
41+
paypalButton.addEventListener("click", async () => {
42+
const createOrderPromiseReference = createRedirectOrder();
43+
44+
try {
45+
const { redirectURL } = await paypalPaymentSession.start(
46+
{
47+
presentationMode: "redirect",
48+
autoRedirect: {
49+
enabled: enableAutoRedirect.checked,
50+
},
51+
},
52+
createOrderPromiseReference,
53+
);
54+
if (redirectURL) {
55+
console.log(`redirectURL: ${redirectURL}`);
56+
window.location.assign(redirectURL);
57+
}
58+
} catch (error) {
59+
console.error(error);
60+
}
61+
});
62+
}
63+
64+
async function getBrowserSafeClientToken() {
65+
const response = await fetch("/paypal-api/auth/browser-safe-client-token", {
66+
method: "GET",
67+
headers: {
68+
"Content-Type": "application/json",
69+
},
70+
});
71+
const { accessToken } = await response.json();
72+
73+
return accessToken;
74+
}
75+
76+
async function createRedirectOrder() {
77+
const returnUrl = new URL(window.location);
78+
returnUrl.searchParams.set("flowState", "approve");
79+
80+
const cancelUrl = new URL(window.location);
81+
cancelUrl.searchParams.set("flowState", "cancel");
82+
83+
const orderPayload = {
84+
intent: "CAPTURE",
85+
paymentSource: {
86+
paypal: {
87+
experienceContext: {
88+
shippingPreference: "NO_SHIPPING",
89+
userAction: "CONTINUE",
90+
returnUrl,
91+
cancelUrl,
92+
},
93+
},
94+
},
95+
purchaseUnits: [
96+
{
97+
amount: {
98+
currencyCode: "USD",
99+
value: "10.00",
100+
breakdown: {
101+
itemTotal: {
102+
currencyCode: "USD",
103+
value: "10.00",
104+
},
105+
},
106+
},
107+
},
108+
],
109+
};
110+
111+
const response = await fetch("/paypal-api/checkout/orders/create", {
112+
method: "POST",
113+
headers: {
114+
"Content-Type": "application/json",
115+
},
116+
body: JSON.stringify(orderPayload),
117+
});
118+
const { id } = await response.json();
119+
return { orderId: id };
120+
}
121+
122+
async function captureOrder({ orderId }) {
123+
const response = await fetch(
124+
`/paypal-api/checkout/orders/${orderId}/capture`,
125+
{
126+
method: "POST",
127+
headers: {
128+
"Content-Type": "application/json",
129+
},
130+
},
131+
);
132+
const data = await response.json();
133+
return data;
134+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<html lang="en">
2+
<head>
3+
<meta charset="UTF-8" />
4+
<title>One-Time Payment - Redirect Flow - PayPal Web SDK</title>
5+
<meta name="viewport" content="width=device-width, initial-scale=1" />
6+
</head>
7+
8+
<body>
9+
<h1>Paypal Redirect Flow</h1>
10+
<div>
11+
<input type="checkbox" id="enable-auto-redirect" checked />
12+
<label for="enable-auto-redirect"> Enable auto-redirect </label>
13+
</div>
14+
<div id="button-container">
15+
<paypal-button id="paypal-button" hidden></paypal-button>
16+
</div>
17+
18+
<script src="app.js"></script>
19+
<script
20+
async
21+
onload="onPayPalLoaded()"
22+
src="https://www.sandbox.paypal.com/web-sdk/v6/core"
23+
></script>
24+
</body>
25+
</html>

client/components/paypalPayments/oneTimePayment/html/src/advanced/sandboxedIframe/README.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ to work entirely in an iframe.
77
To start this example:
88

99
1. Start a server in the `server/` directory. Note, the server needs to provide the following endpoints:
10-
1110
1. `GET /paypal-api/auth/browser-safe-client-token`
1211
2. `POST /paypal-api/checkout/orders/create-with-sample-data`
1312
3. `POST /paypal-api/checkout/orders/:orderId/capture`

client/components/paypalPayments/oneTimePayment/html/src/index.html

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,13 @@ <h1>One-Time Payment Integrations</h1>
1616
>
1717
</li>
1818
<li>
19-
<a href="/custom/paymentHandler/index.html"
20-
>Custom "payment-handler" presentation mode with PayPal button</a
19+
<a href="/advanced/paymentHandler/index.html"
20+
>Advanced "payment-handler" presentation mode with PayPal button</a
21+
>
22+
</li>
23+
<li>
24+
<a href="/advanced/redirect/index.html"
25+
>Advanced Redirect flow with PayPal button</a
2126
>
2227
</li>
2328
</ul>

client/components/venmoPayments/oneTimePayment/html/README.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@ npm start
1414

1515
### Sample Integrations
1616

17-
| Sample Integration | Description |
18-
| --------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
19-
| [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. |
20-
| [Custom Payment Handler](src/custom/paymentHandler/index.html) | This custom integration uses the experimental "payment-handler" presentation mode. It teaches how to control the fallback logic for presentation modes based on what the browser supports. |
21-
| [Custom Sandboxed Iframe](src/custom/sandboxedIframe/README.md) | This custom integration demonstrates how a merchant can wrap the v6 SDK integration code into their own iframe and what values need to be passed to the [iframe sandbox attribute](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/iframe#sandbox). It does require two web servers to demonstrate the use case. Refer to the README in the src/custom/sandboxedIframe directory to learn more. |
17+
| Sample Integration | Description |
18+
| ------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
19+
| [Recommended](../../../paypalPayments/oneTimePayment/html/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. |
20+
| [Custom Payment Handler](../../../paypalPayments/oneTimePayment/html/src/advanced/paymentHandler/index.html) | This custom integration uses the experimental "payment-handler" presentation mode. It teaches how to control the fallback logic for presentation modes based on what the browser supports. |
21+
| [Custom Sandboxed Iframe](../../../paypalPayments/oneTimePayment/html/src/advanced/sandboxedIframe/README.md) | This custom integration demonstrates how a merchant can wrap the v6 SDK integration code into their own iframe and what values need to be passed to the [iframe sandbox attribute](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/iframe#sandbox). It does require two web servers to demonstrate the use case. Refer to the README in the ../../../paypalPayments/oneTimePayment/html/src/advanced/sandboxedIframe directory to learn more. |

0 commit comments

Comments
 (0)