Skip to content

Commit bebb975

Browse files
authored
Adding ejs support and codespaces (#4)
1 parent a8c9563 commit bebb975

File tree

6 files changed

+113
-27
lines changed

6 files changed

+113
-27
lines changed

README.md

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,19 @@ and configuring your .env config file with your Paypal ClientId and ClientSecret
2626
3. Run `npm run dev`
2727
4. Navigate to `http://localhost:8080/`
2828

29-
### PayPal Codespaces Links
29+
## PayPal Codespaces
30+
31+
PayPal codespaces require a client ID and client secret for your app.
32+
33+
### Link to codespaces
34+
3035
[![Open in GitHub Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/paypal-examples/p24)
3136

37+
### Learn more
38+
39+
You can read more about codespaces in the [PayPal Developer Docs](https://developer.paypal.com/api/rest/sandbox/codespaces).
40+
41+
### Feedback
42+
43+
* To report a bug or suggest a new feature, create an [issue in GitHub](https://github.com/paypal-examples/paypaldevsupport/issues/new/choose).
44+
* To submit feedback, go to [GitHub Codespaces](https://developer.paypal.com/api/rest/sandbox/codespaces) and select the "Feedback" tab.

client/index.js renamed to client/public/index.js

Lines changed: 54 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,5 @@
11
/* eslint-disable no-alert, no-unused-vars */
22

3-
var order = {
4-
purchase_units: [
5-
{
6-
amount: {
7-
currency_code: "EUR",
8-
value: "99.99",
9-
},
10-
},
11-
]
12-
};
13-
143
/* Paypal */
154
paypal
165
.Marks({
@@ -25,13 +14,41 @@ paypal
2514
label: "pay",
2615
color: "silver",
2716
},
28-
createOrder(data, actions) {
29-
return actions.order.create(order);
17+
createOrder() {
18+
return fetch("/api/orders", {
19+
method: "POST",
20+
headers: {
21+
"Content-Type": "application/json",
22+
},
23+
// use the "body" param to optionally pass additional order information
24+
// like product skus and quantities
25+
body: JSON.stringify({
26+
cart: [
27+
{
28+
sku: "YOUR_PRODUCT_STOCK_KEEPING_UNIT",
29+
quantity: "YOUR_PRODUCT_QUANTITY",
30+
},
31+
],
32+
}),
33+
})
34+
.then((response) => response.json())
35+
.then((order) => order.id);
3036
},
3137
onApprove(data, actions) {
32-
return actions.order.capture().then(function (details) {
33-
alert(`Transaction completed by ${details.payer.name.given_name}!`);
34-
});
38+
return fetch(`/api/orders/${data.orderID}/capture`, {
39+
method: "post",
40+
})
41+
.then((res) => res.json())
42+
.then((data) => {
43+
swal(
44+
"Order Captured!",
45+
`Id: ${data.id}, ${Object.keys(data.payment_source)[0]}, ${
46+
data.purchase_units[0].payments.captures[0].amount.currency_code
47+
} ${data.purchase_units[0].payments.captures[0].amount.value}`,
48+
"success"
49+
);
50+
})
51+
.catch(console.error);
3552
},
3653
})
3754
.render("#paypal-btn");
@@ -60,11 +77,28 @@ paypal.Buttons({
6077
style: {
6178
label: "pay",
6279
},
63-
createOrder(data, actions) {
64-
return actions.order.create(order);
80+
createOrder() {
81+
return fetch("/api/orders", {
82+
method: "POST",
83+
headers: {
84+
"Content-Type": "application/json",
85+
},
86+
// use the "body" param to optionally pass additional order information
87+
// like product skus and quantities
88+
body: JSON.stringify({
89+
cart: [
90+
{
91+
sku: "YOUR_PRODUCT_STOCK_KEEPING_UNIT",
92+
quantity: "YOUR_PRODUCT_QUANTITY",
93+
},
94+
],
95+
}),
96+
})
97+
.then((response) => response.json())
98+
.then((order) => order.id);
6599
},
66-
onApprove(data, actions) {
67-
fetch(`/capture/${data.orderID}`, {
100+
onApprove(data) {
101+
return fetch(`/api/orders/${data.orderID}/capture`, {
68102
method: "post",
69103
})
70104
.then((res) => res.json())
File renamed without changes.

client/index.html renamed to client/views/index.ejs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@
3636
<div id="paypal-btn"></div>
3737
<div id="p24-btn"></div>
3838

39-
<script src="https://www.paypal.com/sdk/js?client-id=AfPbdUbV4LJdK0-0B0QPeUyHnzGgVhIwZfBO3wYRoazaSYRJAIKwwHnfI0EbekJB42FJuVi-3-vgsQvi&components=buttons,payment-fields,marks,funding-eligibility&enable-funding=p24&currency=EUR"></script>
39+
<script src="https://www.paypal.com/sdk/js?client-id=<%= clientId %>&components=buttons,payment-fields,marks,funding-eligibility&enable-funding=p24&currency=EUR"></script>
4040

4141
<script src="./index.js"></script>
4242

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
"dependencies": {
1313
"axios": "^0.21.1",
1414
"dotenv": "^8.2.0",
15+
"ejs": "^3.1.9",
1516
"express": "^4.17.1"
1617
},
1718
"devDependencies": {

server/index.js

Lines changed: 43 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,53 @@ const { getAccessToken } = require("./oauth");
1010
const { WEBHOOK_ID, PORT, PAYPAL_API_BASE } = require("./config");
1111

1212
const app = express();
13-
14-
app.use(express.static(resolve(__dirname, "../client")));
13+
app.set("view engine", "ejs");
14+
app.set('views', resolve(__dirname, "../client/views"));
15+
app.use(express.static(resolve(__dirname, "../client/public")));
1516
app.use(express.json());
1617

1718
app.get("/", (req, res) => {
18-
res.sendFile(resolve(__dirname, "../client/index.html"));
19+
const clientId = process.env.CLIENT_ID;
20+
const clientSecret = process.env.CLIENT_SECRET;
21+
if(!clientId || !clientSecret) {
22+
res.status(500).send('Client ID and/or Client Secret is missing');
23+
} else {
24+
res.render("index", { clientId });
25+
}
1926
});
2027

21-
app.post("/capture/:orderId", async (req, res) => {
28+
app.post("/api/orders", async (req, res) => {
29+
30+
// use the cart information passed from the front-end to calculate the purchase unit details
31+
const { cart } = req.body;
32+
33+
const { access_token } = await getAccessToken();
34+
const { data } = await axios({
35+
url: `${PAYPAL_API_BASE}/v2/checkout/orders`,
36+
method: "post",
37+
headers: {
38+
"Content-Type": "application/json",
39+
Accept: "application/json",
40+
Authorization: `Bearer ${access_token}`,
41+
},
42+
data: JSON.stringify({
43+
intent: "CAPTURE",
44+
purchase_units: [
45+
{
46+
amount: {
47+
currency_code: "EUR",
48+
value: "99.99",
49+
},
50+
},
51+
]
52+
})
53+
});
54+
55+
console.log(`Order Created!`);
56+
res.json(data);
57+
});
58+
59+
app.post("/api/orders/:orderId/capture", async (req, res) => {
2260
const { orderId } = req.params;
2361

2462
const { access_token } = await getAccessToken();
@@ -106,4 +144,4 @@ app.post("/webhook", async (req, res) => {
106144
app.listen(PORT, async () => {
107145
await open(`http://localhost:${PORT}`);
108146
console.log(`Example app listening at http://localhost:${PORT}`);
109-
});
147+
});

0 commit comments

Comments
 (0)