Skip to content

Commit fe0d689

Browse files
authored
Use a new client/server folder structure (#70)
1 parent 1026de2 commit fe0d689

File tree

10 files changed

+122
-125
lines changed

10 files changed

+122
-125
lines changed

advanced-integration/package.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,12 @@
22
"name": "paypal-advanced-integration",
33
"description": "Sample Node.js web app to integrate PayPal Advanced Checkout for online payments",
44
"version": "1.0.0",
5-
"main": "server.js",
5+
"main": "server/server.js",
66
"type": "module",
77
"scripts": {
88
"test": "echo \"Error: no test specified\" && exit 1",
9-
"start": "node server.js"
9+
"start": "node server/server.js",
10+
"format": "npx prettier --write **.js"
1011
},
1112
"license": "Apache-2.0",
1213
"dependencies": {

advanced-integration/server.js renamed to advanced-integration/server/server.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
import express from "express";
22
import fetch from "node-fetch";
33
import "dotenv/config";
4-
import path from "path";
54

65
const { PAYPAL_CLIENT_ID, PAYPAL_CLIENT_SECRET, PORT = 8888 } = process.env;
76
const base = "https://api-m.sandbox.paypal.com";
87
const app = express();
98
app.set("view engine", "ejs");
10-
app.use(express.static("public"));
9+
app.set("views", "./server/views");
10+
app.use(express.static("client"));
1111

1212
// parse post params sent in body in json format
1313
app.use(express.json());

standard-integration/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ This folder contains example code for a Standard PayPal integration using both t
66

77
1. [Create an application](https://developer.paypal.com/dashboard/applications/sandbox/create)
88
2. Rename `.env.example` to `.env` and update `PAYPAL_CLIENT_ID` and `PAYPAL_CLIENT_SECRET`
9-
3. Replace `test` in `index.html` with your app's client-id
9+
3. Replace `test` in `client/index.html` with your app's client-id
1010
4. Run `npm install`
1111
5. Run `npm start`
1212
6. Open http://localhost:8888

standard-integration/client/app.js

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
window.paypal
2+
.Buttons({
3+
createOrder: async () => {
4+
try {
5+
const response = await fetch("/api/orders", {
6+
method: "POST",
7+
headers: {
8+
"Content-Type": "application/json",
9+
},
10+
// use the "body" param to optionally pass additional order information
11+
// like product ids and quantities
12+
body: JSON.stringify({
13+
cart: [
14+
{
15+
id: "YOUR_PRODUCT_ID",
16+
quantity: "YOUR_PRODUCT_QUANTITY",
17+
},
18+
],
19+
}),
20+
});
21+
22+
const orderData = await response.json();
23+
24+
if (orderData.id) {
25+
return orderData.id;
26+
} else {
27+
const errorDetail = orderData?.details?.[0];
28+
const errorMessage = errorDetail
29+
? `${errorDetail.issue} ${errorDetail.description} (${orderData.debug_id})`
30+
: JSON.stringify(orderData);
31+
32+
throw new Error(errorMessage);
33+
}
34+
} catch (error) {
35+
console.error(error);
36+
resultMessage(`Could not initiate PayPal Checkout...<br><br>${error}`);
37+
}
38+
},
39+
onApprove: async (data, actions) => {
40+
try {
41+
const response = await fetch(`/api/orders/${data.orderID}/capture`, {
42+
method: "POST",
43+
headers: {
44+
"Content-Type": "application/json",
45+
},
46+
});
47+
48+
const orderData = await response.json();
49+
// Three cases to handle:
50+
// (1) Recoverable INSTRUMENT_DECLINED -> call actions.restart()
51+
// (2) Other non-recoverable errors -> Show a failure message
52+
// (3) Successful transaction -> Show confirmation or thank you message
53+
54+
const errorDetail = orderData?.details?.[0];
55+
56+
if (errorDetail?.issue === "INSTRUMENT_DECLINED") {
57+
// (1) Recoverable INSTRUMENT_DECLINED -> call actions.restart()
58+
// recoverable state, per https://developer.paypal.com/docs/checkout/standard/customize/handle-funding-failures/
59+
return actions.restart();
60+
} else if (errorDetail) {
61+
// (2) Other non-recoverable errors -> Show a failure message
62+
throw new Error(`${errorDetail.description} (${orderData.debug_id})`);
63+
} else if (!orderData.purchase_units) {
64+
throw new Error(JSON.stringify(orderData));
65+
} else {
66+
// (3) Successful transaction -> Show confirmation or thank you message
67+
// Or go to another URL: actions.redirect('thank_you.html');
68+
const transaction =
69+
orderData?.purchase_units?.[0]?.payments?.captures?.[0] ||
70+
orderData?.purchase_units?.[0]?.payments?.authorizations?.[0];
71+
resultMessage(
72+
`Transaction ${transaction.status}: ${transaction.id}<br><br>See console for all available details`,
73+
);
74+
console.log(
75+
"Capture result",
76+
orderData,
77+
JSON.stringify(orderData, null, 2),
78+
);
79+
}
80+
} catch (error) {
81+
console.error(error);
82+
resultMessage(
83+
`Sorry, your transaction could not be processed...<br><br>${error}`,
84+
);
85+
}
86+
},
87+
})
88+
.render("#paypal-button-container");
89+
90+
// Example function to show a result to the user. Your site's UI library can be used instead.
91+
function resultMessage(message) {
92+
const container = document.querySelector("#result-message");
93+
container.innerHTML = message;
94+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8">
5+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
6+
<title>PayPal JS SDK Standard Integration</title>
7+
</head>
8+
<body>
9+
<div id="paypal-button-container"></div>
10+
<p id="result-message"></p>
11+
<!-- Replace the "test" client-id value with your client-id -->
12+
<script src="https://www.paypal.com/sdk/js?client-id=test&currency=USD"></script>
13+
<script src="app.js"></script>
14+
</body>
15+
</html>

standard-integration/index.html

Lines changed: 0 additions & 117 deletions
This file was deleted.

standard-integration/package.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,12 @@
22
"name": "paypal-standard-integration",
33
"description": "Sample Node.js web app to integrate PayPal Standard Checkout for online payments",
44
"version": "1.0.0",
5-
"main": "server.js",
5+
"main": "server/server.js",
66
"type": "module",
77
"scripts": {
88
"test": "echo \"Error: no test specified\" && exit 1",
9-
"start": "node server.js"
9+
"start": "node server/server.js",
10+
"format": "npx prettier --write **.js"
1011
},
1112
"license": "Apache-2.0",
1213
"dependencies": {

standard-integration/server.js renamed to standard-integration/server/server.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@ const { PAYPAL_CLIENT_ID, PAYPAL_CLIENT_SECRET, PORT = 8888 } = process.env;
77
const base = "https://api-m.sandbox.paypal.com";
88
const app = express();
99

10+
// host static files
11+
app.use(express.static("client"));
12+
1013
// parse post params sent in body in json format
1114
app.use(express.json());
1215

@@ -141,7 +144,7 @@ app.post("/api/orders/:orderID/capture", async (req, res) => {
141144

142145
// serve index.html
143146
app.get("/", (req, res) => {
144-
res.sendFile(path.resolve("./index.html"));
147+
res.sendFile(path.resolve("./client/checkout.html"));
145148
});
146149

147150
app.listen(PORT, () => {

0 commit comments

Comments
 (0)